"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useSession } from "next-auth/react";
import type { KpiBoardResponse, KpiRowDTO, KpiRowStatus } from "@/lib/kpis/types";
import type { DepartmentKey } from "@/lib/types";

type DepartmentKpiTrackerProps = {
  department: DepartmentKey;
  title: string;
  description: string;
};

type DraftRow = {
  objectiveIndicator: string;
  quantityQuality: string;
  compliance: string;
  dueCommitment: string;
};

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",
};

function normalizeDepartment(department: DepartmentKey | null | undefined): DepartmentKey | null {
  if (!department) {
    return null;
  }

  if (department === "administracion") {
    return "capital_humano";
  }

  return department;
}

function isLeaderRole(role: string | null | undefined): boolean {
  return role === "leader" || role === "lead";
}

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);
}

export default function DepartmentKpiTracker({ department, title, description }: DepartmentKpiTrackerProps) {
  const { data: session } = useSession();
  const [board, setBoard] = useState<KpiBoardResponse | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [statusMessage, setStatusMessage] = useState<string | null>(null);
  const [weekStartInput, setWeekStartInput] = useState("");
  const [groupTitleInput, setGroupTitleInput] = useState("");
  const [kpiNameInput, setKpiNameInput] = useState("");
  const [kpiObjectiveInput, setKpiObjectiveInput] = useState("");
  const [editingRowId, setEditingRowId] = useState<string | null>(null);
  const [isSavingRow, setIsSavingRow] = useState(false);
  const [draftRow, setDraftRow] = useState<DraftRow>({
    objectiveIndicator: "",
    quantityQuality: "",
    compliance: "",
    dueCommitment: "",
  });

  const targetDepartment = normalizeDepartment(department);
  const isOwner = session?.user?.role === "owner";
  const viewerDepartment = normalizeDepartment(session?.user?.department ?? null);
  const isLeaderInDepartment = isLeaderRole(session?.user?.role) && Boolean(targetDepartment) && viewerDepartment === targetDepartment;
  const canManageDepartmentDefinition = isOwner && Boolean(targetDepartment);
  const canCaptureRowUpdates = Boolean(targetDepartment) && (isOwner || isLeaderInDepartment);

  const loadBoard = useCallback(async (weekStart?: string) => {
    setIsLoading(true);
    setError(null);
    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 pudieron cargar KPIs.");
      }

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

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

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

    return board.sections.filter((section) => normalizeDepartment(section.mappedDepartment) === targetDepartment);
  }, [board, targetDepartment]);

  const rows = useMemo(() => filteredSections.flatMap((section) => section.rows), [filteredSections]);
  const scoredRows = useMemo(() => rows.filter((row) => row.compliancePct !== null).length, [rows]);
  const onTrackRows = useMemo(() => rows.filter((row) => row.status === "on_track").length, [rows]);
  const riskRows = useMemo(() => rows.filter((row) => row.status === "risk").length, [rows]);

  const beginEdit = (row: KpiRowDTO) => {
    setEditingRowId(row.id);
    setStatusMessage(null);
    setDraftRow({
      objectiveIndicator: row.objectiveIndicator ?? "",
      quantityQuality: row.quantityQuality ?? "",
      compliance: row.compliance ?? "",
      dueCommitment: row.dueCommitment ?? "",
    });
  };

  const cancelEdit = () => {
    setEditingRowId(null);
    setIsSavingRow(false);
    setDraftRow({
      objectiveIndicator: "",
      quantityQuality: "",
      compliance: "",
      dueCommitment: "",
    });
  };

  const saveRow = async (rowId: string) => {
    setIsSavingRow(true);
    setError(null);
    setStatusMessage(null);
    try {
      const patchPayload: {
        objectiveIndicator?: string;
        quantityQuality: string;
        compliance: string;
        dueCommitment: string;
      } = {
        quantityQuality: draftRow.quantityQuality.trim(),
        compliance: draftRow.compliance.trim(),
        dueCommitment: draftRow.dueCommitment.trim(),
      };
      if (isOwner) {
        patchPayload.objectiveIndicator = draftRow.objectiveIndicator.trim();
      }

      const response = await fetch(`/api/kpis/weekly/rows/${encodeURIComponent(rowId)}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(patchPayload),
      });

      const payload = (await response.json()) as { error?: string };
      if (!response.ok) {
        throw new Error(payload.error ?? "No se pudo guardar la fila KPI.");
      }

      await loadBoard(weekStartInput);
      cancelEdit();
      setStatusMessage("KPI actualizado.");
    } catch (saveError) {
      setError(saveError instanceof Error ? saveError.message : "No se pudo guardar la fila KPI.");
    } finally {
      setIsSavingRow(false);
    }
  };

  const addDepartmentKpi = async () => {
    if (!targetDepartment) {
      setError("Departamento inválido.");
      return;
    }

    if (!groupTitleInput.trim() || !kpiNameInput.trim()) {
      setError("Título de grupo y nombre KPI son obligatorios.");
      return;
    }

    setIsSavingRow(true);
    setError(null);
    setStatusMessage(null);
    try {
      const response = await fetch("/api/kpis/weekly", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          weekStart: weekStartInput,
          department: targetDepartment,
          groupTitle: groupTitleInput.trim(),
          kpiName: kpiNameInput.trim(),
          objectiveIndicator: kpiObjectiveInput.trim() || null,
        }),
      });
      const payload = (await response.json()) as { error?: string; board?: KpiBoardResponse };
      if (!response.ok) {
        throw new Error(payload.error ?? "No se pudo agregar KPI.");
      }

      if (payload.board) {
        setBoard(payload.board);
        setWeekStartInput(payload.board.weekStart);
      } else {
        await loadBoard(weekStartInput);
      }
      setGroupTitleInput("");
      setKpiNameInput("");
      setKpiObjectiveInput("");
      setStatusMessage("KPI agregado al departamento.");
    } catch (addError) {
      setError(addError instanceof Error ? addError.message : "No se pudo agregar KPI.");
    } finally {
      setIsSavingRow(false);
    }
  };

  const clearDepartmentKpis = async () => {
    if (!targetDepartment) {
      setError("Departamento inválido.");
      return;
    }

    const confirmed = window.confirm("¿Limpiar todos los KPIs de este departamento para la semana seleccionada?");
    if (!confirmed) {
      return;
    }

    setIsSavingRow(true);
    setError(null);
    setStatusMessage(null);
    try {
      const params = new URLSearchParams({
        department: targetDepartment,
      });
      if (weekStartInput) {
        params.set("weekStart", weekStartInput);
      }
      const response = await fetch(`/api/kpis/weekly?${params.toString()}`, {
        method: "DELETE",
      });
      const payload = (await response.json()) as {
        error?: string;
        board?: KpiBoardResponse;
        result?: { deletedRows?: number };
      };
      if (!response.ok) {
        throw new Error(payload.error ?? "No se pudieron limpiar KPIs.");
      }

      if (payload.board) {
        setBoard(payload.board);
        setWeekStartInput(payload.board.weekStart);
      } else {
        await loadBoard(weekStartInput);
      }
      const deletedRows = payload.result?.deletedRows ?? 0;
      setStatusMessage(`KPIs limpiados: ${deletedRows} filas eliminadas.`);
      cancelEdit();
    } catch (clearError) {
      setError(clearError instanceof Error ? clearError.message : "No se pudieron limpiar KPIs.");
    } finally {
      setIsSavingRow(false);
    }
  };

  return (
    <section className="rounded-benell border border-benell-stroke bg-benell-surface p-4 shadow-benell md:p-5">
      <header className="flex flex-wrap items-start justify-between gap-3">
        <div>
          <h2 className="text-h2 font-semibold text-benell-text">{title}</h2>
          <p className="text-label mt-1 text-benell-text-soft">{description}</p>
          <p className="text-caption mt-1 text-benell-text-soft">
            Semana {board?.weekStart ?? "-"} a {board?.weekEnd ?? "-"} · Última actualización: {formatDateTime(board?.lastUpdatedAt)}
          </p>
        </div>
        <div className="flex flex-wrap items-end gap-2">
          <label className="text-label flex flex-col gap-1 text-benell-text-soft">
            Semana
            <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>
          <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>
      </header>

      {canManageDepartmentDefinition ? (
        <section className="mt-4 rounded-xl border border-benell-stroke bg-white p-3">
          <div className="flex flex-wrap items-center justify-between gap-2">
            <p className="text-label font-semibold text-benell-text">Owner tab · KPI/{targetDepartment}/grupo/[kpi]</p>
            <button
              type="button"
              onClick={() => void clearDepartmentKpis()}
              disabled={isSavingRow}
              className="rounded-pill border border-benell-red/40 bg-white px-3 py-1.5 text-caption font-semibold text-benell-red disabled:opacity-60"
            >
              Limpiar KPIs del departamento
            </button>
          </div>
          <div className="mt-3 grid gap-2 md:grid-cols-3">
            <label className="text-label flex flex-col gap-1 text-benell-text-soft">
              Grupo / categoría
              <input
                value={groupTitleInput}
                onChange={(event) => setGroupTitleInput(event.target.value)}
                placeholder="Ej. Social media metrics"
                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">
              KPI name
              <input
                value={kpiNameInput}
                onChange={(event) => setKpiNameInput(event.target.value)}
                placeholder="Ej. Alcance orgánico semanal"
                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">
              Cómo se mide (core)
              <input
                value={kpiObjectiveInput}
                onChange={(event) => setKpiObjectiveInput(event.target.value)}
                placeholder="Ej. >= 1.2M impresiones"
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              />
            </label>
          </div>
          <div className="mt-2">
            <button
              type="button"
              onClick={() => void addDepartmentKpi()}
              disabled={isSavingRow}
              className="rounded-pill bg-benell-brown px-3 py-2 text-caption font-semibold text-white disabled:opacity-60"
            >
              Agregar KPI al departamento
            </button>
          </div>
        </section>
      ) : null}

      <div className="mt-4 grid grid-cols-1 gap-3 md: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 del área</p>
          <p className="mt-1 text-h2 font-semibold text-tabular">{rows.length}</p>
        </article>
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label text-benell-text-soft">Con score</p>
          <p className="mt-1 text-h2 font-semibold text-tabular">{scoredRows}</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>
          <p className="mt-1 text-h2 font-semibold text-tabular">{onTrackRows}</p>
        </article>
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label text-benell-text-soft">En riesgo</p>
          <p className="mt-1 text-h2 font-semibold text-tabular">{riskRows}</p>
        </article>
      </div>

      <div className="mt-4 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-4">
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label font-semibold text-benell-text">Cómo medir</p>
          <p className="text-caption mt-1 text-benell-text-soft">Define meta e indicador en la columna de medicion.</p>
        </article>
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label font-semibold text-benell-text">Evidencia</p>
          <p className="text-caption mt-1 text-benell-text-soft">Usa la columna de evidencia para URL, archivo, cantidad o nota.</p>
        </article>
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label font-semibold text-benell-text">Score</p>
          <p className="text-caption mt-1 text-benell-text-soft">Captura el avance en porcentaje de cumplimiento (ejemplo: 78%).</p>
        </article>
        <article className="rounded-xl border border-benell-stroke bg-white p-3">
          <p className="text-label font-semibold text-benell-text">Update</p>
          <p className="text-caption mt-1 text-benell-text-soft">Registra seguimiento y fecha en la columna de actualizacion y compromiso.</p>
        </article>
      </div>

      {!isOwner && canCaptureRowUpdates ? (
        <p className="text-label mt-4 text-benell-text-soft">
          Solo owner puede modificar el KPI core. Como líder puedes actualizar evidencia, score y seguimiento.
        </p>
      ) : null}
      {error ? <p className="text-label mt-4 text-benell-red">{error}</p> : null}
      {statusMessage ? <p className="text-label mt-4 text-benell-green">{statusMessage}</p> : null}
      {isLoading ? <p className="text-label mt-4 text-benell-text-soft">Cargando KPIs del área...</p> : null}

      {!isLoading && !error && filteredSections.length === 0 ? (
        <p className="text-label mt-4 text-benell-text-soft">No hay KPIs mapeados a esta área para la semana seleccionada.</p>
      ) : null}

      <div className="mt-4 space-y-4">
        {filteredSections.map((section) => (
          <details key={section.id} open 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 text-benell-text">{section.rawSectionLabel}</h3>
                <p className="text-caption 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-[1120px] 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 KPI</th>
                    <th className="px-2 py-2">Cómo se mide</th>
                    <th className="px-2 py-2">Evidencia / cantidad</th>
                    <th className="px-2 py-2">% Cumplimiento (score)</th>
                    <th className="px-2 py-2">Actualización y compromiso</th>
                    <th className="px-2 py-2">Estatus</th>
                    <th className="px-2 py-2">Acción</th>
                  </tr>
                </thead>
                <tbody>
                  {section.rows.map((row) => {
                    const isEditing = editingRowId === row.id;
                    return (
                      <tr key={row.id} className="border-b border-benell-stroke/70 align-top">
                        <td className="px-2 py-2 text-benell-text">
                          <p className="font-semibold">{row.responsibility}</p>
                        </td>
                        <td className="px-2 py-2 text-benell-text-soft">
                          {isEditing && isOwner ? (
                            <input
                              value={draftRow.objectiveIndicator}
                              onChange={(event) => setDraftRow((prev) => ({ ...prev, objectiveIndicator: event.target.value }))}
                              className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm text-benell-text"
                              placeholder="Definir cómo se mide"
                            />
                          ) : (
                            row.objectiveIndicator || "-"
                          )}
                        </td>
                        <td className="px-2 py-2 text-benell-text-soft">
                          {isEditing ? (
                            <textarea
                              value={draftRow.quantityQuality}
                              onChange={(event) => setDraftRow((prev) => ({ ...prev, quantityQuality: event.target.value }))}
                              className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm text-benell-text"
                              rows={2}
                              placeholder="Link, archivo, dato o evidencia"
                            />
                          ) : (
                            row.quantityQuality || "-"
                          )}
                        </td>
                        <td className="px-2 py-2">
                          {isEditing ? (
                            <input
                              value={draftRow.compliance}
                              onChange={(event) => setDraftRow((prev) => ({ ...prev, compliance: event.target.value }))}
                              className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm text-benell-text"
                              placeholder="Ej. 85%"
                            />
                          ) : 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">
                          {isEditing ? (
                            <textarea
                              value={draftRow.dueCommitment}
                              onChange={(event) => setDraftRow((prev) => ({ ...prev, dueCommitment: event.target.value }))}
                              className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm text-benell-text"
                              rows={2}
                              placeholder="Último update y próximo compromiso"
                            />
                          ) : (
                            <>
                              <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>
                        <td className="px-2 py-2">
                          {canCaptureRowUpdates ? (
                            isEditing ? (
                              <div className="flex flex-wrap gap-2">
                                <button
                                  type="button"
                                  onClick={() => void saveRow(row.id)}
                                  disabled={isSavingRow}
                                  className="rounded-pill bg-benell-brown px-3 py-1.5 text-caption font-semibold text-white disabled:opacity-50"
                                >
                                  {isSavingRow ? "Guardando..." : "Guardar"}
                                </button>
                                <button
                                  type="button"
                                  onClick={cancelEdit}
                                  disabled={isSavingRow}
                                  className="rounded-pill border border-benell-stroke bg-white px-3 py-1.5 text-caption font-semibold text-benell-text"
                                >
                                  Cancelar
                                </button>
                              </div>
                            ) : (
                              <button
                                type="button"
                                onClick={() => beginEdit(row)}
                                className="rounded-pill border border-benell-stroke bg-white px-3 py-1.5 text-caption font-semibold text-benell-text"
                              >
                                Editar
                              </button>
                            )
                          ) : (
                            <p className="text-caption text-benell-text-soft">Solo lectura</p>
                          )}
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </details>
        ))}
      </div>
    </section>
  );
}
