import { useMemo, useState } from "react";
import {
  ActionIcon,
  Badge,
  Box,
  Button,
  Card,
  Code,
  Group,
  Stack,
  Table,
  Text,
  TextInput,
  ThemeIcon,
} from "@mantine/core";
import {
  FileUp,
  HardDrive,
  Layers,
  Paperclip,
  Pencil,
  Plus,
  Search,
  Settings,
  Trash2,
  X,
} from "lucide-react";
import { useMutation, useQuery } from "@tanstack/react-query";

import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
import { api } from "@/services/api";
import { getMinFiles, type FileUploadSetting } from "@/types/fileUploadSettings";
import { DataTable, type ColumnDef } from "@edr/ui-common";

import EditFileUploadSettingDialog from "./EditFileUploadSettingDialog";
import ManageFileUploadFieldsDialog from "./ManageFileUploadFieldsDialog";
import DeleteFileUploadSettingDialog from "./DeleteFileUploadSettingDialog";

export default function FileUploadSettingsPage() {
  const [query, setQuery] = useState("");

  const { data, isLoading, isError, error, refetch } = useQuery(
    api.fileUploadSettings.list.queryOptions(),
  );
  const deleteMutation = useMutation(api.fileUploadSettings.remove.mutationOptions());

  const fileUploadSettings = useMemo(
    () => (Array.isArray(data) ? data : []),
    [data],
  );

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return fileUploadSettings;
    return fileUploadSettings.filter(
      (s) =>
        s.code.toLowerCase().includes(q) ||
        s.label.toLowerCase().includes(q) ||
        (s.description ?? "").toLowerCase().includes(q) ||
        s.fields.some(
          (f) =>
            f.fileKey.toLowerCase().includes(q) ||
            f.fileLabel.toLowerCase().includes(q),
        ),
    );
  }, [fileUploadSettings, query]);

  const totalFields = fileUploadSettings.reduce(
    (sum, s) => sum + s.fields.length,
    0,
  );
  const requiredFields = fileUploadSettings.reduce(
    (sum, s) => sum + s.fields.filter((f) => f.isRequired).length,
    0,
  );
  const multiFields = fileUploadSettings.reduce(
    (sum, s) => sum + s.fields.filter((f) => f.isMultiple).length,
    0,
  );

  const columns = useMemo<ColumnDef<FileUploadSetting>[]>(() => {
    const headerClassName = ruleEngineTable.headerCell;
    const cellClassName = ruleEngineTable.bodyCell;
    return [
      {
        id: "setting",
        header: "Setting",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => {
          const s = row.original;
          return (
            <Group gap="sm" wrap="nowrap">
              <ThemeIcon size={40} radius="md" variant="light" color="edr-green">
                <FileUp size={18} />
              </ThemeIcon>
              <Stack gap={0} style={{ minWidth: 0, maxWidth: 260 }}>
                <Text size="sm" fw={600} lh={1.2} truncate>
                  {s.label}
                </Text>
                <Text size="xs" c="dimmed" truncate>
                  {s.description ?? "No description"}
                </Text>
              </Stack>
            </Group>
          );
        },
      },
      {
        id: "code",
        header: "Code",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => <Code>{row.original.code}</Code>,
      },
      {
        id: "entity",
        header: "Entity",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Badge variant="light" color="gray" tt="capitalize">
            {row.original.entity ?? "—"}
          </Badge>
        ),
      },
      {
        id: "fields",
        header: "Fields",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Group gap={6} wrap="nowrap">
            <Paperclip size={15} color="var(--mantine-color-edr-green-6)" />
            <Text size="sm" fw={500}>
              {row.original.fields.length}
            </Text>
          </Group>
        ),
      },
      {
        id: "requiredMulti",
        header: "Required / Multi",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => {
          const required = row.original.fields.filter((f) => f.isRequired).length;
          const multi = row.original.fields.filter((f) => f.isMultiple).length;
          return (
            <Group gap={6} wrap="nowrap">
              <Badge variant="light" color="edr-green">
                {required} required
              </Badge>
              <Badge variant="light" color="gray">
                {multi} multi
              </Badge>
            </Group>
          );
        },
      },
      {
        id: "maxSize",
        header: "Max size",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => {
          const maxSize = Math.max(
            0,
            ...row.original.fields.map((f) => f.maxSizeMb),
          );
          return (
            <Group gap={6} wrap="nowrap">
              <HardDrive size={15} color="var(--mantine-color-gray-5)" />
              <Text size="sm">{maxSize ? `${maxSize} MB` : "—"}</Text>
            </Group>
          );
        },
      },
      {
        id: "actions",
        header: "Actions",
        meta: {
          headerClassName,
          cellClassName: `${cellClassName} whitespace-nowrap`,
        },
        cell: ({ row }) => {
          const setting = row.original;
          return (
            <Group gap="xs" justify="flex-end" wrap="nowrap">
              <ManageFileUploadFieldsDialog setting={setting}>
                <Button
                  variant="default"
                  size="xs"
                  leftSection={<Paperclip size={14} />}
                >
                  Fields
                </Button>
              </ManageFileUploadFieldsDialog>

              <EditFileUploadSettingDialog mode="edit" setting={setting}>
                <ActionIcon variant="default" aria-label="Edit setting">
                  <Pencil size={16} />
                </ActionIcon>
              </EditFileUploadSettingDialog>

              <DeleteFileUploadSettingDialog
                settingLabel={setting.label}
                settingCode={setting.code}
                onConfirm={() => deleteMutation.mutate({ id: setting.id })}
              >
                <ActionIcon
                  variant="default"
                  color="red"
                  disabled={deleteMutation.isPending}
                  aria-label="Delete setting"
                >
                  <Trash2 size={16} />
                </ActionIcon>
              </DeleteFileUploadSettingDialog>
            </Group>
          );
        },
      },
    ];
  }, [deleteMutation]);

  const tableStatus = isLoading ? "loading" : isError ? "error" : "success";

  return (
    <PageContainer>
      <PageHeader
        title="File upload settings"
        subtitle="Define the file inputs every form in the platform should render — required/optional, single/multiple, allowed types and size."
        action={
          <EditFileUploadSettingDialog mode="create">
            <Button leftSection={<Plus size={18} />}>New setting</Button>
          </EditFileUploadSettingDialog>
        }
      />

      <KpiStrip
        loading={isLoading}
        items={[
          { label: "Settings", value: fileUploadSettings.length, icon: Settings },
          { label: "Total fields", value: totalFields, icon: Paperclip },
          { label: "Required", value: requiredFields, icon: FileUp },
          { label: "Multi-file", value: multiFields, icon: Layers },
        ]}
      />

      <Card p={0}>
        <Stack gap={0}>
          <Box px="md" pt="md" pb="sm" w="100%">
            <TextInput
              placeholder="Search by code, label, or file key…"
              leftSection={<Search size={18} />}
              value={query}
              onChange={(e) => setQuery(e.currentTarget.value)}
              rightSection={
                query ? (
                  <ActionIcon
                    size="sm"
                    color="gray"
                    variant="transparent"
                    onClick={() => setQuery("")}
                    aria-label="Clear search"
                  >
                    <X size={16} />
                  </ActionIcon>
                ) : null
              }
              style={{ maxWidth: 420 }}
            />
          </Box>

          <Box style={{ overflowX: "auto" }} w="100%">
            <DataTable
              columns={columns}
              data={filtered}
              status={tableStatus}
              error={
                isError
                  ? {
                      message: "Failed to load settings.",
                      description:
                        error instanceof Error ? error.message : "Unknown error.",
                      onRetry: () => void refetch(),
                    }
                  : undefined
              }
              emptyMessage={
                query.trim()
                  ? "No file upload settings match your search."
                  : 'No file upload settings yet. Click "New setting" to add one.'
              }
              containerClassName="border-0 shadow-none bg-transparent min-w-[920px]"
            />
          </Box>
        </Stack>
      </Card>

      <BehaviorReferenceCard />
    </PageContainer>
  );
}

/**
 * Static reference: how `min_files` / `max_files` are derived from the
 * Required × Multiple toggles. Documentation aid for whoever wires uploaders.
 */
function BehaviorReferenceCard() {
  const rows: { required: boolean; multiple: boolean; min: string; max: string }[] =
    [
      { required: false, multiple: false, min: "0", max: "1" },
      { required: true, multiple: false, min: "1", max: "1" },
      { required: false, multiple: true, min: "0", max: "field.maxFiles" },
      { required: true, multiple: true, min: "1", max: "field.maxFiles" },
    ];

  return (
    <Card>
      <Stack gap="xs">
        <Text fw={600}>Required × Multiple behavior</Text>
        <Text size="sm" c="dimmed">
          Min and max file counts are derived from these two toggles. The
          &quot;Max files&quot; you set on a field is only used when{" "}
          <Text span fw={600}>
            Multiple
          </Text>{" "}
          is on.
        </Text>

        <Table mt="sm" striped withRowBorders={false} verticalSpacing="xs">
          <Table.Thead>
            <Table.Tr>
              <Table.Th>Required</Table.Th>
              <Table.Th>Multiple</Table.Th>
              <Table.Th>min_files</Table.Th>
              <Table.Th>max_files</Table.Th>
            </Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {rows.map((r) => (
              <Table.Tr key={`${r.required}-${r.multiple}`}>
                <Table.Td>
                  <Badge variant="light" color={r.required ? "edr-green" : "gray"}>
                    {r.required ? "Required" : "Optional"}
                  </Badge>
                </Table.Td>
                <Table.Td>
                  <Badge variant="light" color={r.multiple ? "edr-green" : "gray"}>
                    {r.multiple ? "Multiple" : "Single"}
                  </Badge>
                </Table.Td>
                <Table.Td>
                  <Code>{r.min}</Code>
                </Table.Td>
                <Table.Td>
                  <Code>{r.max}</Code>
                </Table.Td>
              </Table.Tr>
            ))}
          </Table.Tbody>
        </Table>

        <Text size="xs" c="dimmed">
          Helpers <Code>getMinFiles</Code> and <Code>getEffectiveMaxFiles</Code>{" "}
          live in <Code>@/types/fileUploadSettings</Code> — use them when wiring
          real uploaders. Example: a field with <Code>isRequired=false</Code>,{" "}
          <Code>isMultiple=true</Code>, <Code>maxFiles=5</Code> gives min{" "}
          <Code>
            {getMinFiles({
              isRequired: false,
            })}
          </Code>{" "}
          …5.
        </Text>
      </Stack>
    </Card>
  );
}
