"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import { AlertTriangle, CalendarClock, FolderKanban } from "lucide-react";
import { useSession } from "next-auth/react";
import DepartmentKpiTracker from "@/components/kpis/DepartmentKpiTracker";
import { formatCurrency, formatDate, formatDateTime, getStatusPillClass } from "@/lib/marketing/labels";
import { projectLocations } from "@/lib/projects/mock";
import type { Employee, Initiative, Meeting, Task } from "@/lib/projects/types";
import { PROJECT_DATE_RANGE_LABELS } from "@/lib/projects/labels";
import { useProjectsUIStore } from "@/stores/projectsUIStore";
import { cn } from "@/lib/utils";

const NOW = new Date("2026-03-04T12:00:00-06:00").getTime();
const DAY_MS = 24 * 60 * 60 * 1000;

function matchesDateRange(initiative: Initiative, range: "7d" | "30d" | "qtd"): boolean {
  const referenceDate = new Date(initiative.completedAt ?? initiative.dueDate).getTime();

  if (range === "7d") {
    return Math.abs(referenceDate - NOW) <= 7 * DAY_MS;
  }

  if (range === "30d") {
    return Math.abs(referenceDate - NOW) <= 30 * DAY_MS;
  }

  const year = new Date(NOW).getUTCFullYear();
  const quarterStart = Date.UTC(year, 0, 1);
  const quarterEnd = Date.UTC(year, 2, 31, 23, 59, 59);
  return referenceDate >= quarterStart && referenceDate <= quarterEnd;
}

function matchesLocationScope(initiative: Initiative, selectedLocationId: "all" | string): boolean {
  if (selectedLocationId === "all") {
    return true;
  }

  return initiative.isGlobal || initiative.locationIds.includes(selectedLocationId);
}

export default function ProjectsOverviewPage() {
  const { data: session } = useSession();
  const { locationId, dateRange, setLocationId, setDateRange } = useProjectsUIStore();

  const [employees, setEmployees] = useState<Employee[]>([]);
  const [initiatives, setInitiatives] = useState<Initiative[]>([]);
  const [tasks, setTasks] = useState<Task[]>([]);
  const [meetings, setMeetings] = useState<Meeting[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;

    async function load() {
      setIsLoading(true);
      try {
        const [dashboardResponse, meetingsResponse] = await Promise.all([
          fetch("/api/projects/dashboard", { method: "GET", cache: "no-store" }),
          fetch("/api/projects/meetings", { method: "GET", cache: "no-store" }),
        ]);

        const dashboardPayload = (await dashboardResponse.json()) as {
          error?: string;
          employees?: Employee[];
          initiatives?: Initiative[];
          tasks?: Task[];
        };

        if (!dashboardResponse.ok) {
          throw new Error(dashboardPayload.error ?? "No se pudo cargar el dashboard de Projects.");
        }

        const meetingsPayload = (await meetingsResponse.json()) as {
          error?: string;
          meetings?: Meeting[];
        };

        if (!meetingsResponse.ok) {
          throw new Error(meetingsPayload.error ?? "No se pudieron cargar las reuniones de Projects.");
        }

        if (cancelled) {
          return;
        }

        setEmployees(dashboardPayload.employees ?? []);
        setInitiatives(dashboardPayload.initiatives ?? []);
        setTasks(dashboardPayload.tasks ?? []);
        setMeetings(meetingsPayload.meetings ?? []);
        setError(null);
      } catch (loadError) {
        if (!cancelled) {
          setError(loadError instanceof Error ? loadError.message : "No se pudo cargar Projects.");
        }
      } finally {
        if (!cancelled) {
          setIsLoading(false);
        }
      }
    }

    void load();

    return () => {
      cancelled = true;
    };
  }, []);

  const employeesById = useMemo(() => Object.fromEntries(employees.map((employee) => [employee.id, employee])), [employees]);

  const filteredInitiatives = useMemo(
    () =>
      initiatives.filter((initiative) => {
        const byDate = matchesDateRange(initiative, dateRange);
        const byLocation = matchesLocationScope(initiative, locationId);
        return byDate && byLocation;
      }),
    [dateRange, initiatives, locationId]
  );

  const filteredInitiativeIds = useMemo(() => new Set(filteredInitiatives.map((initiative) => initiative.id)), [filteredInitiatives]);
  const filteredTasks = useMemo(() => tasks.filter((task) => filteredInitiativeIds.has(task.initiativeId)), [filteredInitiativeIds, tasks]);

  const activeProjects = useMemo(
    () => filteredInitiatives.filter((initiative) => initiative.status !== "results" && initiative.status !== "evaluation").length,
    [filteredInitiatives]
  );

  const allMilestones = useMemo(() => filteredInitiatives.flatMap((initiative) => initiative.milestones ?? []), [filteredInitiatives]);
  const onTimeMilestonesPct = useMemo(() => {
    if (allMilestones.length === 0) {
      return 0;
    }

    const onTimeCount = allMilestones.filter((milestone) => {
      if (milestone.status === "completed") {
        return true;
      }

      return new Date(milestone.dueDate).getTime() >= NOW;
    }).length;

    return Math.round((onTimeCount / allMilestones.length) * 100);
  }, [allMilestones]);

  const blockedTasksCount = useMemo(() => filteredTasks.filter((task) => task.status === "blocked").length, [filteredTasks]);
  const overdueTasksCount = useMemo(
    () => filteredTasks.filter((task) => task.status !== "done" && new Date(task.dueDate).getTime() < NOW).length,
    [filteredTasks]
  );

  const actualRevenueTotal = useMemo(
    () => filteredInitiatives.reduce((acc, initiative) => acc + initiative.actualRevenue, 0),
    [filteredInitiatives]
  );
  const actualProfitTotal = useMemo(() => filteredInitiatives.reduce((acc, initiative) => acc + initiative.actualProfit, 0), [filteredInitiatives]);
  const plannedCostTotal = useMemo(() => filteredInitiatives.reduce((acc, initiative) => acc + initiative.plannedCost, 0), [filteredInitiatives]);
  const actualCostTotal = useMemo(() => filteredInitiatives.reduce((acc, initiative) => acc + initiative.actualCost, 0), [filteredInitiatives]);

  const costVariancePctTotal = useMemo(() => {
    if (plannedCostTotal <= 0) {
      return 0;
    }

    return ((actualCostTotal - plannedCostTotal) / plannedCostTotal) * 100;
  }, [actualCostTotal, plannedCostTotal]);

  const marginPctTotal = useMemo(() => {
    if (actualRevenueTotal <= 0) {
      return 0;
    }

    return (actualProfitTotal / actualRevenueTotal) * 100;
  }, [actualProfitTotal, actualRevenueTotal]);

  const alertItems = useMemo(() => {
    const blocked = filteredTasks
      .filter((task) => task.status === "blocked")
      .slice(0, 4)
      .map((task) => ({
        id: `blocked:${task.id}`,
        title: `Bloqueo: ${task.title}`,
        detail: `Responsable: ${employeesById[task.assigneeId]?.name ?? "Sin asignar"}`,
      }));

    const overdueMilestones = allMilestones
      .filter((milestone) => milestone.status !== "completed" && new Date(milestone.dueDate).getTime() < NOW)
      .slice(0, 4)
      .map((milestone) => ({
        id: `milestone:${milestone.id}`,
        title: `Hito vencido: ${milestone.title}`,
        detail: `Fecha objetivo: ${formatDate(milestone.dueDate)}`,
      }));

    const budgetRisk = filteredInitiatives
      .filter((initiative) => initiative.costVariancePct >= 10)
      .slice(0, 4)
      .map((initiative) => ({
        id: `budget:${initiative.id}`,
        title: `Riesgo de costo: ${initiative.name}`,
        detail: `Variación: ${initiative.costVariancePct.toFixed(1)}%`,
      }));

    return [...blocked, ...overdueMilestones, ...budgetRisk].slice(0, 8);
  }, [allMilestones, employeesById, filteredInitiatives, filteredTasks]);

  const myTasks = useMemo(() => {
    const userId = session?.user?.id;
    if (!userId) {
      return [];
    }

    return filteredTasks
      .filter((task) => task.assigneeId === userId)
      .sort((a, b) => new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime())
      .slice(0, 8);
  }, [filteredTasks, session?.user?.id]);

  const upcomingMeetings = useMemo(
    () =>
      meetings
        .filter((meeting) => meeting.status === "scheduled" || meeting.status === "requested")
        .sort((a, b) => new Date(a.scheduledFor ?? "2999-12-31T00:00:00Z").getTime() - new Date(b.scheduledFor ?? "2999-12-31T00:00:00Z").getTime())
        .slice(0, 6),
    [meetings]
  );

  return (
    <div className="space-y-5">
      <section className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
        <div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
          <div>
            <p className="text-sm font-semibold uppercase tracking-wide text-benell-brown">Projects Overview</p>
            <h1 className="mt-1 text-2xl font-semibold text-benell-text">Resumen operativo</h1>
            <p className="mt-1 text-sm text-benell-text-soft">Visibilidad de ejecución, alertas y carga operativa.</p>
          </div>

          <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
            <label className="flex min-w-[180px] flex-col gap-1 text-sm text-benell-text-soft">
              Rango
              <select
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
                value={dateRange}
                onChange={(event) => setDateRange(event.target.value as "7d" | "30d" | "qtd")}
              >
                <option value="7d">{PROJECT_DATE_RANGE_LABELS["7d"]}</option>
                <option value="30d">{PROJECT_DATE_RANGE_LABELS["30d"]}</option>
                <option value="qtd">{PROJECT_DATE_RANGE_LABELS.qtd}</option>
              </select>
            </label>

            <label className="flex min-w-[180px] flex-col gap-1 text-sm text-benell-text-soft">
              Ubicación
              <select
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
                value={locationId}
                onChange={(event) => setLocationId(event.target.value)}
              >
                <option value="all">Todas</option>
                {projectLocations.map((location) => (
                  <option key={location.id} value={location.id}>
                    {location.name}
                  </option>
                ))}
              </select>
            </label>

            <Link
              href="/departments/projects/projects"
              className="inline-flex items-center justify-center rounded-lg bg-benell-brown px-4 py-2 text-sm font-semibold text-white transition hover:brightness-95"
            >
              Nuevo proyecto
            </Link>
          </div>
        </div>
      </section>

      {error ? (
        <section className="rounded-benell border border-benell-red/40 bg-benell-red/10 p-4 text-sm text-benell-red">{error}</section>
      ) : null}

      <DepartmentKpiTracker
        department="proyectos"
        title="KPIs del área: Projects (OOH / Comunidad)"
        description="Gestiona medición, evidencia, score y actualización de KPIs de Uber Eats, Grab & Go, eventos y nuevos proyectos."
      />

      <section className="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-6">
        {[
          { label: "Proyectos activos", value: activeProjects.toString() },
          { label: "Hitos en tiempo", value: `${onTimeMilestonesPct}%` },
          { label: "Tareas bloqueadas", value: blockedTasksCount.toString() },
          { label: "Tareas vencidas", value: overdueTasksCount.toString() },
          { label: "Variación de costo", value: `${costVariancePctTotal.toFixed(1)}%` },
          { label: "Margen", value: `${marginPctTotal.toFixed(1)}%` },
        ].map((card) => (
          <article key={card.label} className="rounded-benell border border-benell-stroke bg-benell-surface p-4 shadow-benell">
            <p className="text-xs uppercase tracking-wide text-benell-text-soft">{card.label}</p>
            <p className="mt-2 text-2xl font-semibold text-benell-text">{card.value}</p>
          </article>
        ))}
      </section>

      <section className="grid gap-5 xl:grid-cols-2">
        <article className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
          <header className="mb-3 flex items-center gap-2 text-benell-red">
            <AlertTriangle className="size-4" aria-hidden />
            <h2 className="text-base font-semibold text-benell-text">Alertas prioritarias</h2>
          </header>
          {alertItems.length === 0 ? (
            <p className="text-sm text-benell-text-soft">Sin alertas críticas en el rango actual.</p>
          ) : (
            <ul className="space-y-2">
              {alertItems.map((item) => (
                <li key={item.id} className="rounded-lg border border-benell-stroke bg-white px-3 py-2">
                  <p className="text-sm font-semibold text-benell-text">{item.title}</p>
                  <p className="text-xs text-benell-text-soft">{item.detail}</p>
                </li>
              ))}
            </ul>
          )}
        </article>

        <article className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
          <header className="mb-3 flex items-center gap-2 text-benell-brown">
            <CalendarClock className="size-4" aria-hidden />
            <h2 className="text-base font-semibold text-benell-text">Próximas reuniones</h2>
          </header>

          {upcomingMeetings.length === 0 ? (
            <p className="text-sm text-benell-text-soft">Sin reuniones próximas.</p>
          ) : (
            <ul className="space-y-2">
              {upcomingMeetings.map((meeting) => (
                <li key={meeting.id} className="rounded-lg border border-benell-stroke bg-white px-3 py-2">
                  <div className="flex items-start justify-between gap-3">
                    <div>
                      <p className="text-sm font-semibold text-benell-text">{meeting.title}</p>
                      <p className="text-xs text-benell-text-soft">{formatDateTime(meeting.scheduledFor)}</p>
                    </div>
                    <span className={cn("rounded-full px-2 py-0.5 text-xs font-semibold", getStatusPillClass(meeting.status))}>
                      {meeting.status}
                    </span>
                  </div>
                </li>
              ))}
            </ul>
          )}

          <div className="mt-4">
            <Link href="/departments/projects/meetings" className="text-sm font-semibold text-benell-brown hover:underline">
              Ir a calendario semanal
            </Link>
          </div>
        </article>
      </section>

      <section className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
        <header className="mb-3 flex items-center gap-2 text-benell-brown">
          <FolderKanban className="size-4" aria-hidden />
          <h2 className="text-base font-semibold text-benell-text">Portafolio (vista rápida)</h2>
        </header>

        <div className="overflow-x-auto">
          <table className="min-w-full divide-y divide-benell-stroke text-sm">
            <thead className="bg-benell-surface-muted text-left text-xs uppercase tracking-wide text-benell-text-soft">
              <tr>
                <th className="px-3 py-2">Proyecto</th>
                <th className="px-3 py-2">Status</th>
                <th className="px-3 py-2">Owner</th>
                <th className="px-3 py-2">Due date</th>
                <th className="px-3 py-2">Variación costo</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-benell-stroke">
              {filteredInitiatives.slice(0, 10).map((initiative) => (
                <tr key={initiative.id} className="hover:bg-benell-surface-muted/70">
                  <td className="px-3 py-2">
                    <Link href="/departments/projects/projects" className="font-semibold text-benell-brown hover:underline">
                      {initiative.name}
                    </Link>
                  </td>
                  <td className="px-3 py-2">
                    <span className={cn("rounded-full px-2 py-0.5 text-xs font-semibold", getStatusPillClass(initiative.status))}>
                      {initiative.status}
                    </span>
                  </td>
                  <td className="px-3 py-2 text-benell-text-soft">{employeesById[initiative.ownerId]?.name ?? "Sin asignar"}</td>
                  <td className="px-3 py-2 text-benell-text-soft">{formatDate(initiative.dueDate)}</td>
                  <td className="px-3 py-2 text-benell-text-soft">{initiative.costVariancePct.toFixed(1)}%</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </section>

      <section className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
        <h2 className="text-base font-semibold text-benell-text">Mi carga de trabajo</h2>
        <p className="mt-1 text-sm text-benell-text-soft">Asignaciones y compromisos del usuario actual.</p>

        {myTasks.length === 0 ? (
          <p className="mt-3 text-sm text-benell-text-soft">Sin tareas asignadas en el rango seleccionado.</p>
        ) : (
          <ul className="mt-3 space-y-2">
            {myTasks.map((task) => (
              <li key={task.id} className="rounded-lg border border-benell-stroke bg-white px-3 py-2">
                <div className="flex items-start justify-between gap-3">
                  <div>
                    <p className="text-sm font-semibold text-benell-text">{task.title}</p>
                    <p className="text-xs text-benell-text-soft">Vence {formatDate(task.dueDate)}</p>
                  </div>
                  <span className={cn("rounded-full px-2 py-0.5 text-xs font-semibold", getStatusPillClass(task.status))}>{task.status}</span>
                </div>
              </li>
            ))}
          </ul>
        )}
      </section>

      <section className="rounded-benell border border-benell-stroke bg-benell-surface p-4 text-sm text-benell-text-soft">
        <p>
          Totales financieros del rango: costo plan {formatCurrency(plannedCostTotal)}, costo real {formatCurrency(actualCostTotal)}, utilidad real
          {" "}
          {formatCurrency(actualProfitTotal)}.
        </p>
        {isLoading ? <p className="mt-2">Actualizando datos...</p> : null}
      </section>
    </div>
  );
}
