"use client";

import { useMemo } from "react";
import Link from "next/link";
import { trpc } from "~/lib/trpc/client.js";
import type { WidgetProps } from "~/components/dashboard/widget-registry.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { ShoringBadge } from "~/components/projects/ShoringIndicator.js";
import { WidgetFilterBar, type WidgetFilter } from "~/components/dashboard/WidgetFilterBar.js";
import { useWidgetFilterOptions } from "~/hooks/useWidgetFilterOptions.js";
import { formatMoney } from "~/lib/format.js";

type ProjectHealthRow = {
  id: string;
  projectName: string;
  shortCode: string;
  status: string;
  clientId: string | null;
  clientName: string | null;
  budgetHealth: number;
  staffingHealth: number;
  timelineHealth: number;
  compositeScore: number;
  budgetCents?: number | null;
  spentCents?: number;
  remainingBudgetCents?: number | null;
  budgetUtilizationPercent?: number | null;
  demandHeadcountTotal?: number;
  demandHeadcountFilled?: number;
  demandHeadcountOpen?: number;
  demandRequirementCount?: number;
  plannedEndDate?: string | Date | null;
  daysUntilEndDate?: number | null;
  timelineStatus?: "ON_TRACK" | "DUE_SOON" | "OVERDUE" | "UNSCHEDULED" | null;
  calendarLocations?: Array<{
    countryCode?: string | null;
    countryName?: string | null;
    federalState?: string | null;
    metroCityName?: string | null;
    assignmentCount: number;
    spentCents: number;
  }>;
  derivation?: {
    periodStart: string;
    periodEnd: string;
    calendarContextCount: number;
    holidayAwareAssignmentCount: number;
    fallbackAssignmentCount: number;
    baseSpentCents: number;
    adjustedSpentCents: number;
    publicHolidayDayEquivalent: number;
    publicHolidayCostDeductionCents: number;
    absenceDayEquivalent: number;
    absenceCostDeductionCents: number;
  } | null;
};

function healthDot(value: number): string {
  if (value >= 70) return "bg-green-500";
  if (value >= 40) return "bg-amber-400";
  return "bg-red-500";
}

function scoreBadge(score: number): string {
  if (score >= 70) return "bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300";
  if (score >= 40) return "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300";
  return "bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300";
}

function formatShortDate(value?: string | Date | null): string {
  if (!value) {
    return "No end date";
  }

  const date = value instanceof Date ? value : new Date(value);
  if (Number.isNaN(date.getTime())) {
    return "No end date";
  }

  return new Intl.DateTimeFormat("de-DE", {
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
  }).format(date);
}

function formatTimeline(daysUntilEndDate?: number | null, timelineStatus?: string | null): string {
  if (timelineStatus === "UNSCHEDULED" || daysUntilEndDate == null) {
    return "No end date";
  }

  if (daysUntilEndDate < 0) {
    return `${Math.abs(daysUntilEndDate)} days overdue`;
  }

  if (daysUntilEndDate === 0) {
    return "Due today";
  }

  return `${daysUntilEndDate} days left`;
}

function formatLocation(location: {
  countryCode?: string | null;
  countryName?: string | null;
  federalState?: string | null;
  metroCityName?: string | null;
}): string {
  const parts = [
    location.countryCode ?? location.countryName ?? null,
    location.federalState ?? null,
    location.metroCityName ?? null,
  ].filter((part): part is string => Boolean(part));
  return parts.length > 0 ? parts.join(" / ") : "No calendar context";
}

function formatDayEquivalent(value?: number | null): string {
  if (value == null) return "—";
  return Number.isInteger(value) ? String(value) : value.toFixed(1);
}

export function ProjectHealthWidget({ config, onConfigChange }: WidgetProps) {
  const showDetails = config.showDetails === true;
  const { clients } = useWidgetFilterOptions({ clients: true });

  const filters = useMemo<WidgetFilter[]>(
    () => [
      { type: "search", key: "search", placeholder: "Search project..." },
      { type: "select", key: "clientId", label: "Client", options: clients },
    ],
    [clients],
  );

  const { data, isLoading } = trpc.dashboard.getProjectHealth.useQuery(
    undefined,
    { staleTime: 60_000, placeholderData: (prev) => prev },
  );

  const search = ((config.search as string) ?? "").toLowerCase();
  const clientId = (config.clientId as string) ?? "";

  const rows = useMemo(() => {
    const all = (data ?? []) as ProjectHealthRow[];
    return all.filter((r) => {
      if (search && !r.projectName.toLowerCase().includes(search) && !r.shortCode.toLowerCase().includes(search)) return false;
      if (clientId && r.clientId !== clientId) return false;
      return true;
    });
  }, [data, search, clientId]);

  if (isLoading && !data) {
    return (
      <div className="flex flex-col gap-1 pt-1">
        {[...Array(5)].map((_, i) => (
          <div key={i} className="flex items-center gap-3 px-3 py-2">
            <div className="h-3 w-16 shimmer-skeleton rounded" />
            <div className="h-3 flex-1 shimmer-skeleton rounded" />
            <div className="flex gap-1">
              <div className="h-4 w-4 shimmer-skeleton rounded-full" />
              <div className="h-4 w-4 shimmer-skeleton rounded-full" />
              <div className="h-4 w-4 shimmer-skeleton rounded-full" />
            </div>
            <div className="h-5 w-10 shimmer-skeleton rounded-full" />
          </div>
        ))}
      </div>
    );
  }

  if (rows.length === 0) {
    return (
      <div className="flex flex-col h-full">
        <WidgetFilterBar filters={filters} values={config} onChange={onConfigChange ?? (() => {})} />
        <div className="flex items-center justify-center flex-1 text-sm text-gray-400">
          No active projects found.
        </div>
      </div>
    );
  }

  return (
    <div className="flex flex-col h-full overflow-hidden">
      <WidgetFilterBar filters={filters} values={config} onChange={onConfigChange ?? (() => {})} />
      <div className="overflow-auto flex-1">
        <table className="w-full text-xs">
          <thead className="bg-gray-50 dark:bg-gray-800/50 sticky top-0">
            <tr>
              <th className="px-3 py-2 text-left font-medium text-gray-500 dark:text-gray-400">
                Project <InfoTooltip content="Active projects scored across three health dimensions including visible budget, staffing, and timeline basis." />
              </th>
              <th className="px-3 py-2 text-center font-medium text-gray-500 dark:text-gray-400">
                B / S / T <InfoTooltip content="Budget health (spent vs budget), Staffing health (filled vs total demanded headcount), Timeline health (end date and remaining horizon)." />
              </th>
              <th className="px-3 py-2 text-center font-medium text-gray-500 dark:text-gray-400">
                Shoring <InfoTooltip content="Offshore staffing ratio: percentage of hours from non-onshore resources. Color indicates threshold status." />
              </th>
              <th className="px-3 py-2 text-right font-medium text-gray-500 dark:text-gray-400">
                Score <InfoTooltip content="Composite score: average of Budget, Staffing, and Timeline health (0-100)" />
              </th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-100 dark:divide-gray-800">
            {rows.map((row) => (
              <tr key={row.shortCode} className="hover:bg-gray-50 dark:hover:bg-gray-800/30">
                <td className="px-3 py-2 text-gray-900 dark:text-gray-100 max-w-[320px]">
                  <Link href={`/projects/${(row as any).id}`} className="block hover:text-brand-600 dark:hover:text-brand-400 transition-colors">
                    <div className="truncate font-medium">
                      <span className="font-mono text-gray-500 dark:text-gray-400 mr-1">{row.shortCode}</span>
                      {row.projectName}
                    </div>
                  </Link>
                  {showDetails ? (
                    <div className="mt-1 space-y-0.5 text-[11px] leading-4 text-gray-500 dark:text-gray-400">
                      <div>
                        Budget: {formatMoney(row.spentCents ?? 0)} spent
                        {row.budgetCents != null ? ` / ${formatMoney(row.budgetCents)} budget` : " / no budget"}
                        {row.remainingBudgetCents != null ? ` / ${formatMoney(row.remainingBudgetCents)} remaining` : ""}
                      </div>
                      <div>
                        Staffing: {row.demandHeadcountFilled ?? 0}/{row.demandHeadcountTotal ?? 0} HC
                        {typeof row.demandHeadcountOpen === "number" ? `, ${row.demandHeadcountOpen} open` : ""}
                        {typeof row.demandRequirementCount === "number" ? ` across ${row.demandRequirementCount} demands` : ""}
                      </div>
                      <div>
                        Timeline: {formatShortDate(row.plannedEndDate)} · {formatTimeline(row.daysUntilEndDate, row.timelineStatus)}
                      </div>
                      {row.derivation ? (
                        <>
                          <div>
                            Spend basis: {row.derivation.calendarContextCount} calendar bases · {row.derivation.holidayAwareAssignmentCount} holiday-aware
                            {row.derivation.fallbackAssignmentCount > 0 ? ` · ${row.derivation.fallbackAssignmentCount} fallback` : ""}
                          </div>
                          <div>
                            Base {formatMoney(row.derivation.baseSpentCents)} {"->"} Effective {formatMoney(row.derivation.adjustedSpentCents)}
                          </div>
                          <div>
                            Holidays -{formatMoney(row.derivation.publicHolidayCostDeductionCents)} ({formatDayEquivalent(row.derivation.publicHolidayDayEquivalent)}d)
                            {" · "}
                            Absence -{formatMoney(row.derivation.absenceCostDeductionCents)} ({formatDayEquivalent(row.derivation.absenceDayEquivalent)}d)
                          </div>
                        </>
                      ) : null}
                      {(row.calendarLocations ?? []).length > 0 ? (
                        <div>
                          Calendar basis: {(row.calendarLocations ?? [])
                            .slice(0, 2)
                            .map((location) => `${formatLocation(location)} (${formatMoney(location.spentCents)} / ${location.assignmentCount} assign.)`)
                            .join(" · ")}
                          {(row.calendarLocations ?? []).length > 2
                            ? ` · +${(row.calendarLocations ?? []).length - 2} more`
                            : ""}
                        </div>
                      ) : null}
                    </div>
                  ) : null}
                </td>
                <td className="px-3 py-2">
                  <div className="flex flex-col items-center justify-center gap-1 text-[11px] text-gray-500 dark:text-gray-400">
                    <div className="flex items-center justify-center gap-2">
                      <span
                        className={`inline-block w-3 h-3 rounded-full ${healthDot(row.budgetHealth)}`}
                        title={`Budget: ${row.budgetHealth}%`}
                      />
                      <span
                        className={`inline-block w-3 h-3 rounded-full ${healthDot(row.staffingHealth)}`}
                        title={`Staffing: ${row.staffingHealth}%`}
                      />
                      <span
                        className={`inline-block w-3 h-3 rounded-full ${healthDot(row.timelineHealth)}`}
                        title={`Timeline: ${row.timelineHealth}%`}
                      />
                    </div>
                    <div className="text-center tabular-nums">
                      B {row.budgetUtilizationPercent ?? 0}% used
                    </div>
                    {showDetails ? (
                      <div className="text-center tabular-nums">
                        S {row.demandHeadcountFilled ?? 0}/{row.demandHeadcountTotal ?? 0} · T {formatTimeline(row.daysUntilEndDate, row.timelineStatus)}
                      </div>
                    ) : null}
                  </div>
                </td>
                <td className="px-3 py-2 text-center">
                  <ShoringBadge projectId={(row as any).id} />
                </td>
                <td className="px-3 py-2 text-right">
                  <span
                    className={`inline-block px-2 py-0.5 rounded-full font-semibold tabular-nums ${scoreBadge(row.compositeScore)}`}
                  >
                    {row.compositeScore}
                  </span>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}
