"use client";

import * as React from "react";

import {
  getCoreRowModel,
  useReactTable,
  type Header,
} from "@tanstack/react-table";
import { useRouter } from "next/navigation";
import { toast } from "sonner";

import {
  DataTablePagination,
  DataTableShell,
  useServerPagination,
  type ServerPaginationMeta,
} from "@/app/dashboard/_components/data-table";
import { useMasterListFilters } from "@/hooks/use-master-list-filters";
import { useDebouncedValue } from "@/hooks/use-debounced-value";
import { requestDashboardApi } from "@/lib/dashboard-api-client";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { TableCell } from "@/components/ui/table";

import { createCountryColumns } from "./columns";
import {
  COUNTRY_STATUS_OPTIONS,
  type CountryBulkLan,
  type CountryFilters,
  type CountryRow,
} from "./schema";
import { exportCountriesFullCsv } from "./export-csv";

const BULK_SAVE_HREF = "/dashboard/master/countries/bulk-translate";

type Props = {
  data: CountryRow[];
  initialFilters: CountryFilters;
  pagination: ServerPaginationMeta;
  bulkLan: CountryBulkLan | null;
};

type TextDrafts = Pick<CountryFilters, "name" | "code" | "shipping">;

function buildTranslationMap(rows: CountryRow[]) {
  const map: Record<number, string> = {};
  for (const row of rows) {
    map[row.id] = row.bulkTranslation ?? "";
  }
  return map;
}

export function CountriesTable({
  data,
  initialFilters,
  pagination: serverPagination,
  bulkLan,
}: Props) {
  const router = useRouter();
  const bulkMode = bulkLan != null;
  const { filters, setFilter } = useMasterListFilters(initialFilters, [
    "name",
    "code",
    "shipping",
    "status",
  ] as const);
  const [drafts, setDrafts] = React.useState<TextDrafts>({
    name: filters.name,
    code: filters.code,
    shipping: filters.shipping,
  });
  const committedTextRef = React.useRef<TextDrafts>({
    name: filters.name,
    code: filters.code,
    shipping: filters.shipping,
  });
  const [checkedIds, setCheckedIds] = React.useState<Set<number>>(
    () => new Set(data.map((row) => row.id)),
  );
  const [translations, setTranslations] = React.useState<Record<number, string>>(() =>
    buildTranslationMap(data),
  );
  const [isSavingBulk, setIsSavingBulk] = React.useState(false);
  const { pagination, onPaginationChange, totalCount } =
    useServerPagination(serverPagination);

  const debouncedName = useDebouncedValue(drafts.name, 300);
  const debouncedCode = useDebouncedValue(drafts.code, 300);
  const debouncedShipping = useDebouncedValue(drafts.shipping, 300);

  React.useEffect(() => {
    setDrafts((draft) => ({
      name:
        draft.name === committedTextRef.current.name || draft.name === filters.name
          ? filters.name
          : draft.name,
      code:
        draft.code === committedTextRef.current.code || draft.code === filters.code
          ? filters.code
          : draft.code,
      shipping:
        draft.shipping === committedTextRef.current.shipping ||
        draft.shipping === filters.shipping
          ? filters.shipping
          : draft.shipping,
    }));
    committedTextRef.current = {
      name: filters.name,
      code: filters.code,
      shipping: filters.shipping,
    };
  }, [filters.name, filters.code, filters.shipping]);

  React.useEffect(() => {
    if (debouncedName !== filters.name) setFilter("name", debouncedName);
  }, [debouncedName, filters.name, setFilter]);

  React.useEffect(() => {
    if (debouncedCode !== filters.code) setFilter("code", debouncedCode);
  }, [debouncedCode, filters.code, setFilter]);

  React.useEffect(() => {
    if (debouncedShipping !== filters.shipping) setFilter("shipping", debouncedShipping);
  }, [debouncedShipping, filters.shipping, setFilter]);

  // Reset bulk editors when page data / language changes (Yii1 reloads grid values).
  React.useEffect(() => {
    setCheckedIds(new Set(data.map((row) => row.id)));
    setTranslations(buildTranslationMap(data));
  }, [data, bulkLan]);

  const updateDraft = <K extends keyof TextDrafts>(key: K, value: TextDrafts[K]) => {
    setDrafts((prev) => ({ ...prev, [key]: value }));
  };

  const updateStatusFilter = (value: string) => {
    setFilter("status", value);
  };

  const allChecked = data.length > 0 && data.every((row) => checkedIds.has(row.id));

  const toggleSelectAll = (checked: boolean) => {
    setCheckedIds(checked ? new Set(data.map((row) => row.id)) : new Set());
  };

  const applyTranslation = () => {
    // Yii1 applyTanslation(): copy name-column text into checked bulk inputs.
    setTranslations((prev) => {
      const next = { ...prev };
      for (const row of data) {
        if (checkedIds.has(row.id)) {
          next[row.id] = row.name;
        }
      }
      return next;
    });
    toast.message("Copied English names into checked translation fields.");
  };

  const saveBulkTranslations = async () => {
    if (!bulkLan) return;
    setIsSavingBulk(true);
    try {
      const bulk: Record<string, string> = {};
      for (const row of data) {
        const value = (translations[row.id] ?? "").trim();
        if (value) bulk[String(row.id)] = value;
      }
      const dataResponse = await requestDashboardApi<{ status?: string; message?: string }>({
        url: BULK_SAVE_HREF,
        method: "POST",
        body: { lan: bulkLan, bulk },
        fallbackError: "Bulk translations could not be saved.",
        validate: (payload) => payload.status === "success",
      });
      toast.success(
        typeof dataResponse.message === "string" && dataResponse.message.trim()
          ? dataResponse.message
          : "Priority successfully updated!",
      );
      router.refresh();
    } catch (error) {
      toast.error(error instanceof Error ? error.message : "Bulk translations could not be saved.");
    } finally {
      setIsSavingBulk(false);
    }
  };

  const columns = React.useMemo(
    () =>
      createCountryColumns(
        bulkMode && bulkLan
          ? {
              lan: bulkLan,
              checkedIds,
              translations,
              onToggleChecked: (id, checked) => {
                setCheckedIds((prev) => {
                  const next = new Set(prev);
                  if (checked) next.add(id);
                  else next.delete(id);
                  return next;
                });
              },
              onTranslationChange: (id, value) => {
                setTranslations((prev) => ({ ...prev, [id]: value }));
              },
            }
          : null,
      ),
    [bulkMode, bulkLan, checkedIds, translations],
  );

  const table = useReactTable({
    data,
    columns,
    state: { pagination },
    onPaginationChange,
    manualPagination: true,
    pageCount: serverPagination.pageCount,
    rowCount: totalCount,
    getCoreRowModel: getCoreRowModel(),
    getRowId: (row) => String(row.id),
  });

  return (
    <div className="space-y-4">
      {bulkMode ? (
        <div className="rounded-lg border bg-muted/20 px-3 py-2 text-sm">
          <p className="text-muted-foreground">
            {bulkLan === "ar" ? "Arabic" : "Dutch"} bulk update — edit translations below, then
            save.
          </p>
        </div>
      ) : null}

      <div className="flex justify-end">
        <Button
          type="button"
          variant="secondary"
          size="sm"
          onClick={() => exportCountriesFullCsv(data)}
        >
          Export filtered
        </Button>
      </div>

      <DataTableShell
        table={table}
        columnCount={columns.length}
        emptyMessage="No countries match your filters."
        renderFilterCell={(header) =>
          renderFilterCell(
            header,
            drafts,
            filters.status,
            updateDraft,
            updateStatusFilter,
            bulkMode
              ? {
                  allChecked,
                  onToggleSelectAll: toggleSelectAll,
                  onApplyTranslation: applyTranslation,
                }
              : null,
          )
        }
      />

      <DataTablePagination
        table={table}
        totalRows={totalCount}
        itemNoun="country"
        idPrefix="countries"
      />

      {bulkMode ? (
        <div className="flex justify-end border-t pt-3">
          <Button type="button" size="sm" disabled={isSavingBulk} onClick={saveBulkTranslations}>
            {isSavingBulk ? "Saving..." : "Update Priority"}
          </Button>
        </div>
      ) : null}
    </div>
  );
}

function renderFilterCell(
  header: Header<CountryRow, unknown>,
  drafts: TextDrafts,
  status: string,
  updateDraft: <K extends keyof TextDrafts>(key: K, value: TextDrafts[K]) => void,
  updateStatusFilter: (value: string) => void,
  bulkControls: {
    allChecked: boolean;
    onToggleSelectAll: (checked: boolean) => void;
    onApplyTranslation: () => void;
  } | null,
) {
  const columnId = header.column.id;

  if (columnId === "name") {
    return (
      <TableCell key={header.id} className="p-2">
        <Input
          value={drafts.name}
          onChange={(event) => updateDraft("name", event.target.value)}
          placeholder="Country name"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  if (columnId === "bulkUpdate" && bulkControls) {
    return (
      <TableCell key={header.id} className="p-2">
        <div className="flex min-w-[220px] flex-col gap-2">
          <label className="flex items-center gap-2 text-muted-foreground text-xs">
            <Checkbox
              checked={bulkControls.allChecked}
              onCheckedChange={(value) => bulkControls.onToggleSelectAll(value === true)}
            />
            Click to check / uncheck all
          </label>
          <Button
            type="button"
            size="sm"
            variant="secondary"
            className="h-7 w-fit text-xs"
            onClick={bulkControls.onApplyTranslation}
          >
            Apply Translation
          </Button>
        </div>
      </TableCell>
    );
  }

  if (columnId === "code") {
    return (
      <TableCell key={header.id} className="p-2">
        <Input
          value={drafts.code}
          onChange={(event) => updateDraft("code", event.target.value)}
          placeholder="Code"
          className="h-8 bg-background font-mono text-xs uppercase"
        />
      </TableCell>
    );
  }

  if (columnId === "shipping") {
    return (
      <TableCell key={header.id} className="p-2">
        <Input
          value={drafts.shipping}
          onChange={(event) => updateDraft("shipping", event.target.value)}
          placeholder="Shipping"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  if (columnId === "status") {
    return (
      <TableCell key={header.id} className="p-2">
        <Select value={status} onValueChange={updateStatusFilter}>
          <SelectTrigger className="h-8 bg-background text-xs">
            <SelectValue placeholder="Status" />
          </SelectTrigger>
          <SelectContent>
            {COUNTRY_STATUS_OPTIONS.map((option) => (
              <SelectItem key={option.value} value={option.value}>
                {option.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </TableCell>
    );
  }

  return null;
}
