"use client";

import { useState, useTransition } from "react";
import { format } from "date-fns";
import { de } from "date-fns/locale";
import { NotdienstPlanStatus } from "@prisma/client";
import {
  ArrowRight,
  CheckSquare,
  Download,
  Loader2,
  RotateCcw,
  Send,
  Wand2,
} from "lucide-react";
import { toast } from "sonner";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import {
  generatePlanAction,
  publishPlanAction,
  updateAssignmentAction,
} from "./actions";

interface PlanViewProps {
  planId?: string;
  status?: NotdienstPlanStatus;
  days: {
    date: string;
    assignmentId: string | null;
    childId: string | null;
  }[];
  allChildren: {
    id: string;
    name: string;
    parentName: string;
  }[];
  familyStatuses: {
    id: string;
    name: string;
    childCount: number;
    selectedDays: {
      iso: string;
      label: string;
    }[];
  }[];
  requiredDays: number;
  respondedFamilies: number;
  openFamilies: number;
  totalFamilies: number;
  totalAvailabilitySlots: number;
  coverageFactor: number;
  closureCount: number;
  monthName: string;
}

export function PlanView({
  planId,
  status,
  days,
  allChildren,
  familyStatuses,
  requiredDays,
  respondedFamilies,
  openFamilies,
  totalFamilies,
  totalAvailabilitySlots,
  coverageFactor,
  closureCount,
  monthName,
}: PlanViewProps) {
  const [isPending, startTransition] = useTransition();
  const [activeTab, setActiveTab] = useState<"preview" | "manual">("preview");

  const responsePercent =
    totalFamilies > 0 ? Math.round((respondedFamilies / totalFamilies) * 100) : 0;

  const handleGenerate = () => {
    startTransition(async () => {
      const result = await generatePlanAction();
      if ("error" in result && result.error) {
        toast.error(result.error as string);
      } else {
        toast.success("Plan erfolgreich generiert.");
      }
    });
  };

  const handlePublish = () => {
    if (!planId) return;
    startTransition(async () => {
      const result = await publishPlanAction(planId);
      if ("error" in result && result.error) {
        toast.error(result.error as string);
      } else {
        toast.success("Plan veröffentlicht! Er ist nun fix.");
      }
    });
  };

  const handleAssignmentChange = (date: string, newChildId: string) => {
    if (!planId || status !== "DRAFT") return;
    const valueToSet = newChildId === "empty" ? null : newChildId;

    startTransition(async () => {
      const result = await updateAssignmentAction(planId, date, valueToSet);
      if ("error" in result && result.error) {
        toast.error(result.error as string);
      } else {
        toast.success("Zuteilung aktualisiert.");
      }
    });
  };

  if (!planId && respondedFamilies === 0) {
    return (
      <Card className="border-dashed">
        <div className="flex min-h-[280px] flex-col items-center justify-center p-8 text-center">
          <div className="mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-[var(--accent-soft)] text-[var(--accent-deep)]">
            <Wand2 className="h-7 w-7 [stroke-width:1.7]" />
          </div>
          <h3 className="mb-1 text-xl font-medium tracking-[-0.02em] text-[var(--ink)]">
            Noch keine Verfügbarkeiten
          </h3>
          <p className="mb-5 max-w-md text-sm leading-6 text-[var(--ink-soft)]">
            Für {monthName} hat noch keine Familie geantwortet. Verschicke
            zuerst Erinnerungen, damit die automatische Planung belastbar ist.
          </p>
          <div className="flex flex-wrap justify-center gap-2">
            <Button disabled={isPending} onClick={handleGenerate}>
              Trotzdem generieren
            </Button>
            <Button variant="ghost">
              <Send className="h-4 w-4 [stroke-width:1.7]" />
              Erinnerungen verschicken
            </Button>
          </div>
        </div>
      </Card>
    );
  }

  if (!planId) {
    return (
      <div className="space-y-5">
        <div className="grid grid-cols-[minmax(0,2fr)_minmax(300px,1fr)] gap-5 max-[1050px]:grid-cols-1">
          <Card className="p-0">
            <div className="border-b border-[var(--hairline-soft)] px-6 py-5">
              <div className="flex items-start justify-between gap-4">
                <div>
                  <h2 className="text-lg font-medium tracking-[-0.02em] text-[var(--ink)]">
                    Verfügbarkeiten Eltern
                  </h2>
                  <p className="mt-1 text-[13.5px] leading-5 text-[var(--ink-soft)]">
                    {respondedFamilies} von {totalFamilies} Familien haben
                    geantwortet · noch {openFamilies} offen
                  </p>
                </div>
                <span className="text-sm font-semibold tabular-nums text-[var(--ink-soft)]">
                  {responsePercent}%
                </span>
              </div>
              <div className="mt-4 h-1 overflow-hidden rounded-full bg-[var(--accent-soft)]">
                <div
                  className="h-full rounded-full bg-[var(--accent)]"
                  style={{ width: `${responsePercent}%` }}
                />
              </div>
            </div>

            <div className="divide-y divide-[var(--hairline-soft)]">
              {familyStatuses.map((family) => (
                <div
                  key={family.id}
                  className="group relative flex items-center gap-3 px-6 py-3.5 transition-colors hover:bg-[var(--surface-2)]"
                >
                  <div className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-[var(--accent-soft)] text-[11px] font-semibold uppercase text-[var(--accent-deep)]">
                    {family.name.slice(0, 1)}
                  </div>
                  <div className="min-w-0 flex-1">
                    <p className="truncate text-sm font-medium text-[var(--ink)]">
                      {family.name}
                    </p>
                    <p className="text-xs text-[var(--ink-muted)]">
                      {family.childCount} Kind
                      {family.childCount === 1 ? "" : "er"}
                    </p>
                  </div>
                  <FamilyStatusPill selectedDays={family.selectedDays.length} />
                  <div className="pointer-events-none absolute right-6 top-10 z-20 hidden max-w-xs rounded-lg bg-[oklch(0.22_0.015_45)] px-3 py-2 text-xs leading-5 text-white shadow-lg group-hover:block">
                    {family.selectedDays.length > 0
                      ? family.selectedDays.map((day) => day.label).join(" · ")
                      : "Noch keine Tage markiert"}
                  </div>
                </div>
              ))}
            </div>

            <div className="border-t border-[var(--hairline-soft)] px-6 py-4">
              <Button variant="ghost" disabled={openFamilies === 0}>
                <Send className="h-4 w-4 [stroke-width:1.7]" />
                Erinnerung an offene senden ({openFamilies})
              </Button>
            </div>
          </Card>

          <Card className="p-6">
            <div>
              <h2 className="text-lg font-medium tracking-[-0.02em] text-[var(--ink)]">
                Bedarfs-Übersicht
              </h2>
              <p className="mt-1 text-[13.5px] text-[var(--ink-soft)]">
                Planungsgrundlage für {monthName}.
              </p>
            </div>
            <div className="mt-5 grid gap-4">
              <PlanMetric
                label={`Tage benötigt in ${monthName}`}
                value={requiredDays}
              />
              <PlanMetric
                label="Verfügbarkeiten gesamt"
                value={totalAvailabilitySlots}
              />
              <PlanMetric
                label="Überdeckung"
                value={`${coverageFactor.toFixed(1)}×`}
                badge="good"
              />
              <PlanMetric label="Schließtage" value={closureCount} />
            </div>
            <div className="mt-5 rounded-lg border border-[var(--hairline)] bg-[var(--surface-2)] px-4 py-3 text-sm leading-6 text-[var(--ink-soft)]">
              {coverageFactor >= 1
                ? "Du hast genug Verfügbarkeiten für einen Plan."
                : "Die Verfügbarkeiten reichen noch nicht für einen belastbaren Plan."}
            </div>
          </Card>
        </div>

        <Card variant="featured" className="sticky bottom-6 z-10 p-5">
          <div className="flex items-center justify-between gap-5 max-[760px]:flex-col max-[760px]:items-start">
            <div className="flex gap-4">
              <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-[var(--accent-soft)] text-[var(--accent-deep)]">
                <Wand2 className="h-5 w-5 [stroke-width:1.7]" />
              </div>
              <div>
                <h3 className="text-lg font-medium tracking-[-0.02em] text-[var(--ink)]">
                  Plan automatisch generieren
                </h3>
                <p className="mt-1 text-[13.5px] text-[var(--ink-soft)]">
                  Verteilt {requiredDays} Notdiensttage fair auf{" "}
                  {respondedFamilies} Familien.
                </p>
                <details className="mt-3 text-xs text-[var(--ink-soft)]">
                  <summary className="cursor-pointer font-semibold text-[var(--accent-deep)]">
                    Faire Verteilung berücksichtigt
                  </summary>
                  <div className="mt-2 flex flex-wrap gap-2">
                    <span>☑ Quote pro Familie</span>
                    <span>☑ Bevorzugte Tage</span>
                    <span>☐ Geschwister-Familien zusammen</span>
                  </div>
                </details>
              </div>
            </div>
            <Button onClick={handleGenerate} disabled={isPending}>
              {isPending && (
                <Loader2 className="h-4 w-4 animate-spin [stroke-width:1.7]" />
              )}
              Generieren
              <ArrowRight className="h-4 w-4 [stroke-width:1.7]" />
            </Button>
          </div>
        </Card>
      </div>
    );
  }

  const isDraft = status === "DRAFT";

  return (
    <div className="space-y-5">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <div className="inline-flex overflow-hidden rounded-full border border-[var(--hairline)] bg-[var(--surface)]">
          <TabButton
            active={activeTab === "preview"}
            onClick={() => setActiveTab("preview")}
          >
            Plan-Vorschau
          </TabButton>
          <TabButton
            active={activeTab === "manual"}
            onClick={() => setActiveTab("manual")}
            withDivider
          >
            Manuell zuweisen
          </TabButton>
        </div>

        <div className="flex flex-wrap gap-2">
          {isDraft && (
            <Button onClick={handlePublish} disabled={isPending}>
              {isPending && (
                <Loader2 className="h-4 w-4 animate-spin [stroke-width:1.7]" />
              )}
              <CheckSquare className="h-4 w-4 [stroke-width:1.7]" />
              Plan veröffentlichen
            </Button>
          )}
          <Button variant="ghost">
            <Download className="h-4 w-4 [stroke-width:1.7]" />
            Als PDF exportieren
          </Button>
          <Button
            variant="ghost"
            className="text-[var(--danger)] hover:bg-[var(--danger-soft)] hover:text-[var(--danger)]"
          >
            <RotateCcw className="h-4 w-4 [stroke-width:1.7]" />
            Plan zurücksetzen
          </Button>
        </div>
      </div>

      <Card className="flex items-center justify-between p-4">
        <div className="flex items-center gap-3">
          <Badge variant={isDraft ? "warning" : "success"}>
            {isDraft ? "Entwurf" : "Veröffentlicht"}
          </Badge>
          <span className="text-sm text-[var(--ink-soft)]">
            {isDraft
              ? "Du kannst die Liste jetzt manuell anpassen."
              : "Dieser Plan ist verbindlich."}
          </span>
        </div>
      </Card>

      {activeTab === "preview" ? (
        <PlanPreviewTable days={days} allChildren={allChildren} />
      ) : (
        <ManualAssignmentTable
          days={days}
          allChildren={allChildren}
          isDraft={isDraft}
          isPending={isPending}
          onAssignmentChange={handleAssignmentChange}
        />
      )}
    </div>
  );
}

function FamilyStatusPill({ selectedDays }: { selectedDays: number }) {
  if (selectedDays === 0) {
    return (
      <span className="rounded-full border border-[var(--warn)] bg-[var(--warn-soft)] px-2.5 py-1 text-[11px] font-semibold text-[var(--warn)]">
        Noch nicht
      </span>
    );
  }

  return (
    <span className="rounded-full border border-[var(--good)] bg-[var(--good-soft)] px-2.5 py-1 text-[11px] font-semibold text-[var(--good)]">
      {selectedDays} Tage
    </span>
  );
}

function PlanMetric({
  label,
  value,
  badge,
}: {
  label: string;
  value: number | string;
  badge?: "good";
}) {
  return (
    <div className="flex items-center justify-between gap-4 border-b border-[var(--hairline-soft)] pb-3 last:border-b-0 last:pb-0">
      <span className="text-[13.5px] text-[var(--ink-soft)]">{label}</span>
      {badge ? (
        <span className="rounded-full border border-[var(--good)] bg-[var(--good-soft)] px-2.5 py-1 text-sm font-semibold text-[var(--good)] tabular-nums">
          {value}
        </span>
      ) : (
        <span className="text-2xl font-medium tracking-[-0.025em] text-[var(--ink)] tabular-nums">
          {value}
        </span>
      )}
    </div>
  );
}

function TabButton({
  active,
  withDivider,
  onClick,
  children,
}: {
  active: boolean;
  withDivider?: boolean;
  onClick: () => void;
  children: React.ReactNode;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={[
        "h-9 px-4 text-[13px] font-semibold transition focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--focus-ring)]",
        withDivider ? "border-l border-[var(--hairline-soft)]" : "",
        active
          ? "bg-[var(--accent-soft)] text-[var(--accent-deep)]"
          : "text-[var(--ink-soft)] hover:bg-[var(--surface-2)]",
      ].join(" ")}
    >
      {children}
    </button>
  );
}

function PlanPreviewTable({
  days,
  allChildren,
}: Pick<PlanViewProps, "days" | "allChildren">) {
  return (
    <Card className="overflow-hidden p-0">
      <div className="grid grid-cols-[1.1fr_1fr_2fr_1.6fr_1fr] border-b border-[var(--hairline-soft)] bg-[var(--surface-2)] p-4 text-[11px] font-semibold uppercase text-[var(--ink-muted)] [letter-spacing:0.12em]">
        <div>Datum</div>
        <div>Wochentag</div>
        <div>Zugewiesen</div>
        <div>Backup</div>
        <div>Status</div>
      </div>
      <div className="divide-y divide-[var(--hairline-soft)]">
        {days.map((day) => {
          const dateObj = new Date(day.date);
          const assignedChild = allChildren.find(
            (child) => child.id === day.childId,
          );

          return (
            <div
              key={day.date}
              className="grid cursor-pointer grid-cols-[1.1fr_1fr_2fr_1.6fr_1fr] items-center p-4 text-sm transition-colors hover:bg-[var(--surface-2)]"
            >
              <div className="font-medium tabular-nums text-[var(--ink)]">
                {format(dateObj, "dd.MM.", { locale: de })}
              </div>
              <div className="text-[var(--ink-soft)]">
                {format(dateObj, "EEEE", { locale: de })}
              </div>
              <div className="text-[var(--ink)]">
                {assignedChild ? assignedChild.parentName : "Unbesetzt"}
                {assignedChild && (
                  <span className="ml-1 text-[var(--ink-muted)]">
                    ({assignedChild.name})
                  </span>
                )}
              </div>
              <div className="italic text-[var(--ink-faint)]">Noch offen</div>
              <div>
                <Badge variant={assignedChild ? "success" : "destructive"}>
                  {assignedChild ? "Besetzt" : "Offen"}
                </Badge>
              </div>
            </div>
          );
        })}
      </div>
    </Card>
  );
}

function ManualAssignmentTable({
  days,
  allChildren,
  isDraft,
  isPending,
  onAssignmentChange,
}: Pick<PlanViewProps, "days" | "allChildren"> & {
  isDraft: boolean;
  isPending: boolean;
  onAssignmentChange: (date: string, newChildId: string) => void;
}) {
  return (
    <Card className="overflow-hidden p-0">
      <div className="grid grid-cols-[1fr_2fr] border-b border-[var(--hairline-soft)] bg-[var(--surface-2)] p-4 text-[11px] font-semibold uppercase text-[var(--ink-muted)] [letter-spacing:0.12em]">
        <div>Datum</div>
        <div>Eingeteilte Familie</div>
      </div>
      <div className="divide-y divide-[var(--hairline-soft)]">
        {days.map((day) => {
          const dateObj = new Date(day.date);
          const assignedChild = allChildren.find(
            (child) => child.id === day.childId,
          );

          return (
            <div
              key={day.date}
              className="grid grid-cols-[1fr_2fr] items-center p-4 transition-colors hover:bg-[var(--surface-2)]"
            >
              <div className="font-medium text-[var(--ink)]">
                {format(dateObj, "EE, dd.MM.", { locale: de })}
              </div>
              <div>
                {isDraft ? (
                  <select
                    className="w-full max-w-sm rounded-lg border border-[var(--hairline)] bg-[var(--surface)] px-3 py-1.5 text-sm text-[var(--ink)] ring-offset-[var(--surface)] hover:border-[var(--accent-mid)] focus-visible:border-[var(--accent)] focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--focus-ring)]"
                    value={day.childId || "empty"}
                    disabled={isPending}
                    onChange={(event) =>
                      onAssignmentChange(day.date, event.target.value)
                    }
                  >
                    <option value="empty">-- Unbesetzt --</option>
                    {allChildren.map((child) => (
                      <option key={child.id} value={child.id}>
                        {child.parentName} ({child.name})
                      </option>
                    ))}
                  </select>
                ) : assignedChild ? (
                  <span className="text-sm text-[var(--ink)]">
                    {assignedChild.parentName}{" "}
                    <span className="text-[var(--ink-muted)]">
                      ({assignedChild.name})
                    </span>
                  </span>
                ) : (
                  <span className="text-sm font-medium text-[var(--danger)]">
                    Unbesetzt!
                  </span>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </Card>
  );
}
