"use client";

import * as React from "react";

import Link from "next/link";
import { ExternalLink } from "lucide-react";

import {
  getCoreRowModel,
  useReactTable,
  type Header,
} from "@tanstack/react-table";
import { Download, Plus } from "lucide-react";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import { TableCell } from "@/components/ui/table";

import { createCustomerColumns } from "./columns";
import { CUSTOMER_STATUS_OPTIONS } from "./schema";
import type { CustomerFilters, CustomerRow } from "./schema";
import {
  DataTablePagination,
  DataTableRefreshButton,
  DataTableShell,
  useServerPagination,
  type ServerPaginationMeta,
} from "@/app/dashboard/_components/data-table";
import { useMasterListFilters } from "@/hooks/use-master-list-filters";
import { CustomerCredentialsForm } from "./customer-credentials/customer-credentials-form";
import type { CustomerCredentialsValues } from "./customer-credentials/schema";
import { CustomerPortalRoutesForm } from "./customer-portal-routes/customer-portal-routes-form";
import type { PortalAppCatalog } from "../_lib/portal-routes-server-api";

const CUSTOMER_FILTER_KEYS = [
  "customerId",
  "status",
  "fullName",
  "subdomain",
  "accountType",
  "email",
] as const;

function exportCustomersExcel(rows: CustomerRow[]) {
  const headers = [
    "Customer ID",
    "DB Name",
    "Status",
    "First Name",
    "Last Name",
    "Email",
    "Account Type",
    "Subdomain",
    "Created By",
  ];
  const lines = rows.map((row) =>
    [
      row.id,
      row.dbName,
      row.statusLabel,
      row.firstName,
      row.lastName,
      row.email,
      row.accountTypeLabel,
      row.subdomain,
      row.createdBy ?? "",
    ]
      .map((cell) => `"${String(cell).replace(/"/g, '""')}"`)
      .join(","),
  );
  const csv = [headers.join(","), ...lines].join("\n");
  const blob = new Blob([csv], {
    type: "application/vnd.ms-excel;charset=utf-8;",
  });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = `customers-data-${new Date().toISOString().slice(0, 10)}.xls`;
  link.click();
  URL.revokeObjectURL(url);
}

type CustomersTableProps = {
  data: CustomerRow[];
  parentCustomerId?: number;
  initialFilters: CustomerFilters;
  pagination: ServerPaginationMeta;
};

export function CustomersTable({
  data,
  parentCustomerId,
  initialFilters,
  pagination: serverPagination,
}: CustomersTableProps) {
  const { filters, setFilter } = useMasterListFilters(
    initialFilters,
    CUSTOMER_FILTER_KEYS,
  );
  const { pagination, onPaginationChange, totalCount } =
    useServerPagination(serverPagination);
  const [toolbarStatus, setToolbarStatus] = React.useState(filters.status);
  const [credentialsOpen, setCredentialsOpen] = React.useState(false);
  const [credentialsCustomer, setCredentialsCustomer] =
    React.useState<CustomerRow | null>(null);
  const [credentialsInitial, setCredentialsInitial] =
    React.useState<CustomerCredentialsValues | null>(null);
  const [credentialsError, setCredentialsError] = React.useState<string | null>(
    null,
  );
  const [credentialsLoading, setCredentialsLoading] = React.useState(false);
  const [portalRoutesOpen, setPortalRoutesOpen] = React.useState(false);
  const [portalRoutesCustomer, setPortalRoutesCustomer] =
    React.useState<CustomerRow | null>(null);
  const [portalRoutesApps, setPortalRoutesApps] = React.useState<
    PortalAppCatalog[]
  >([]);
  const [portalRoutesInitial, setPortalRoutesInitial] = React.useState<
    string[]
  >([]);
  const [portalRoutesConfigured, setPortalRoutesConfigured] =
    React.useState(false);
  const [portalRoutesError, setPortalRoutesError] = React.useState<
    string | null
  >(null);
  const [portalRoutesLoading, setPortalRoutesLoading] = React.useState(false);

  const applyToolbarSearch = () => {
    setFilter("status", toolbarStatus);
  };

  const openCredentialsModal = React.useCallback(
    async (row: CustomerRow) => {
      setCredentialsCustomer(row);
      setCredentialsOpen(true);
      setCredentialsError(null);
      setCredentialsInitial(null);
      setCredentialsLoading(true);

      try {
        const params = new URLSearchParams();
        params.set("customerId", String(row.id));
        if (parentCustomerId)
          params.set("parentCustomerId", String(parentCustomerId));
        const response = await fetch(
          `/dashboard/customers/credentials/load?${params.toString()}`,
          {
            method: "GET",
            headers: { Accept: "application/json" },
          },
        );
        const payload = (await response.json().catch(() => null)) as {
          status?: string;
          message?: string;
          credentials?: CustomerCredentialsValues;
        } | null;

        if (
          !response.ok ||
          payload?.status !== "success" ||
          !payload.credentials
        ) {
          throw new Error(
            payload?.message ?? "Could not load customer credentials.",
          );
        }

        setCredentialsInitial(payload.credentials);
      } catch (error) {
        setCredentialsError(
          error instanceof Error
            ? error.message
            : "Could not load customer credentials.",
        );
      } finally {
        setCredentialsLoading(false);
      }
    },
    [parentCustomerId],
  );

  const openPortalRoutesModal = React.useCallback(async (row: CustomerRow) => {
    setPortalRoutesCustomer(row);
    setPortalRoutesOpen(true);
    setPortalRoutesError(null);
    setPortalRoutesApps([]);
    setPortalRoutesInitial([]);
    setPortalRoutesConfigured(false);
    setPortalRoutesLoading(true);

    try {
      const params = new URLSearchParams();
      params.set("customerId", String(row.id));
      const response = await fetch(
        `/dashboard/customers/portal-routes/load?${params.toString()}`,
        {
          method: "GET",
          headers: { Accept: "application/json" },
        },
      );
      const payload = (await response.json().catch(() => null)) as {
        status?: string;
        message?: string;
        data?: {
          apps?: PortalAppCatalog[];
          entitled_routes?: string[];
          has_configured_entitlements?: boolean;
        };
      } | null;

      if (!response.ok || payload?.status !== "success" || !payload.data) {
        throw new Error(
          payload?.message ?? "Could not load portal route entitlements.",
        );
      }

      setPortalRoutesApps(payload.data.apps ?? []);
      setPortalRoutesInitial(payload.data.entitled_routes ?? []);
      setPortalRoutesConfigured(
        payload.data.has_configured_entitlements ?? false,
      );
    } catch (error) {
      setPortalRoutesError(
        error instanceof Error
          ? error.message
          : "Could not load portal route entitlements.",
      );
    } finally {
      setPortalRoutesLoading(false);
    }
  }, []);

  const columns = React.useMemo(
    () =>
      createCustomerColumns({
        parentCustomerId,
        onOpenCredentials: openCredentialsModal,
        onOpenPortalRoutes: openPortalRoutesModal,
      }),
    [openCredentialsModal, openPortalRoutesModal, parentCustomerId],
  );

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

  const updateFilter = <K extends keyof CustomerFilters>(
    key: K,
    value: CustomerFilters[K],
  ) => {
    setFilter(key, value);
  };

  return (
    <div className="space-y-4">
      <Dialog
        open={credentialsOpen}
        onOpenChange={(open) => {
          setCredentialsOpen(open);
          if (!open) {
            setCredentialsCustomer(null);
            setCredentialsInitial(null);
            setCredentialsError(null);
            setCredentialsLoading(false);
          }
        }}
      >
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>Send customer credential</DialogTitle>
            <DialogDescription>
              {credentialsCustomer
                ? `Update login credentials for ${credentialsCustomer.firstName} ${credentialsCustomer.lastName} and send them by email.`
                : "Update login credentials and send them by email."}
            </DialogDescription>
          </DialogHeader>

          {credentialsError ? (
            <div className="rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-destructive text-sm">
              {credentialsError}
            </div>
          ) : null}

          {credentialsCustomer ? (
            <div className="space-y-3">
              {credentialsLoading ? (
                <div className="text-muted-foreground text-sm">Loading…</div>
              ) : (
                <CustomerCredentialsForm
                  customerId={credentialsCustomer.id}
                  customerName={`${credentialsCustomer.firstName} ${credentialsCustomer.lastName}`.trim()}
                  initial={credentialsInitial ?? undefined}
                  initialErrorMessage={null}
                  parentCustomerId={parentCustomerId}
                  variant="modal"
                  onSuccess={() => setCredentialsOpen(false)}
                />
              )}
            </div>
          ) : null}
        </DialogContent>
      </Dialog>

      <Sheet
        open={portalRoutesOpen}
        onOpenChange={(open) => {
          setPortalRoutesOpen(open);
          if (!open) {
            setPortalRoutesCustomer(null);
            setPortalRoutesApps([]);
            setPortalRoutesInitial([]);
            setPortalRoutesConfigured(false);
            setPortalRoutesError(null);
            setPortalRoutesLoading(false);
          }
        }}
      >
        <SheetContent className="flex h-full !w-[min(1120px,calc(100vw-1rem))] !max-w-none flex-col gap-0 overflow-hidden bg-muted/30 p-0">
          <SheetHeader className="shrink-0 border-b bg-card px-5 py-4 pr-14 sm:px-6">
            <SheetTitle>Portal Apps &amp; Permissions</SheetTitle>
            <SheetDescription>
              {portalRoutesCustomer
                ? `Assign customer portal Apps and routes for ${portalRoutesCustomer.firstName} ${portalRoutesCustomer.lastName}.`
                : "Assign customer portal Apps and routes for this tenant account."}
            </SheetDescription>
            {portalRoutesCustomer ? (
              <Button asChild variant="link" size="sm" className="h-auto px-0">
                <Link
                  href={`/dashboard/admins/portal/entitlements?customerId=${portalRoutesCustomer.id}`}
                >
                  <ExternalLink className="size-3.5" />
                  Manage in Admins &amp; Access
                </Link>
              </Button>
            ) : null}
          </SheetHeader>

          <div className="min-h-0 flex-1 overflow-y-auto px-5 py-4 sm:px-6 sm:py-5">
            {portalRoutesError ? (
              <div className="rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-destructive text-sm">
                {portalRoutesError}
              </div>
            ) : null}

            {portalRoutesCustomer ? (
              portalRoutesLoading ? (
                <div className="text-muted-foreground text-sm">
                  Loading portal permissions…
                </div>
              ) : (
                <CustomerPortalRoutesForm
                  customerId={portalRoutesCustomer.id}
                  customerName={`${portalRoutesCustomer.firstName} ${portalRoutesCustomer.lastName}`.trim()}
                  apps={portalRoutesApps}
                  initialRoutes={portalRoutesInitial}
                  hasConfiguredEntitlements={portalRoutesConfigured}
                  preferRolesGroupLabels={
                    portalRoutesCustomer.accountType !== "C"
                  }
                  initialErrorMessage={null}
                  onSuccess={() => setPortalRoutesOpen(false)}
                />
              )
            ) : null}
          </div>
        </SheetContent>
      </Sheet>

      {parentCustomerId ? (
        <Link
          href="/dashboard/customers"
          className="inline-flex items-center text-sm text-primary hover:underline"
        >
          ← Back to all customers
        </Link>
      ) : null}

      <div className="flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between">
        <div className="flex flex-wrap items-end gap-2">
          <div className="space-y-1">
            <Label htmlFor="customers-toolbar-status" className="text-xs">
              Status
            </Label>
            <Select value={toolbarStatus} onValueChange={setToolbarStatus}>
              <SelectTrigger
                id="customers-toolbar-status"
                className="h-9 w-[180px]"
              >
                <SelectValue placeholder="Status" />
              </SelectTrigger>
              <SelectContent>
                <SelectGroup>
                  {CUSTOMER_STATUS_OPTIONS.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectGroup>
              </SelectContent>
            </Select>
          </div>
          <Button type="button" className="h-9" onClick={applyToolbarSearch}>
            Search
          </Button>
        </div>
        {!parentCustomerId ? (
          <Button variant="outline" className="h-9" asChild>
            <Link href="/dashboard/corporate-customers">
              Customers of Corporate Account
            </Link>
          </Button>
        ) : null}
      </div>

      <DataTableShell
        table={table}
        columnCount={columns.length}
        emptyMessage="No customers match your filters."
        renderFilterCell={(header) =>
          renderFilterCell(header, filters, updateFilter)
        }
      />

      <DataTablePagination
        table={table}
        totalRows={totalCount}
        itemNoun="customer"
        idPrefix="customers"
      />
    </div>
  );
}

function BlurFilterInput({
  value,
  onCommit,
  placeholder,
}: {
  value: string;
  onCommit: (value: string) => void;
  placeholder: string;
}) {
  const [draft, setDraft] = React.useState(value);

  React.useEffect(() => {
    setDraft(value);
  }, [value]);

  return (
    <Input
      value={draft}
      onChange={(event) => setDraft(event.target.value)}
      onBlur={() => {
        if (draft !== value) {
          onCommit(draft);
        }
      }}
      onKeyDown={(event) => {
        if (event.key === "Enter") {
          event.currentTarget.blur();
        }
      }}
      placeholder={placeholder}
      className="h-8 bg-background text-xs"
    />
  );
}

function renderFilterCell(
  header: Header<CustomerRow, unknown>,
  filters: CustomerFilters,
  updateFilter: <K extends keyof CustomerFilters>(
    key: K,
    value: CustomerFilters[K],
  ) => void,
) {
  const columnId = header.column.id;

  if (columnId === "id") {
    return (
      <TableCell key={header.id} className="p-2">
        <BlurFilterInput
          value={filters.customerId}
          onCommit={(next) => updateFilter("customerId", next)}
          placeholder="Customer ID"
        />
      </TableCell>
    );
  }

  if (columnId === "fullName") {
    return (
      <TableCell key={header.id} className="p-2">
        <BlurFilterInput
          value={filters.fullName}
          onCommit={(next) => updateFilter("fullName", next)}
          placeholder="Full name"
        />
      </TableCell>
    );
  }

  if (columnId === "subdomain") {
    return (
      <TableCell key={header.id} className="p-2">
        <BlurFilterInput
          value={filters.subdomain}
          onCommit={(next) => updateFilter("subdomain", next)}
          placeholder="Subdomain"
        />
      </TableCell>
    );
  }

  if (columnId === "accountTypeLabel") {
    return (
      <TableCell key={header.id} className="p-2">
        <Select
          value={filters.accountType}
          onValueChange={(value) => updateFilter("accountType", value)}
        >
          <SelectTrigger className="h-8 bg-background text-xs">
            <SelectValue placeholder="Type" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All</SelectItem>
            <SelectItem value="I">Individual</SelectItem>
            <SelectItem value="C">Corporate</SelectItem>
          </SelectContent>
        </Select>
      </TableCell>
    );
  }

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

  return null;
}

export function CustomersHeaderActions({ data }: { data: CustomerRow[] }) {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Button size="sm" className="gap-1.5" asChild>
        <Link href="/dashboard/customers/create">
          <Plus className="size-4" />
          Create new
        </Link>
      </Button>
      <Button
        variant="outline"
        size="sm"
        className="gap-1.5 border-green-600 text-green-700 hover:bg-green-50"
        onClick={() => exportCustomersExcel(data)}
      >
        <Download className="size-4" />
        Download Excel
      </Button>
      <DataTableRefreshButton />
    </div>
  );
}
