"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import { useAlertConfirm } from "@/components/ui/alert-dialog";
import { useLocalStorage } from "@/lib/hooks/use-local-storage";
import {
  DEFAULT_ONBOARDING_TASKS,
  type OnboardingTaskTemplate,
} from "@/lib/hr/onboarding-template";
import { ALL_ORGANIZATIONS } from "@/lib/sag/entities";
import type { Employee } from "@/lib/sag/employees-seed";
import { formatDate } from "@/lib/utils";

// ──────────────────────────────────────────────────────────────────────────
// Types
// ──────────────────────────────────────────────────────────────────────────

type OnboardingItemState = {
  hireId: string;
  templateId: string;
  status: "todo" | "in_progress" | "done" | "blocked";
  completedAt?: string;
  notes?: string;
};

type OnboardingStore = Record<string, OnboardingItemState[]>;

const STATE_KEY = "sag.hr.onboarding";
const ONBOARDING_WINDOW_DAYS = 30;

const GROUPS = [
  "Tax & Identity",
  "Banking",
  "Legal",
  "Equipment",
  "Brand & Voice",
  "Manager Touchpoints",
] as const satisfies readonly OnboardingTaskTemplate["group"][];

const RESPONSIBLE_LABEL: Record<
  OnboardingTaskTemplate["responsibleParty"],
  string
> = {
  hire: "Hire",
  manager: "Manager",
  hr: "HR",
};

const RESPONSIBLE_TONE: Record<
  OnboardingTaskTemplate["responsibleParty"],
  "outline" | "info" | "secondary"
> = {
  hire: "outline",
  manager: "info",
  hr: "secondary",
};

const STATUS_LABEL: Record<OnboardingItemState["status"], string> = {
  todo: "To do",
  in_progress: "In progress",
  done: "Done",
  blocked: "Blocked",
};

const STATUS_TONE: Record<
  OnboardingItemState["status"],
  "outline" | "warning" | "success" | "destructive"
> = {
  todo: "outline",
  in_progress: "warning",
  done: "success",
  blocked: "destructive",
};

// ──────────────────────────────────────────────────────────────────────────
// Helpers
// ──────────────────────────────────────────────────────────────────────────

function seedItemsFor(hireId: string): OnboardingItemState[] {
  return DEFAULT_ONBOARDING_TASKS.map((t) => ({
    hireId,
    templateId: t.id,
    status: "todo" as const,
  }));
}

function todayIso(): string {
  return new Date().toISOString().slice(0, 10);
}

function addDays(iso: string, offset: number): string {
  const d = new Date(iso + "T00:00:00Z");
  d.setUTCDate(d.getUTCDate() + offset);
  return d.toISOString().slice(0, 10);
}

function daysBetween(fromIso: string, toIso: string): number {
  const from = new Date(fromIso + "T00:00:00Z").getTime();
  const to = new Date(toIso + "T00:00:00Z").getTime();
  return Math.round((to - from) / (1000 * 60 * 60 * 24));
}

// ──────────────────────────────────────────────────────────────────────────
// Main component
// ──────────────────────────────────────────────────────────────────────────

export function HrOnboardingChecklist({ hire }: { hire: Employee }) {
  const [store, setStore] = useLocalStorage<OnboardingStore>(STATE_KEY, {});
  const [archived, setArchived] = useLocalStorage<Record<string, boolean>>(
    "sag.hr.onboarding.archived",
    {}
  );
  const [expandedNotes, setExpandedNotes] = useState<Record<string, boolean>>({});
  const { confirm: confirmAlert, AlertConfirmPortal } = useAlertConfirm();

  const org = useMemo(
    () => ALL_ORGANIZATIONS.find((o) => o.slug === hire.organizationSlug),
    [hire.organizationSlug]
  );

  // Ensure the hire has a seeded list. Seed lazily on first access.
  const items = useMemo<OnboardingItemState[]>(() => {
    const existing = store[hire.id];
    if (existing && existing.length > 0) {
      // Merge in any new template tasks that didn't exist when this hire was seeded.
      const present = new Set(existing.map((i) => i.templateId));
      const additions = DEFAULT_ONBOARDING_TASKS.filter(
        (t) => !present.has(t.id)
      ).map<OnboardingItemState>((t) => ({
        hireId: hire.id,
        templateId: t.id,
        status: "todo",
      }));
      return additions.length === 0 ? existing : [...existing, ...additions];
    }
    return seedItemsFor(hire.id);
  }, [store, hire.id]);

  // Persist the merged seed once when the hire's list is missing or stale.
  // We avoid depending on `store` directly to prevent a write→re-read loop.
  useEffect(() => {
    const existing = store[hire.id];
    if (!existing || existing.length !== items.length) {
      setStore({ ...store, [hire.id]: items });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [hire.id, items.length]);

  const itemByTemplateId = useMemo(() => {
    const m: Record<string, OnboardingItemState> = {};
    for (const it of items) m[it.templateId] = it;
    return m;
  }, [items]);

  const totalTasks = DEFAULT_ONBOARDING_TASKS.length;
  const doneCount = items.filter((i) => i.status === "done").length;
  const pct = totalTasks > 0 ? Math.round((doneCount / totalTasks) * 100) : 0;

  const startDate = hire.startDate;
  const today = todayIso();
  const daysSinceStart = startDate ? daysBetween(startDate, today) : null;
  const windowClosed =
    startDate != null && daysSinceStart != null && daysSinceStart > ONBOARDING_WINDOW_DAYS;
  const isArchived = archived[hire.id] === true;

  function updateItem(templateId: string, patch: Partial<OnboardingItemState>) {
    const current = itemByTemplateId[templateId];
    if (!current) return;
    const next: OnboardingItemState = { ...current, ...patch };
    const updated = items.map((i) => (i.templateId === templateId ? next : i));
    setStore({ ...store, [hire.id]: updated });
  }

  function toggleDone(templateId: string) {
    const cur = itemByTemplateId[templateId];
    if (!cur) return;
    if (cur.status === "done") {
      updateItem(templateId, { status: "todo", completedAt: undefined });
    } else {
      updateItem(templateId, { status: "done", completedAt: todayIso() });
    }
  }

  function setStatus(templateId: string, status: OnboardingItemState["status"]) {
    if (status === "done") {
      updateItem(templateId, { status, completedAt: todayIso() });
    } else {
      updateItem(templateId, { status, completedAt: undefined });
    }
  }

  function setNotes(templateId: string, notes: string) {
    updateItem(templateId, { notes });
  }

  async function resetToTemplate() {
    const ok = await confirmAlert({
      title: "Reset this hire's checklist to the default template?",
      description: "All progress, notes, and completion dates will be lost.",
      actionLabel: "Reset",
      destructive: true,
    });
    if (!ok) return;
    setStore({ ...store, [hire.id]: seedItemsFor(hire.id) });
    setExpandedNotes({});
  }

  async function archive() {
    const ok = await confirmAlert({
      title: "Archive this checklist?",
      description: "It will be hidden from active onboarding views.",
      actionLabel: "Archive",
      destructive: false,
    });
    if (!ok) return;
    setArchived({ ...archived, [hire.id]: true });
  }

  function unarchive() {
    setArchived({ ...archived, [hire.id]: false });
  }

  function toggleNotes(templateId: string) {
    setExpandedNotes((p) => ({ ...p, [templateId]: !p[templateId] }));
  }

  return (
    <>
    <div className="space-y-6">
      <div className="flex items-center justify-between flex-wrap gap-2">
        <Link
          href="/app/hr"
          className="text-sm text-muted-foreground hover:text-foreground"
        >
          ← HR directory
        </Link>
        <div className="flex items-center gap-2">
          <Button variant="outline" size="sm" onClick={resetToTemplate}>
            Reset to template
          </Button>
          {!isArchived && (
            <Button
              variant="ghost"
              size="sm"
              onClick={archive}
              disabled={!windowClosed}
              title={
                windowClosed
                  ? "Archive this checklist"
                  : "Archive becomes available once the 30-day onboarding window has closed"
              }
            >
              Archive
            </Button>
          )}
          {isArchived && (
            <Button variant="ghost" size="sm" onClick={unarchive}>
              Unarchive
            </Button>
          )}
        </div>
      </div>

      {/* ─── Header ───────────────────────────────────────────────────── */}
      <Card>
        <CardContent className="p-5">
          <div className="flex flex-wrap items-start justify-between gap-4">
            <div className="min-w-0">
              <div className="flex items-center gap-2 flex-wrap mb-1">
                <Badge
                  variant={
                    hire.status === "Active"
                      ? "success"
                      : hire.status === "On Leave"
                        ? "warning"
                        : "outline"
                  }
                >
                  {hire.status}
                </Badge>
                <span className="text-xs text-muted-foreground inline-flex items-center gap-1">
                  {org?.emoji ?? "🏢"} {org?.name ?? hire.organizationSlug}
                </span>
                {isArchived && (
                  <Badge variant="outline" className="text-[10px]">
                    Archived
                  </Badge>
                )}
              </div>
              <h2 className="text-xl font-semibold">{hire.fullName}</h2>
              <div className="text-sm text-muted-foreground">{hire.role}</div>
              <div className="mt-3 grid gap-y-1 gap-x-6 text-xs text-muted-foreground sm:grid-cols-2 md:grid-cols-3">
                <div>
                  <span className="text-[10px] uppercase tracking-wider">Start date</span>
                  <div className="text-foreground tabular-nums">
                    {startDate ? formatDate(startDate) : "—"}
                  </div>
                </div>
                <div>
                  <span className="text-[10px] uppercase tracking-wider">Days since start</span>
                  <div className="text-foreground tabular-nums">
                    {daysSinceStart == null
                      ? "—"
                      : daysSinceStart < 0
                        ? `${Math.abs(daysSinceStart)} until start`
                        : `${daysSinceStart} day${daysSinceStart === 1 ? "" : "s"}`}
                  </div>
                </div>
                <div>
                  <span className="text-[10px] uppercase tracking-wider">Onboarding window</span>
                  <div className="text-foreground">
                    {windowClosed ? "Closed (>30 days)" : "Open"}
                  </div>
                </div>
              </div>
            </div>
            <div className="text-right shrink-0">
              <div className="section-label">
                Progress
              </div>
              <div className="text-2xl font-semibold tabular-nums">{pct}%</div>
              <div className="text-xs text-muted-foreground tabular-nums">
                {doneCount} of {totalTasks} complete
              </div>
            </div>
          </div>
          <div className="mt-4">
            <Progress value={pct} />
          </div>
        </CardContent>
      </Card>

      {/* ─── Window-closed banner ────────────────────────────────────── */}
      {windowClosed && !isArchived && (
        <Card className="border-yellow-500/40 bg-yellow-50/40 dark:bg-yellow-950/20">
          <CardContent className="p-4">
            <div className="flex items-start gap-3">
              <div className="text-2xl">📅</div>
              <div className="flex-1">
                <div className="text-sm font-semibold">
                  Onboarding window closed — archive this checklist?
                </div>
                <p className="mt-1 text-xs text-muted-foreground">
                  {hire.fullName.split(" ")[0]} started{" "}
                  {daysSinceStart} days ago. The 30-day onboarding window has
                  passed. Archive to hide this checklist from active views, or
                  leave open if items remain.
                </p>
                <div className="mt-3">
                  <Button variant="brand" size="sm" onClick={archive}>
                    Archive checklist
                  </Button>
                </div>
              </div>
            </div>
          </CardContent>
        </Card>
      )}

      {/* ─── Grouped task sections ───────────────────────────────────── */}
      <div className="space-y-4">
        {GROUPS.map((group) => {
          const tasks = DEFAULT_ONBOARDING_TASKS.filter((t) => t.group === group);
          if (tasks.length === 0) return null;
          const groupDone = tasks.filter(
            (t) => itemByTemplateId[t.id]?.status === "done"
          ).length;
          return (
            <Card key={group}>
              <CardContent className="p-0">
                <div className="px-5 py-3 border-b flex items-center justify-between">
                  <h3 className="text-sm font-semibold">{group}</h3>
                  <span className="section-label tabular-nums">
                    {groupDone} / {tasks.length}
                  </span>
                </div>
                <ul>
                  {tasks.map((t) => {
                    const it = itemByTemplateId[t.id];
                    const status = it?.status ?? "todo";
                    const dueIso = startDate
                      ? addDays(startDate, t.dueDayOffset)
                      : null;
                    const overdue =
                      dueIso != null && dueIso < today && status !== "done";
                    const showNotes = expandedNotes[t.id] === true;
                    return (
                      <li
                        key={t.id}
                        className={`px-5 py-3 border-b last:border-0 ${
                          status === "done" ? "bg-muted/30" : ""
                        } ${overdue ? "bg-destructive/5" : ""}`}
                      >
                        <div className="flex items-start gap-3 flex-wrap">
                          <input
                            type="checkbox"
                            checked={status === "done"}
                            onChange={() => toggleDone(t.id)}
                            className="mt-1 h-4 w-4"
                            aria-label={`Mark ${t.title} complete`}
                          />
                          <div className="min-w-0 flex-1">
                            <div className="flex items-center gap-2 flex-wrap">
                              <span
                                className={`text-sm font-medium ${
                                  status === "done"
                                    ? "line-through text-muted-foreground"
                                    : ""
                                }`}
                              >
                                {t.title}
                              </span>
                              <Badge
                                variant={RESPONSIBLE_TONE[t.responsibleParty]}
                                className="text-[10px]"
                              >
                                {RESPONSIBLE_LABEL[t.responsibleParty]}
                              </Badge>
                              <Badge
                                variant={STATUS_TONE[status]}
                                className="text-[10px]"
                              >
                                {STATUS_LABEL[status]}
                              </Badge>
                              {overdue && (
                                <Badge variant="destructive" className="text-[10px]">
                                  Overdue
                                </Badge>
                              )}
                            </div>
                            <p className="mt-1 text-xs text-muted-foreground">
                              {t.description}
                            </p>
                            <div className="mt-1.5 flex items-center gap-3 flex-wrap text-[11px] text-muted-foreground tabular-nums">
                              <span>
                                <span className="text-[10px] uppercase tracking-wider mr-1">
                                  Due
                                </span>
                                {dueIso ? formatDate(dueIso) : "—"}
                                <span className="ml-1 text-muted-foreground/70">
                                  (start
                                  {t.dueDayOffset === 0
                                    ? ""
                                    : t.dueDayOffset > 0
                                      ? ` +${t.dueDayOffset}d`
                                      : ` ${t.dueDayOffset}d`}
                                  )
                                </span>
                              </span>
                              {it?.completedAt && (
                                <span>
                                  <span className="text-[10px] uppercase tracking-wider mr-1">
                                    Completed
                                  </span>
                                  {formatDate(it.completedAt)}
                                </span>
                              )}
                              <button
                                type="button"
                                className="underline hover:text-foreground"
                                onClick={() => toggleNotes(t.id)}
                              >
                                {showNotes
                                  ? "Hide notes"
                                  : it?.notes
                                    ? "Edit notes"
                                    : "Add notes"}
                              </button>
                            </div>
                            {showNotes && (
                              <div className="mt-2">
                                <textarea
                                  value={it?.notes ?? ""}
                                  onChange={(e) => setNotes(t.id, e.target.value)}
                                  rows={2}
                                  className="w-full text-xs rounded-md border border-input bg-background p-2"
                                  placeholder="Anything worth remembering — doc location, exceptions, follow-ups."
                                />
                              </div>
                            )}
                          </div>
                          <div className="shrink-0">
                            <select
                              value={status}
                              onChange={(e) =>
                                setStatus(
                                  t.id,
                                  e.target.value as OnboardingItemState["status"]
                                )
                              }
                              className="h-8 rounded-md border border-input bg-background px-2 text-xs"
                              aria-label={`Status for ${t.title}`}
                            >
                              <option value="todo">To do</option>
                              <option value="in_progress">In progress</option>
                              <option value="done">Done</option>
                              <option value="blocked">Blocked</option>
                            </select>
                          </div>
                        </div>
                      </li>
                    );
                  })}
                </ul>
              </CardContent>
            </Card>
          );
        })}
      </div>

      <p className="text-xs text-muted-foreground">
        Checklist state saved locally in this browser under{" "}
        <code className="font-mono">{STATE_KEY}</code>. Once Supabase is wired
        for HR, this will sync per-entity for the hiring manager and HR.
      </p>
    </div>
    <AlertConfirmPortal />
    </>
  );
}
