"use client";

import { useMemo, useState } from "react";
import { keepPreviousData, useMutation, useQuery } from "@tanstack/react-query";
import type { ColumnDef } from "@tanstack/react-table";
import { parseAsInteger, parseAsString, useQueryStates } from "nuqs";
import { toast } from "sonner";
import { hasAnyPermission } from "@/lib/auth/authorization";
import { getSortingStateParser } from "@/lib/parsers";
import { formatDate } from "@/lib/format";
import { useDataTable } from "@/hooks/use-data-table";
import { cn } from "@/lib/utils";
import { Icons } from "@/components/icons";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { DataTable } from "@/components/ui/table/data-table";
import { DataTableToolbar } from "@/components/ui/table/data-table-toolbar";
import { DataTableColumnHeader } from "@/components/ui/table/data-table-column-header";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import {
  activateTrainingPolicyMutation,
  cloneTrainingPolicyMutation,
  deactivateTrainingPolicyMutation,
} from "../api/mutations";
import {
  trainingPolicyByIdQueryOptions,
  trainingPolicyHistoryQueryOptions,
  trainingPoliciesQueryOptions,
} from "../api/queries";
import type { TrainingPolicy } from "../api/types";
import { TrainingPolicyForm } from "./training-policy-form";

const columnIds = [
  "display_name",
  "year",
  "total_hours",
  "status",
  "updated_at",
  "actions",
];

function formatHours(value: number) {
  return value % 1 === 0 ? value.toFixed(0) : value.toFixed(1);
}

function getStatusLabel(policy: TrainingPolicy) {
  return policy.is_active ? "ใช้งาน" : "ไม่ใช้งาน";
}

function getColumns({
  canManage,
  onView,
  onEdit,
}: {
  canManage: boolean;
  onView: (policy: TrainingPolicy) => void;
  onEdit: (policy: TrainingPolicy) => void;
}): ColumnDef<TrainingPolicy>[] {
  return [
    {
      id: "display_name",
      accessorKey: "display_name",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title="นโยบาย" />
      ),
      cell: ({ row }) => (
        <div className="flex min-w-0 flex-col">
          <span className="truncate font-medium">
            {row.original.display_name}
          </span>
          <span className="text-muted-foreground text-xs">
            ปี {row.original.year}
          </span>
        </div>
      ),
      meta: {
        label: "ค้นหานโยบาย",
        placeholder: "ค้นหาจากปีนโยบาย...",
        variant: "text" as const,
        icon: Icons.search,
      },
      enableColumnFilter: true,
    },
    {
      id: "year",
      accessorKey: "year",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title="ปี" />
      ),
      cell: ({ row }) => (
        <span className="font-medium">{row.original.year}</span>
      ),
    },
    {
      id: "total_hours",
      accessorKey: "total_hours",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title="ชั่วโมงรวม" />
      ),
      cell: ({ row }) => (
        <span>{formatHours(row.original.total_hours)} ชั่วโมง</span>
      ),
    },
    {
      id: "status",
      accessorKey: "status",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title="สถานะ" />
      ),
      cell: ({ row }) => (
        <Badge variant={row.original.is_active ? "default" : "secondary"}>
          {getStatusLabel(row.original)}
        </Badge>
      ),
      meta: {
        label: "สถานะ",
        variant: "multiSelect" as const,
        options: [
          { label: "ใช้งาน", value: "active" },
          { label: "ไม่ใช้งาน", value: "inactive" },
        ],
      },
      enableColumnFilter: true,
    },
    {
      id: "updated_at",
      accessorKey: "updated_at",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title="อัปเดตล่าสุด" />
      ),
      cell: ({ row }) => (
        <div className="flex min-w-0 flex-col">
          <span>{formatDate(row.original.updated_at)}</span>
          <span className="text-muted-foreground text-xs">
            {row.original.updated_by_name ?? "-"}
          </span>
        </div>
      ),
    },
    {
      id: "actions",
      header: () => <span className="sr-only">จัดการ</span>,
      cell: ({ row }) => (
        <div className="flex justify-end">
          <TrainingPolicyActionMenu
            policy={row.original}
            canManage={canManage}
            onView={onView}
            onEdit={onEdit}
          />
        </div>
      ),
      enableSorting: false,
      enableHiding: false,
      size: 50,
      meta: {
        label: "จัดการ",
        headerClassName: "w-[60px] px-3 text-right",
        cellClassName: "w-[60px] px-3 text-right",
      },
    },
  ];
}

export function TrainingPolicyPage({
  permissions,
}: {
  permissions: readonly string[];
}) {
  const canManage = hasAnyPermission(permissions, ["training_policy:write"]);
  const [formPolicy, setFormPolicy] = useState<TrainingPolicy | null>(null);
  const [detailPolicyId, setDetailPolicyId] = useState<number | null>(null);
  const [formOpen, setFormOpen] = useState(false);
  const [detailOpen, setDetailOpen] = useState(false);
  const [params] = useQueryStates({
    page: parseAsInteger.withDefault(1),
    perPage: parseAsInteger.withDefault(10),
    search: parseAsString,
    status: parseAsString,
    sort: getSortingStateParser(columnIds).withDefault([]),
  });

  const filters = {
    page: params.page,
    limit: params.perPage,
    ...(params.search && { search: params.search }),
    ...(params.status && { status: params.status }),
    ...(params.sort.length > 0 && { sort: JSON.stringify(params.sort) }),
  };

  const { data, error, isFetching, isPending } = useQuery({
    ...trainingPoliciesQueryOptions(filters),
    placeholderData: keepPreviousData,
  });

  const columns = useMemo(
    () =>
      getColumns({
        canManage,
        onView: (policy) => {
          setDetailPolicyId(policy.id);
          setDetailOpen(true);
        },
        onEdit: (policy) => {
          setFormPolicy(policy);
          setFormOpen(true);
        },
      }),
    [canManage],
  );

  const { table } = useDataTable({
    data: data?.policies ?? [],
    columns,
    pageCount: data
      ? Math.max(1, Math.ceil(data.total_training_policies / params.perPage))
      : 1,
    shallow: true,
    debounceMs: 300,
    initialState: {
      sorting: [{ id: "updated_at", desc: true }],
      columnPinning: { right: ["actions"] },
    },
  });

  if (error) {
    return (
      <Card className="border-dashed">
        <CardContent className="flex flex-col items-center justify-center gap-4 py-12 text-center">
          <div className="bg-muted flex h-12 w-12 items-center justify-center rounded-full">
            <Icons.warning className="text-muted-foreground h-6 w-6" />
          </div>
          <div className="space-y-1">
            <h3 className="text-lg font-semibold">
              ไม่สามารถโหลดนโยบายการอบรมได้
            </h3>
            <p className="text-muted-foreground text-sm">{error.message}</p>
          </div>
        </CardContent>
      </Card>
    );
  }

  if ((isPending && !data) || !data) {
    return (
      <Card className="border-dashed">
        <CardContent className="flex flex-col items-center justify-center gap-4 py-12 text-center">
          <Icons.spinner className="text-muted-foreground h-6 w-6 animate-spin" />
          <p className="text-muted-foreground text-sm">
            กำลังโหลดนโยบายการอบรม
          </p>
        </CardContent>
      </Card>
    );
  }

  const activePolicy = data.active_policy;

  return (
    <>
      <div className="space-y-6">
        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
          <MetricCard
            label="ปีที่ใช้งานอยู่"
            value={activePolicy ? String(activePolicy.year) : "-"}
            description="นโยบายที่ระบบใช้เป็นค่าอ้างอิงหลักขององค์กร"
          />
          <MetricCard
            label="ชั่วโมงรวม"
            value={
              activePolicy
                ? `${formatHours(activePolicy.total_hours)} ชม.`
                : "-"
            }
            description="เป้าหมายชั่วโมงอบรมต่อคนต่อปี"
          />
          <MetricCard
            label="สัดส่วน K / S / A"
            value={
              activePolicy
                ? `${formatHours(activePolicy.k_hours)} / ${formatHours(activePolicy.s_hours)} / ${formatHours(activePolicy.a_hours)}`
                : "-"
            }
            description="ชั่วโมงความรู้ ทักษะ และทัศนคติ"
          />
          <MetricCard
            label="จำนวนนโยบาย"
            value={data.total_training_policies.toLocaleString("th-TH")}
            description="รายการนโยบายที่มีอยู่ในระบบ"
          />
        </div>

        {data.policies.length === 0 ? (
          <Card className="border-dashed">
            <CardContent className="flex flex-col items-center justify-center gap-4 py-12 text-center">
              <div className="bg-muted flex h-12 w-12 items-center justify-center rounded-full">
                <Icons.forms className="text-muted-foreground h-6 w-6" />
              </div>
              <div className="space-y-1">
                <h3 className="text-lg font-semibold">ยังไม่มีนโยบายการอบรม</h3>
                <p className="text-muted-foreground max-w-md text-sm">
                  เริ่มสร้างนโยบายรายปีเพื่อกำหนดชั่วโมงรวมและสัดส่วน K/S/A
                  ที่องค์กรต้องการใช้
                </p>
              </div>
            </CardContent>
          </Card>
        ) : (
          <DataTable table={table}>
            <DataTableToolbar table={table}>
              <div className="flex items-center gap-2">
                {isFetching ? (
                  <span className="text-muted-foreground inline-flex items-center gap-2 text-sm">
                    <Icons.spinner className="h-4 w-4 animate-spin" />
                    กำลังโหลด
                  </span>
                ) : null}
                {canManage ? (
                  <Button
                    type="button"
                    className="shrink-0 whitespace-nowrap"
                    onClick={() => {
                      setFormPolicy(null);
                      setFormOpen(true);
                    }}
                  >
                    <Icons.add className="mr-2 h-4 w-4" />
                    เพิ่มนโยบาย
                  </Button>
                ) : null}
              </div>
            </DataTableToolbar>
          </DataTable>
        )}
      </div>

      <Sheet open={formOpen} onOpenChange={setFormOpen}>
        <SheetContent className="flex w-full flex-col sm:max-w-3xl">
          <SheetHeader>
            <SheetTitle>
              {formPolicy ? "แก้ไขนโยบายการอบรม" : "เพิ่มนโยบายการอบรม"}
            </SheetTitle>
            <SheetDescription>
              ปรับชั่วโมงรวมและสถานะใช้งานโดยใช้ schema และ validation
              เดิมของระบบ
            </SheetDescription>
          </SheetHeader>
          <div className="flex-1 overflow-auto py-2">
            <TrainingPolicyForm
              initialData={formPolicy}
              showCard={false}
              onCancelEdit={() => setFormOpen(false)}
              onSuccess={() => {
                setFormOpen(false);
                setFormPolicy(null);
              }}
            />
          </div>
        </SheetContent>
      </Sheet>

      <TrainingPolicyDetailSheet
        policyId={detailPolicyId}
        open={detailOpen}
        onOpenChange={setDetailOpen}
      />
    </>
  );
}

function MetricCard({
  label,
  value,
  description,
}: {
  label: string;
  value: string;
  description: string;
}) {
  return (
    <Card>
      <CardHeader className="pb-2">
        <CardDescription>{label}</CardDescription>
        <CardTitle className="text-2xl">{value}</CardTitle>
      </CardHeader>
      <CardContent className="text-muted-foreground text-sm">
        {description}
      </CardContent>
    </Card>
  );
}

function TrainingPolicyActionMenu({
  policy,
  canManage,
  onView,
  onEdit,
}: {
  policy: TrainingPolicy;
  canManage: boolean;
  onView: (policy: TrainingPolicy) => void;
  onEdit: (policy: TrainingPolicy) => void;
}) {
  const [activateOpen, setActivateOpen] = useState(false);
  const [deactivateOpen, setDeactivateOpen] = useState(false);

  const cloneMutation = useMutation({
    ...cloneTrainingPolicyMutation,
    onSuccess: (response) => {
      toast.success(response.message);
    },
    onError: (error) => {
      toast.error(error.message || "ไม่สามารถโคลนนโยบายการอบรมได้");
    },
  });

  const activateMutation = useMutation({
    ...activateTrainingPolicyMutation,
    onSuccess: (response) => {
      toast.success(response.message);
      setActivateOpen(false);
    },
    onError: (error) => {
      toast.error(error.message || "ไม่สามารถเปิดใช้งานนโยบายการอบรมได้");
    },
  });

  const deactivateMutation = useMutation({
    ...deactivateTrainingPolicyMutation,
    onSuccess: (response) => {
      toast.success(response.message);
      setDeactivateOpen(false);
    },
    onError: (error) => {
      toast.error(error.message || "ไม่สามารถปิดใช้งานนโยบายการอบรมได้");
    },
  });

  const isPending =
    cloneMutation.isPending ||
    activateMutation.isPending ||
    deactivateMutation.isPending;

  return (
    <>
      <AlertDialog open={activateOpen} onOpenChange={setActivateOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>
              เปิดใช้งานนโยบายปี {policy.year}
            </AlertDialogTitle>
            <AlertDialogDescription>
              ระบบจะปิดใช้งานนโยบายอื่นในองค์กรก่อน
              แล้วตั้งนโยบายนี้เป็นตัวหลักเพียงรายการเดียว
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={activateMutation.isPending}>
              ยกเลิก
            </AlertDialogCancel>
            <AlertDialogAction
              onClick={() => activateMutation.mutate({ id: policy.id })}
            >
              ยืนยัน
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      <AlertDialog open={deactivateOpen} onOpenChange={setDeactivateOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>ปิดใช้งานนโยบายปี {policy.year}</AlertDialogTitle>
            <AlertDialogDescription>
              หลังยืนยัน
              นโยบายนี้จะไม่ถูกใช้เป็นค่าอ้างอิงหลักของระบบจนกว่าจะเปิดใช้งานอีกครั้ง
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={deactivateMutation.isPending}>
              ยกเลิก
            </AlertDialogCancel>
            <AlertDialogAction
              onClick={() => deactivateMutation.mutate({ id: policy.id })}
            >
              ยืนยัน
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      <DropdownMenu modal={false}>
        <DropdownMenuTrigger asChild>
          <Button
            type="button"
            variant="ghost"
            size="icon"
            className="h-8 w-8 shrink-0"
            aria-label="เมนูจัดการนโยบายการอบรม"
          >
            <Icons.ellipsis className="h-4 w-4" />
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent
          align="end"
          sideOffset={8}
          className="w-56 max-w-[calc(100vw-1rem)]"
        >
          <DropdownMenuLabel>จัดการ</DropdownMenuLabel>
          <DropdownMenuItem onClick={() => onView(policy)}>
            <Icons.info className="mr-2 h-4 w-4" />
            ดูรายละเอียด
          </DropdownMenuItem>
          {canManage ? (
            <DropdownMenuItem onClick={() => onEdit(policy)}>
              <Icons.edit className="mr-2 h-4 w-4" />
              แก้ไข
            </DropdownMenuItem>
          ) : null}
          {canManage ? <DropdownMenuSeparator /> : null}
          {canManage ? (
            <DropdownMenuItem
              disabled={isPending}
              onClick={() => cloneMutation.mutate({ id: policy.id })}
            >
              <Icons.share className="mr-2 h-4 w-4" />
              โคลน
            </DropdownMenuItem>
          ) : null}
          {canManage && !policy.is_active ? (
            <DropdownMenuItem
              disabled={isPending}
              onClick={() => setActivateOpen(true)}
            >
              <Icons.check className="mr-2 h-4 w-4" />
              เปิดใช้งาน
            </DropdownMenuItem>
          ) : null}
          {canManage && policy.is_active ? (
            <DropdownMenuItem
              disabled={isPending}
              onClick={() => setDeactivateOpen(true)}
            >
              <Icons.close className="mr-2 h-4 w-4" />
              ปิดใช้งาน
            </DropdownMenuItem>
          ) : null}
        </DropdownMenuContent>
      </DropdownMenu>
    </>
  );
}

function TrainingPolicyDetailSheet({
  policyId,
  open,
  onOpenChange,
}: {
  policyId: number | null;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const { data: detail, isPending: isPolicyPending } = useQuery({
    ...(policyId
      ? trainingPolicyByIdQueryOptions(policyId)
      : trainingPolicyByIdQueryOptions(0)),
    enabled: open && policyId !== null,
  });

  const { data: history, isPending: isHistoryPending } = useQuery({
    ...(policyId
      ? trainingPolicyHistoryQueryOptions(policyId)
      : trainingPolicyHistoryQueryOptions(0)),
    enabled: open && policyId !== null,
  });

  const policy = detail?.policy;

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="flex w-full flex-col sm:max-w-2xl">
        <SheetHeader>
          <SheetTitle>
            {policy ? `รายละเอียดนโยบายปี ${policy.year}` : "รายละเอียดนโยบาย"}
          </SheetTitle>
          <SheetDescription>
            ตรวจสอบชั่วโมงรวม สถานะ และประวัติการเปลี่ยนแปลงล่าสุด
          </SheetDescription>
        </SheetHeader>
        <div className="flex-1 space-y-6 overflow-auto py-2">
          {isPolicyPending || !policy ? (
            <div className="text-muted-foreground flex items-center gap-2 text-sm">
              <Icons.spinner className="h-4 w-4 animate-spin" />
              กำลังโหลดรายละเอียดนโยบาย
            </div>
          ) : (
            <>
              <div className="grid gap-4 md:grid-cols-2">
                <DetailField label="ชื่อแสดงผล" value={policy.display_name} />
                <DetailField label="สถานะ" value={getStatusLabel(policy)} />
                <DetailField
                  label="ชั่วโมงรวม"
                  value={`${formatHours(policy.total_hours)} ชั่วโมง`}
                />
                <DetailField
                  label="K / S / A"
                  value={`${formatHours(policy.k_hours)} / ${formatHours(policy.s_hours)} / ${formatHours(policy.a_hours)}`}
                />
                <DetailField
                  label="อัปเดตโดย"
                  value={policy.updated_by_name ?? "-"}
                />
                <DetailField
                  label="อัปเดตล่าสุด"
                  value={formatDate(policy.updated_at)}
                />
              </div>

              <div className="space-y-3">
                <div>
                  <h3 className="font-medium">ประวัติการเปลี่ยนแปลง</h3>
                  <p className="text-muted-foreground text-sm">
                    อ้างอิงจาก audit log ของโมดูลนโยบายการอบรม
                  </p>
                </div>

                {isHistoryPending ? (
                  <div className="text-muted-foreground flex items-center gap-2 text-sm">
                    <Icons.spinner className="h-4 w-4 animate-spin" />
                    กำลังโหลดประวัติ
                  </div>
                ) : history?.history.length ? (
                  <div className="space-y-3">
                    {history.history.map((item) => (
                      <div key={item.id} className="rounded-lg border p-4">
                        <div className="flex flex-wrap items-center justify-between gap-2">
                          <span className="font-medium">{item.details}</span>
                          <span className="text-muted-foreground text-xs">
                            {formatDate(item.created_at)}
                          </span>
                        </div>
                        <div className="text-muted-foreground mt-1 text-sm">
                          โดย {item.user_name ?? "ไม่ระบุผู้ใช้"}
                        </div>
                      </div>
                    ))}
                  </div>
                ) : (
                  <div className="text-muted-foreground rounded-lg border border-dashed px-4 py-6 text-sm">
                    ยังไม่มีประวัติการเปลี่ยนแปลง
                  </div>
                )}
              </div>
            </>
          )}
        </div>
      </SheetContent>
    </Sheet>
  );
}

function DetailField({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-lg border p-4">
      <div className="text-muted-foreground text-sm">{label}</div>
      <div className={cn("mt-1 font-medium")}>{value}</div>
    </div>
  );
}
