import { useEffect, useMemo, useState } from "react";
import { createFileRoute } from "@tanstack/react-router";
import { ArrowDown, ArrowUp, Pencil, Plus, Search, Trash2 } from "lucide-react";
import { toast } from "sonner";

import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Page } from "@/components/app/Page";
import { EmptyState, PageHeading } from "@/components/app/Primitives";
import { StatusPill } from "@/components/app/StatusPill";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { MasterRecordSheet } from "@/features/master-types/components/MasterRecordSheet";
import { MasterTypeSheet } from "@/features/master-types/components/MasterTypeSheet";
import {
  useCreateMasterRecord,
  useCreateMasterType,
  useDeleteMasterRecord,
  useMasterTypeRecords,
  useMasterTypes,
  useUpdateMasterRecord,
  useUpdateMasterType,
  type MasterRecord,
  type MasterType,
} from "@/features/master-types/api";
import { ApiClientError } from "@/lib/api";
import { cn } from "@/lib/utils";

export const Route = createFileRoute("/master-types")({
  head: () => ({
    meta: [
      { title: "Master Types | KareVoyage Operations" },
      {
        name: "description",
        content: "One reusable framework for every reference list the portal needs.",
      },
      { property: "og:title", content: "Master Types | KareVoyage Operations" },
      {
        property: "og:description",
        content: "Manage document types, payment modes, room types and every other lookup list.",
      },
    ],
  }),
  component: MasterTypesPage,
});

function onApiError(err: unknown, fallback: string) {
  toast.error(err instanceof ApiClientError ? err.message : fallback);
}

function MasterTypesPage() {
  const { data: masterTypes = [], isLoading: masterTypesLoading } = useMasterTypes();
  const [selectedId, setSelectedId] = useState<string>("");
  const [masterQuery, setMasterQuery] = useState("");
  const [recordQuery, setRecordQuery] = useState("");
  const [showInactive, setShowInactive] = useState(true);

  useEffect(() => {
    if (!selectedId && masterTypes.length > 0) setSelectedId(masterTypes[0]!.id);
  }, [selectedId, masterTypes]);

  const { data: masterRecords = [], isLoading: recordsLoading } = useMasterTypeRecords(
    selectedId || undefined,
  );

  const createMasterType = useCreateMasterType();
  const updateMasterType = useUpdateMasterType();
  const createRecord = useCreateMasterRecord(selectedId);
  const updateRecord = useUpdateMasterRecord(selectedId);
  const deleteRecord = useDeleteMasterRecord(selectedId);

  const [masterSheetOpen, setMasterSheetOpen] = useState(false);
  const [editingMaster, setEditingMaster] = useState<MasterType | undefined>(undefined);
  const [recordSheetOpen, setRecordSheetOpen] = useState(false);
  const [editingRecord, setEditingRecord] = useState<MasterRecord | undefined>(undefined);
  const [deleteTarget, setDeleteTarget] = useState<MasterRecord | undefined>(undefined);

  const filteredMasters = useMemo(() => {
    const q = masterQuery.trim().toLowerCase();
    if (!q) return masterTypes;
    return masterTypes.filter((m) => `${m.name} ${m.key}`.toLowerCase().includes(q));
  }, [masterTypes, masterQuery]);

  const selectedMaster = masterTypes.find((m) => m.id === selectedId);

  const sortedRecords = useMemo(
    () => [...masterRecords].sort((a, b) => a.order - b.order),
    [masterRecords],
  );

  const visibleRecords = useMemo(() => {
    const q = recordQuery.trim().toLowerCase();
    return sortedRecords.filter((r) => {
      if (!showInactive && !r.active) return false;
      if (!q) return true;
      return `${r.code} ${r.name} ${r.description}`.toLowerCase().includes(q);
    });
  }, [sortedRecords, recordQuery, showInactive]);

  const moveRecord = (record: MasterRecord, direction: -1 | 1) => {
    const idx = sortedRecords.findIndex((r) => r.id === record.id);
    const swapWith = sortedRecords[idx + direction];
    if (!swapWith) return;
    updateRecord.mutate({ id: record.id, order: swapWith.order });
    updateRecord.mutate({ id: swapWith.id, order: record.order });
  };

  const toggleRecordActive = (record: MasterRecord) => {
    updateRecord.mutate(
      { id: record.id, active: !record.active },
      {
        onSuccess: () =>
          toast.success(`${record.name} ${record.active ? "deactivated" : "activated"}.`),
        onError: (err) => onApiError(err, "Couldn't update the record."),
      },
    );
  };

  const toggleMasterActive = () => {
    if (!selectedMaster) return;
    updateMasterType.mutate(
      { id: selectedMaster.id, active: !selectedMaster.active },
      {
        onSuccess: () =>
          toast.success(
            `${selectedMaster.name} ${selectedMaster.active ? "deactivated" : "activated"}.`,
          ),
        onError: (err) => onApiError(err, "Couldn't update the master type."),
      },
    );
  };

  return (
    <Page className="space-y-6">
      <PageHeading
        title="Master Types"
        description="One reusable framework for every list the application needs — select a master on the left to manage its records on the right."
        actions={
          <Button
            className="gap-1.5"
            onClick={() => {
              setEditingMaster(undefined);
              setMasterSheetOpen(true);
            }}
          >
            <Plus className="h-4 w-4" /> New master type
          </Button>
        }
      />

      <div className="grid gap-5 lg:grid-cols-[300px_1fr]">
        {/* Master list */}
        <div className="rounded-xl border border-border bg-surface">
          <div className="border-b border-border p-3">
            <div className="relative">
              <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input
                value={masterQuery}
                onChange={(e) => setMasterQuery(e.target.value)}
                placeholder="Search master…"
                className="h-9 pl-9"
              />
            </div>
          </div>
          <div className="flex items-center justify-between px-4 py-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground">
            <span>Master</span>
            <span>Records</span>
          </div>
          <div className="max-h-[65vh] overflow-y-auto kv-scroll">
            {masterTypesLoading ? (
              <p className="px-4 py-8 text-center text-sm text-muted-foreground">
                Loading master types…
              </p>
            ) : filteredMasters.length === 0 ? (
              <p className="px-4 py-8 text-center text-sm text-muted-foreground">
                {masterQuery ? "No master types match your search." : "No master types yet."}
              </p>
            ) : (
              filteredMasters.map((m) => {
                const active = m.id === selectedId;
                return (
                  <button
                    key={m.id}
                    type="button"
                    onClick={() => setSelectedId(m.id)}
                    className={cn(
                      "flex w-full items-center justify-between gap-3 border-l-2 border-transparent px-4 py-2.5 text-left transition-colors hover:bg-muted/60",
                      active && "border-primary bg-primary-soft",
                    )}
                  >
                    <span className="min-w-0">
                      <span
                        className={cn(
                          "block truncate text-sm font-medium",
                          active ? "text-accent-foreground" : "text-foreground",
                          !m.active && "opacity-60",
                        )}
                      >
                        {m.name}
                      </span>
                      <span className="block truncate font-mono text-[11px] text-muted-foreground">
                        {m.key}
                      </span>
                    </span>
                    <span className="shrink-0 rounded-full bg-muted px-2 py-0.5 text-xs tabular-nums text-muted-foreground">
                      {m.recordCount ?? 0}
                    </span>
                  </button>
                );
              })
            )}
          </div>
        </div>

        {/* Selected master detail */}
        <div className="rounded-xl border border-border bg-surface">
          {!selectedMaster ? (
            <EmptyState
              title={masterTypesLoading ? "Loading…" : "No master types yet"}
              message={
                masterTypesLoading
                  ? "Fetching master types from the server."
                  : "Create your first master type to start building reference lists."
              }
              action={
                masterTypesLoading ? undefined : (
                  <Button
                    onClick={() => {
                      setEditingMaster(undefined);
                      setMasterSheetOpen(true);
                    }}
                  >
                    New master type
                  </Button>
                )
              }
            />
          ) : (
            <>
              <div className="flex flex-wrap items-start justify-between gap-4 border-b border-border p-5">
                <div className="min-w-0">
                  <div className="flex flex-wrap items-center gap-2">
                    <h2 className="text-lg font-semibold text-foreground">{selectedMaster.name}</h2>
                    <StatusPill value={selectedMaster.active ? "Active" : "Inactive"} />
                  </div>
                  {selectedMaster.description ? (
                    <p className="mt-1 text-sm text-muted-foreground">
                      {selectedMaster.description}
                    </p>
                  ) : null}
                  <p className="mt-1 font-mono text-xs text-muted-foreground">
                    key: {selectedMaster.key}
                  </p>
                </div>
                <div className="flex flex-wrap items-center gap-2">
                  <Button
                    variant="outline"
                    size="sm"
                    className="gap-1.5"
                    onClick={() => {
                      setEditingMaster(selectedMaster);
                      setMasterSheetOpen(true);
                    }}
                  >
                    <Pencil className="h-3.5 w-3.5" /> Edit master
                  </Button>
                  <Button variant="outline" size="sm" onClick={toggleMasterActive}>
                    {selectedMaster.active ? "Deactivate" : "Activate"}
                  </Button>
                  <Button
                    size="sm"
                    className="gap-1.5"
                    onClick={() => {
                      setEditingRecord(undefined);
                      setRecordSheetOpen(true);
                    }}
                  >
                    <Plus className="h-3.5 w-3.5" /> Add record
                  </Button>
                </div>
              </div>

              <div className="flex flex-wrap items-center gap-3 p-4">
                <div className="relative min-w-[220px] flex-1 sm:max-w-xs">
                  <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                  <Input
                    value={recordQuery}
                    onChange={(e) => setRecordQuery(e.target.value)}
                    placeholder="Search records…"
                    className="h-9 pl-9"
                  />
                </div>
                <div className="ml-auto flex items-center gap-2">
                  <Label
                    htmlFor="show-inactive"
                    className="text-sm font-normal text-muted-foreground"
                  >
                    Show inactive
                  </Label>
                  <Switch
                    id="show-inactive"
                    checked={showInactive}
                    onCheckedChange={setShowInactive}
                  />
                </div>
              </div>

              <div className="overflow-x-auto kv-scroll border-t border-border">
                <table className="w-full min-w-[720px] border-collapse text-sm">
                  <thead>
                    <tr className="border-b border-border bg-surface-muted/60 text-left text-xs font-semibold text-muted-foreground">
                      <th className="px-4 py-3">Code</th>
                      <th className="px-4 py-3">Name</th>
                      <th className="px-4 py-3">Description</th>
                      <th className="px-4 py-3 text-right">Order</th>
                      <th className="px-4 py-3">Status</th>
                      <th className="px-4 py-3 text-right">Action</th>
                    </tr>
                  </thead>
                  <tbody>
                    {visibleRecords.map((r, i) => (
                      <tr key={r.id} className="border-b border-border/70 last:border-0">
                        <td className="px-4 py-2.5 font-mono text-xs text-muted-foreground">
                          {r.code}
                        </td>
                        <td className="px-4 py-2.5 font-medium text-foreground">{r.name}</td>
                        <td className="px-4 py-2.5 text-muted-foreground">
                          {r.description || "—"}
                        </td>
                        <td className="px-4 py-2.5 text-right tabular-nums text-muted-foreground">
                          {r.order}
                        </td>
                        <td className="px-4 py-2.5">
                          <StatusPill value={r.active ? "Active" : "Inactive"} />
                        </td>
                        <td className="px-4 py-2.5">
                          <div className="flex items-center justify-end gap-1">
                            <Button
                              variant="outline"
                              size="sm"
                              className="h-7 px-2 text-xs"
                              onClick={() => {
                                setEditingRecord(r);
                                setRecordSheetOpen(true);
                              }}
                            >
                              Edit
                            </Button>
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-7 w-7"
                              aria-label="Move up"
                              disabled={i === 0}
                              onClick={() => moveRecord(r, -1)}
                            >
                              <ArrowUp className="h-3.5 w-3.5" />
                            </Button>
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-7 w-7"
                              aria-label="Move down"
                              disabled={i === visibleRecords.length - 1}
                              onClick={() => moveRecord(r, 1)}
                            >
                              <ArrowDown className="h-3.5 w-3.5" />
                            </Button>
                            <Button
                              variant="outline"
                              size="sm"
                              className="h-7 px-2 text-xs"
                              onClick={() => toggleRecordActive(r)}
                            >
                              {r.active ? "Deactivate" : "Activate"}
                            </Button>
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-7 w-7 text-destructive hover:text-destructive"
                              aria-label={`Delete ${r.name}`}
                              onClick={() => setDeleteTarget(r)}
                            >
                              <Trash2 className="h-3.5 w-3.5" />
                            </Button>
                          </div>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
                {recordsLoading ? (
                  <p className="px-4 py-8 text-center text-sm text-muted-foreground">
                    Loading records…
                  </p>
                ) : visibleRecords.length === 0 ? (
                  <EmptyState
                    title="No records"
                    message={
                      recordQuery
                        ? "Nothing matches your search."
                        : `Add the first record to ${selectedMaster.name}.`
                    }
                    action={
                      recordQuery ? undefined : (
                        <Button
                          size="sm"
                          onClick={() => {
                            setEditingRecord(undefined);
                            setRecordSheetOpen(true);
                          }}
                        >
                          Add record
                        </Button>
                      )
                    }
                  />
                ) : null}
              </div>
            </>
          )}
        </div>
      </div>

      <MasterTypeSheet
        open={masterSheetOpen}
        onOpenChange={setMasterSheetOpen}
        masterType={editingMaster}
        existingKeys={masterTypes.map((m) => m.key)}
        onSave={(values) => {
          if (editingMaster) {
            updateMasterType.mutate(
              {
                id: editingMaster.id,
                name: values.name,
                description: values.description,
                active: values.active,
              },
              {
                onSuccess: () => toast.success(`${values.name} updated.`),
                onError: (err) => onApiError(err, "Couldn't update the master type."),
              },
            );
          } else {
            createMasterType.mutate(
              { name: values.name, description: values.description, active: values.active },
              {
                onSuccess: (created) => {
                  setSelectedId(created.id);
                  toast.success(`${values.name} created.`);
                },
                onError: (err) => onApiError(err, "Couldn't create the master type."),
              },
            );
          }
        }}
      />

      {selectedMaster ? (
        <MasterRecordSheet
          open={recordSheetOpen}
          onOpenChange={setRecordSheetOpen}
          masterName={selectedMaster.name}
          record={editingRecord}
          existingCodes={sortedRecords.map((r) => r.code)}
          nextOrder={sortedRecords.length ? Math.max(...sortedRecords.map((r) => r.order)) + 1 : 1}
          onSave={(values) => {
            if (editingRecord) {
              updateRecord.mutate(
                { id: editingRecord.id, ...values },
                {
                  onSuccess: () => toast.success(`${values.name} updated.`),
                  onError: (err) => onApiError(err, "Couldn't update the record."),
                },
              );
            } else {
              createRecord.mutate(values, {
                onSuccess: () => toast.success(`${values.name} added to ${selectedMaster.name}.`),
                onError: (err) => onApiError(err, "Couldn't create the record."),
              });
            }
          }}
        />
      ) : null}

      <AlertDialog open={!!deleteTarget} onOpenChange={(o) => !o && setDeleteTarget(undefined)}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete record?</AlertDialogTitle>
            <AlertDialogDescription>
              {deleteTarget
                ? `"${deleteTarget.name}" will be permanently removed from ${selectedMaster?.name}. This can't be undone.`
                : ""}
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
              onClick={() => {
                if (!deleteTarget) return;
                deleteRecord.mutate(deleteTarget.id, {
                  onSuccess: () => toast.success(`${deleteTarget.name} deleted.`),
                  onError: (err) => onApiError(err, "Couldn't delete the record."),
                });
                setDeleteTarget(undefined);
              }}
            >
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </Page>
  );
}
