"use client";

import { useState, useTransition } from "react";
import { BellRing, Loader2 } from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  checkAndSendDutyReminders,
  upsertDutyAssignment,
} from "./actions";

const UNASSIGNED = "__unassigned__";

export type DutyPlanWeekDto = {
  key: string;
  label: string;
  startDate: string;
  endDate: string;
};

export type DutyPlanDutyTypeDto = {
  id: string;
  name: string;
  description: string | null;
};

export type DutyPlanFamilyDto = {
  id: string;
  name: string;
};

export type DutyPlanAssignmentDto = {
  id: string;
  dutyTypeId: string;
  familyId: string;
  startDate: string;
};

export function DutyPlanner({
  weeks,
  dutyTypes,
  families,
  assignments,
}: {
  weeks: DutyPlanWeekDto[];
  dutyTypes: DutyPlanDutyTypeDto[];
  families: DutyPlanFamilyDto[];
  assignments: DutyPlanAssignmentDto[];
}) {
  const [isPending, startTransition] = useTransition();
  const [pendingCell, setPendingCell] = useState<string | null>(null);

  const assignmentByCell = new Map(
    assignments.map((assignment) => [
      `${assignment.startDate}:${assignment.dutyTypeId}`,
      assignment,
    ]),
  );

  function handleAssignmentChange(
    week: DutyPlanWeekDto,
    dutyTypeId: string,
    value: string,
  ) {
    const cellKey = `${week.startDate}:${dutyTypeId}`;
    setPendingCell(cellKey);

    startTransition(async () => {
      const result = await upsertDutyAssignment({
        dutyTypeId,
        familyId: value === UNASSIGNED ? null : value,
        startDate: week.startDate,
        endDate: week.endDate,
      });

      if (result.error) {
        toast.error(result.error);
      } else {
        toast.success(
          value === UNASSIGNED
            ? "Zuweisung entfernt"
            : "Dienstplan aktualisiert",
        );
      }
      setPendingCell(null);
    });
  }

  function sendReminders() {
    startTransition(async () => {
      const result = await checkAndSendDutyReminders();
      if (result.error) {
        toast.error(result.error);
        return;
      }

      toast.success(
        `Erinnerungen versendet: ${result.sent ?? 0}. Ohne Empfaenger: ${
          result.skipped ?? 0
        }.`,
      );

      if (result.errors?.length) {
        toast.warning(`${result.errors.length} Erinnerung(en) fehlgeschlagen.`);
      }
    });
  }

  if (dutyTypes.length === 0) {
    return (
      <div className="rounded-lg border border-dashed border-[var(--hairline)] bg-[var(--surface-2)] p-8 text-center">
        <p className="text-sm font-medium text-[var(--ink)]">
          Noch keine Diensttypen
        </p>
        <p className="mt-1 text-sm text-[var(--ink-soft)]">
          Lege zuerst einen Diensttyp an, danach erscheint hier das Planungsgrid.
        </p>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      <div className="flex justify-end">
        <Button
          type="button"
          variant="outline"
          size="sm"
          onClick={sendReminders}
          disabled={isPending}
        >
          {isPending ? (
            <Loader2 className="h-4 w-4 animate-spin [stroke-width:1.7]" />
          ) : (
            <BellRing className="h-4 w-4 [stroke-width:1.7]" />
          )}
          Reminder diese Woche senden
        </Button>
      </div>

      <div className="overflow-x-auto rounded-lg border border-[var(--hairline)]">
        <table className="w-full min-w-[760px] border-collapse text-[13.5px] text-[var(--ink)]">
          <thead>
            <tr className="border-b border-[var(--hairline-soft)] bg-[var(--surface-2)]">
              <th className="sticky left-0 z-10 w-56 bg-[var(--surface-2)] px-4 py-3 text-left text-[11px] font-semibold uppercase text-[var(--ink-muted)] [letter-spacing:0.12em]">
                Woche
              </th>
              {dutyTypes.map((dutyType) => (
                <th
                  key={dutyType.id}
                  className="min-w-56 px-4 py-3 text-left font-medium text-[var(--ink)]"
                >
                  <div>{dutyType.name}</div>
                  {dutyType.description && (
                    <div className="mt-1 line-clamp-1 text-xs font-normal text-[var(--ink-muted)]">
                      {dutyType.description}
                    </div>
                  )}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {weeks.map((week) => (
              <tr
                key={week.key}
                className="border-b border-[var(--hairline-soft)] last:border-b-0 hover:bg-[var(--surface-2)]"
              >
                <td className="sticky left-0 z-10 bg-[var(--surface)] px-4 py-3 font-medium">
                  {week.label}
                </td>
                {dutyTypes.map((dutyType) => {
                  const cellKey = `${week.startDate}:${dutyType.id}`;
                  const currentAssignment = assignmentByCell.get(cellKey);
                  return (
                    <td key={cellKey} className="px-4 py-3">
                      <Select
                        value={currentAssignment?.familyId ?? UNASSIGNED}
                        onValueChange={(value) =>
                          handleAssignmentChange(week, dutyType.id, value)
                        }
                        disabled={isPending && pendingCell === cellKey}
                      >
                        <SelectTrigger className="h-9">
                          <SelectValue placeholder="Familie wählen" />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value={UNASSIGNED}>
                            Nicht zugewiesen
                          </SelectItem>
                          {families.map((family) => (
                            <SelectItem key={family.id} value={family.id}>
                              {family.name}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </td>
                  );
                })}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}
