"use client";

import Link from "next/link";
import { type ReactNode, useCallback, useEffect, useMemo, useState } from "react";
import { Bar, BarChart, CartesianGrid, Cell, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
import { buildDueBuckets, buildSectionHealth, buildStatusDistribution, summaryDelta } from "@/lib/kpis/analytics";
import type { KpiBoardResponse, KpiRowDTO, KpiRowStatus } from "@/lib/kpis/types";

const STATUS_LABELS: Record<KpiRowStatus, string> = {
  on_track: "En ruta",
  watch: "Seguimiento",
  risk: "Riesgo",
  no_score: "Sin score",
};

const STATUS_CLASSNAMES: Record<KpiRowStatus, string> = {
  on_track: "bg-benell-green/20 text-benell-green",
  watch: "bg-benell-amber/25 text-benell-amber",
  risk: "bg-benell-red/20 text-benell-red",
  no_score: "bg-benell-surface-muted text-benell-text-soft",
};

const STATUS_COLORS: Record<KpiRowStatus, string> = {
  on_track: "#2f8f4e",
  watch: "#b98312",
  risk: "#c93a3a",
  no_score: "#9b9b9b",
};

type SortOption = "default" | "compliance_desc" | "compliance_asc" | "responsibility";
type StatusFilter = "all" | KpiRowStatus;
type WeeklyKpiBoardMode = "full" | "owner_summary";

type WeeklyKpiBoardProps = {
  mode?: WeeklyKpiBoardMode;
  middleContent?: ReactNode;
};

function formatDate(isoDate: string | null): string {
  if (!isoDate) {
    return "-";
  }

  const parsed = new Date(`${isoDate}T00:00:00.000Z`);
  return new Intl.DateTimeFormat("es-MX", {
    day: "2-digit",
    month: "short",
    year: "numeric",
    timeZone: "UTC",
  }).format(parsed);
}

function formatDateTime(isoDateTime: string | null | undefined): string {
  if (!isoDateTime) {
    return "Sin actualización";
  }

  const parsed = new Date(isoDateTime);
  return new Intl.DateTimeFormat("es-MX", {
    day: "2-digit",
    month: "short",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
    timeZone: "UTC",
  }).format(parsed);
}

function rowMatchesQuery(row: KpiRowDTO, query: string): boolean {
  if (!query) {
    return true;
  }

  const haystack = [
    row.responsibility,
    row.objectiveIndicator,
    row.quantityQuality,
    row.compliance,
    row.dueCommitment,
  ]
    .filter(Boolean)
    .join(" ")
    .toLowerCase();

  return haystack.includes(query);
}

function sortRows(rows: KpiRowDTO[], sortBy: SortOption): KpiRowDTO[] {
  const list = [...rows];

  if (sortBy === "compliance_desc") {
    list.sort((a, b) => (b.compliancePct ?? -1) - (a.compliancePct ?? -1));
    return list;
  }

  if (sortBy === "compliance_asc") {
    list.sort((a, b) => (a.compliancePct ?? 101) - (b.compliancePct ?? 101));
    return list;
  }

  if (sortBy === "responsibility") {
    list.sort((a, b) => a.responsibility.localeCompare(b.responsibility, "es"));
    return list;
  }

  list.sort((a, b) => a.sortOrder - b.sortOrder);
  return list;
}

function deltaPill(delta: number | null, suffix = "pp") {
  if (delta === null) {
    return <span className="text-caption text-benell-text-soft">Sin semana previa</span>;
  }

  const positive = delta > 0;
  const neutral = delta === 0;
  return (
    <span
      className={`text-caption inline-flex rounded-full px-2 py-1 font-semibold ${
        neutral
          ? "bg-benell-surface-muted text-benell-text-soft"
          : positive
            ? "bg-benell-green/15 text-benell-green"
            : "bg-benell-red/15 text-benell-red"
      }`}
    >
      {positive ? "+" : ""}
      {delta.toFixed(1)}{suffix}
    </span>
  );
}

export default function WeeklyKpiBoard({ mode = "full", middleContent }: WeeklyKpiBoardProps) {
  const isOwnerSummary = mode === "owner_summary";
  const [board, setBoard] = useState<KpiBoardResponse | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [weekStartInput, setWeekStartInput] = useState("");
  const [statusFilter, setStatusFilter] = useState<StatusFilter>("all");
  const [sectionFilter, setSectionFilter] = useState("all");
  const [sortBy, setSortBy] = useState<SortOption>("default");
  const [query, setQuery] = useState("");

  const loadBoard = useCallback(async (weekStart?: string) => {
    setIsLoading(true);
    try {
      const search = weekStart ? `?weekStart=${encodeURIComponent(weekStart)}` : "";
      const response = await fetch(`/api/kpis/weekly${search}`, {
        method: "GET",
        cache: "no-store",
      });

      const payload = (await response.json()) as KpiBoardResponse & { error?: string };

      if (!response.ok) {
        throw new Error(payload.error ?? "No se pudo cargar KPIs semanales.");
      }

      setBoard(payload);
      setWeekStartInput(payload.weekStart);
      setError(null);
    } catch (loadError) {
      setError(loadError instanceof Error ? loadError.message : "No se pudo cargar KPIs semanales.");
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    void loadBoard();
  }, [loadBoard]);

  const sectionOptions = useMemo(() => {
    if (!board) {
      return [] as Array<{ key: string; label: string }>;
    }

    return board.sections.map((section) => ({
      key: section.sectionKey,
      label: section.rawSectionLabel,
    }));
  }, [board]);

  const normalizedQuery = query.trim().toLowerCase();

  const filteredSections = useMemo(() => {
    if (!board) {
      return [];
    }

    return board.sections
      .filter((section) => sectionFilter === "all" || section.sectionKey === sectionFilter)
      .map((section) => {
        const rows = sortRows(
          section.rows.filter((row) => {
            const statusMatch = statusFilter === "all" || row.status === statusFilter;
            const queryMatch = rowMatchesQuery(row, normalizedQuery);
            return statusMatch && queryMatch;
          }),
          sortBy
        );

        return {
          ...section,
          rows,
        };
      })
      .filter((section) => section.rows.length > 0);
  }, [board, normalizedQuery, sectionFilter, sortBy, statusFilter]);

  const flattenedRows = useMemo(() => filteredSections.flatMap((section) => section.rows), [filteredSections]);

  const statusDistribution = useMemo(() => buildStatusDistribution(flattenedRows), [flattenedRows]);

  const dueBuckets = useMemo(() => {
    if (!board) {
      return [];
    }
    return buildDueBuckets(flattenedRows, board.weekStart);
  }, [board, flattenedRows]);

  const sectionHealth = useMemo(() => {
    if (!board) {
      return [];
    }

    return buildSectionHealth(filteredSections, board.weekStart).sort((a, b) => a.healthScore - b.healthScore);
  }, [board, filteredSections]);

  const onTrackDelta = summaryDelta(board?.summary.onTrackPct ?? 0, board?.previousWeekSummary?.onTrackPct);
  const riskDelta = summaryDelta(board?.summary.atRiskRows ?? 0, board?.previousWeekSummary?.atRiskRows);
  const dueSoonDelta = summaryDelta(board?.summary.dueSoonRows ?? 0, board?.previousWeekSummary?.dueSoonRows);

  return (
    <section className="rounded-benell border border-benell-stroke bg-benell-surface p-4 shadow-benell md:p-6" aria-labelledby="weekly-kpi-title">
      {isOwnerSummary ? (
        <div>
          <h2 id="weekly-kpi-title" className="text-h2 font-semibold">
            KPIs clave
          </h2>
          <p className="text-label mt-1 text-benell-text-soft">
            Indicadores principales y vista rápida semanal.
          </p>
        </div>
      ) : (
        <div className="flex flex-wrap items-start justify-between gap-3">
          <div>
            <h2 id="weekly-kpi-title" className="text-h2 font-semibold">
              Weekly KPI Board
            </h2>
            <p className="text-label mt-1 text-benell-text-soft">
              Vista de 3 segundos: estado general, riesgos críticos y carga de vencimientos.
            </p>
            <p className="text-caption mt-1 text-benell-text-soft">
              Actualizado: {formatDateTime(board?.lastUpdatedAt)} · Cobertura secciones: {board?.coverage.mappedSections ?? 0}/
              {board?.coverage.totalSections ?? 0} ({board?.coverage.mappedPct.toFixed(1) ?? "0.0"}%) · Fuente: {board?.source ?? "platform"}
            </p>
          </div>

          <div className="flex flex-wrap items-center gap-2 print:hidden">
            <Link
              href={board?.weekStart ? `/dashboard/print?weekStart=${encodeURIComponent(board.weekStart)}` : "/dashboard/print"}
              className="rounded-pill border border-benell-stroke bg-white px-3 py-2 text-label font-semibold text-benell-text"
            >
              Exportar PDF
            </Link>
            <button
              type="button"
              onClick={() => void loadBoard(weekStartInput)}
              className="rounded-pill bg-benell-brown px-3 py-2 text-label font-semibold text-white"
            >
              Recargar
            </button>
          </div>
        </div>
      )}

      <div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-4">
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label text-benell-text-soft">KPIs totales</p>
          <p className="mt-1 text-h2 font-semibold text-tabular">{board?.summary.totalRows ?? 0}</p>
          <p className="text-caption mt-1 text-benell-text-soft">Scored: {board?.summary.scoredRows ?? 0}</p>
        </article>
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label text-benell-text-soft">En ruta</p>
          <div className="mt-1 flex items-center justify-between gap-2">
            <p className="text-h2 font-semibold text-tabular">{board?.summary.onTrackPct.toFixed(1) ?? "0.0"}%</p>
            {deltaPill(onTrackDelta)}
          </div>
        </article>
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label text-benell-text-soft">En riesgo</p>
          <div className="mt-1 flex items-center justify-between gap-2">
            <p className="text-h2 font-semibold text-tabular">{board?.summary.atRiskRows ?? 0}</p>
            {deltaPill(riskDelta, "")}
          </div>
        </article>
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label text-benell-text-soft">Vencen pronto</p>
          <div className="mt-1 flex items-center justify-between gap-2">
            <p className="text-h2 font-semibold text-tabular">{board?.summary.dueSoonRows ?? 0}</p>
            {deltaPill(dueSoonDelta, "")}
          </div>
        </article>
      </div>

      {isOwnerSummary && middleContent ? <div className="mt-4">{middleContent}</div> : null}

      {isLoading ? <p className="text-label mt-4 text-benell-text-soft">Cargando KPIs...</p> : null}
      {error ? <p className="text-label mt-4 text-benell-red">{error}</p> : null}

      {!isLoading && !error && flattenedRows.length === 0 ? (
        <p className="text-label mt-4 text-benell-text-soft">No hay KPIs para mostrar en esta semana.</p>
      ) : null}

      <div className="mt-4 grid grid-cols-1 gap-4 xl:grid-cols-2">
        <article className="rounded-xl border border-benell-stroke bg-white p-4">
          <h3 className="text-label font-semibold text-benell-text">Distribución de estatus</h3>
          <div className="mt-3 h-56">
            <ResponsiveContainer width="100%" height="100%">
              <PieChart>
                <Pie data={statusDistribution} dataKey="value" nameKey="label" innerRadius={50} outerRadius={84} paddingAngle={2}>
                  {statusDistribution.map((entry) => (
                    <Cell key={entry.status} fill={STATUS_COLORS[entry.status]} />
                  ))}
                </Pie>
                <Tooltip />
              </PieChart>
            </ResponsiveContainer>
          </div>
          <div className="mt-2 grid grid-cols-2 gap-2 text-caption text-benell-text-soft">
            {statusDistribution.map((item) => (
              <p key={item.status}>
                {item.label}: <span className="font-semibold text-benell-text">{item.value}</span>
              </p>
            ))}
          </div>
        </article>

        <article className="rounded-xl border border-benell-stroke bg-white p-4">
          <h3 className="text-label font-semibold text-benell-text">Carga de vencimientos</h3>
          <div className="mt-3 h-56">
            <ResponsiveContainer width="100%" height="100%">
              <BarChart data={dueBuckets} margin={{ top: 4, right: 8, left: 0, bottom: 2 }}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis dataKey="label" tick={{ fontSize: 11 }} />
                <YAxis allowDecimals={false} tick={{ fontSize: 11 }} />
                <Tooltip />
                <Bar dataKey="value" fill="#8a6a3d" radius={[4, 4, 0, 0]} />
              </BarChart>
            </ResponsiveContainer>
          </div>
        </article>
      </div>

      {!isOwnerSummary ? (
        <>
          <div className="mt-4 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-5 print:hidden">
            <label className="text-label flex flex-col gap-1 text-benell-text-soft">
              Semana (inicio)
              <input
                type="date"
                value={weekStartInput}
                onChange={(event) => setWeekStartInput(event.target.value)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              />
            </label>

            <label className="text-label flex flex-col gap-1 text-benell-text-soft">
              Estatus
              <select
                value={statusFilter}
                onChange={(event) => setStatusFilter(event.target.value as StatusFilter)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              >
                <option value="all">Todos</option>
                <option value="on_track">En ruta</option>
                <option value="watch">Seguimiento</option>
                <option value="risk">Riesgo</option>
                <option value="no_score">Sin score</option>
              </select>
            </label>

            <label className="text-label flex flex-col gap-1 text-benell-text-soft">
              Sección
              <select
                value={sectionFilter}
                onChange={(event) => setSectionFilter(event.target.value)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              >
                <option value="all">Todas</option>
                {sectionOptions.map((option) => (
                  <option key={option.key} value={option.key}>
                    {option.label}
                  </option>
                ))}
              </select>
            </label>

            <label className="text-label flex flex-col gap-1 text-benell-text-soft">
              Orden
              <select
                value={sortBy}
                onChange={(event) => setSortBy(event.target.value as SortOption)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              >
                <option value="default">Orden original</option>
                <option value="compliance_desc">Cumplimiento alto a bajo</option>
                <option value="compliance_asc">Cumplimiento bajo a alto</option>
                <option value="responsibility">Responsabilidad A-Z</option>
              </select>
            </label>

            <label className="text-label flex flex-col gap-1 text-benell-text-soft">
              Buscar
              <input
                value={query}
                onChange={(event) => setQuery(event.target.value)}
                placeholder="Texto KPI..."
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              />
            </label>
          </div>

          {!isLoading && !error && filteredSections.length === 0 ? (
            <p className="text-label mt-4 text-benell-text-soft">No hay KPIs para los filtros seleccionados.</p>
          ) : null}

          <div className="mt-4 grid grid-cols-1 gap-3 xl:grid-cols-2">
            {sectionHealth.map((section) => (
              <article key={section.sectionId} className="rounded-xl border border-benell-stroke bg-white p-4">
                <div className="flex items-start justify-between gap-2">
                  <div>
                    <h3 className="text-h3 font-semibold">{section.label}</h3>
                    <p className="text-caption text-benell-text-soft">{section.ownerTeamLabel || "Sin owner"}</p>
                  </div>
                  <span className="rounded-full bg-benell-surface-muted px-2 py-1 text-caption font-semibold text-benell-text-soft">
                    Health {section.healthScore.toFixed(1)}
                  </span>
                </div>
                <div className="mt-3 grid grid-cols-3 gap-2 text-caption text-benell-text-soft">
                  <p>
                    Riesgo: <span className="font-semibold text-benell-red">{section.riskRows}</span>
                  </p>
                  <p>
                    Vence 7d: <span className="font-semibold text-benell-amber">{section.dueSoonRows}</span>
                  </p>
                  <p>
                    Peor %: <span className="font-semibold text-benell-text">{section.worstCompliancePct?.toFixed(1) ?? "-"}</span>
                  </p>
                </div>
              </article>
            ))}
          </div>

          <div className="mt-4 space-y-4">
            {filteredSections.map((section) => (
              <details key={section.id} className="rounded-xl border border-benell-stroke bg-white p-3 md:p-4">
                <summary className="cursor-pointer list-none">
                  <header className="flex flex-wrap items-center justify-between gap-2">
                    <h3 className="text-h3 font-semibold">{section.rawSectionLabel}</h3>
                    <p className="text-label text-benell-text-soft">{section.ownerTeamLabel || "Sin owner"} · {section.rows.length} KPIs</p>
                  </header>
                </summary>

                <div className="mt-3 overflow-x-auto">
                  <table className="w-full min-w-[920px] text-sm">
                    <thead>
                      <tr className="border-b border-benell-stroke text-left text-label text-benell-text-soft">
                        <th className="px-2 py-2">Responsabilidad</th>
                        <th className="px-2 py-2">Objetivo / Indicador</th>
                        <th className="px-2 py-2">Quantity & Quality</th>
                        <th className="px-2 py-2">% Cumplimiento</th>
                        <th className="px-2 py-2">Fecha / Compromiso</th>
                        <th className="px-2 py-2">Estatus</th>
                      </tr>
                    </thead>
                    <tbody>
                      {section.rows.map((row) => (
                        <tr key={row.id} className="border-b border-benell-stroke/70 align-top">
                          <td className="px-2 py-2 text-benell-text">{row.responsibility}</td>
                          <td className="px-2 py-2 text-benell-text-soft">{row.objectiveIndicator || "-"}</td>
                          <td className="px-2 py-2 text-tabular text-benell-text-soft">{row.quantityQuality || "-"}</td>
                          <td className="px-2 py-2">
                            {row.compliancePct !== null ? (
                              <div className="space-y-1">
                                <p className="text-tabular text-benell-text">{row.compliancePct.toFixed(1)}%</p>
                                <div className="h-1.5 w-28 rounded-full bg-benell-surface-muted">
                                  <div
                                    className="h-1.5 rounded-full bg-benell-brown"
                                    style={{ width: `${Math.max(0, Math.min(100, row.compliancePct))}%` }}
                                  />
                                </div>
                              </div>
                            ) : (
                              <p className="text-benell-text-soft">{row.compliance || "-"}</p>
                            )}
                          </td>
                          <td className="px-2 py-2 text-benell-text-soft">
                            <p>{row.dueCommitment || "-"}</p>
                            <p className="text-caption mt-1">{formatDate(row.dueDate)}</p>
                          </td>
                          <td className="px-2 py-2">
                            <span className={`inline-flex rounded-full px-2 py-1 text-caption font-semibold ${STATUS_CLASSNAMES[row.status]}`}>
                              {STATUS_LABELS[row.status]}
                            </span>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              </details>
            ))}
          </div>
        </>
      ) : null}
    </section>
  );
}
