"use client";

/**
 * Everything retired through this page, newest first.
 *
 * Read from core's own `account_deletion_records` rather than the activity log,
 * because two of the columns here — the notice and the follow-up — are written after
 * the request that created the row, the follow-up a month later.
 *
 * Both mails get their own column for the same reason: they can end differently, and
 * one combined "emailed" state would hide a follow-up that never went.
 */

import {
  ActionIcon,
  Anchor,
  Badge,
  Button,
  Card,
  Group,
  Modal,
  Pagination,
  Skeleton,
  Stack,
  Table,
  Text,
  TextInput,
  Tooltip,
} from "@mantine/core";
import { notifications } from "@mantine/notifications";
import {
  IconHistory,
  IconRefresh,
  IconRotateClockwise,
  IconSearch,
} from "@tabler/icons-react";
import { useCallback, useEffect, useState } from "react";
import { Link } from "react-router";
import {
  listDeletionRecords,
  reactivateAccount,
  type DeletionRecord,
  type EdmStatus,
} from "@/lib/features/account-deletion/query";
import styles from "@/routes/promo-code-campaigns/_components/promo.module.css";

const PAGE_SIZE = 10;

const EDM_TONE: Record<EdmStatus, { color?: string }> = {
  sent: { color: "green" },
  pending: { color: "gray" },
  // Distinct on purpose: "skipped" is a configuration state (no template id, no
  // address on file) and "failed" is a delivery problem. Colouring them the same
  // would bury real failures in whichever is more common.
  skipped: { color: "yellow" },
  // Reactivated before the 30 days were up, so the mail was stood down rather than
  // failing. Blue keeps it visibly distinct from both.
  cancelled: { color: "blue" },
  failed: { color: "red" },
};

const REGION_LABEL: Record<string, string> = {
  uk: "UK",
  europe: "Europe",
  india: "India",
  indonesia: "Indonesia",
  others: "Rest of world",
};

const formatWhen = (value: string | null): string => {
  if (!value) return "—";
  const parsed = new Date(value);
  return Number.isFinite(parsed.getTime()) ? parsed.toLocaleString() : "—";
};

const formatDay = (value: string | null): string => {
  if (!value) return "—";
  const parsed = new Date(value);
  return Number.isFinite(parsed.getTime()) ? parsed.toLocaleDateString() : "—";
};

const EdmCell: React.FC<{
  status: EdmStatus;
  at: string | null;
  error: string | null;
  due?: string | null;
}> = ({ status, at, error, due }) => (
  <Tooltip
    label={error ?? (status === "pending" && due ? `Due ${formatDay(due)}` : formatWhen(at))}
    disabled={!error && !at && !due}
    multiline
    w={280}
  >
    <Badge variant="light" {...EDM_TONE[status]}>
      {status}
    </Badge>
  </Tooltip>
);

interface Props {
  /** Bumped by the parent after a deletion, to pull the new row in. */
  refreshToken: number;
}

const DeletionHistoryTable: React.FC<Props> = ({ refreshToken }) => {
  const [records, setRecords] = useState<DeletionRecord[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [search, setSearch] = useState("");
  const [applied, setApplied] = useState("");
  const [loading, setLoading] = useState(true);
  const [reactivating, setReactivating] = useState<DeletionRecord | null>(null);
  const [submitting, setSubmitting] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    const response = await listDeletionRecords({
      page,
      pageSize: PAGE_SIZE,
      search: applied || undefined,
    });
    if (response.success && response.data) {
      setRecords(response.data.items);
      setTotal(response.data.pagination.total);
    } else {
      setRecords([]);
      setTotal(0);
    }
    setLoading(false);
  }, [applied, page]);

  useEffect(() => {
    void load();
  }, [load, refreshToken]);

  const confirmReactivate = useCallback(async () => {
    if (!reactivating) return;
    setSubmitting(true);
    const response = await reactivateAccount(reactivating.id);
    setSubmitting(false);

    if (!response.success) {
      notifications.show({
        color: "red",
        message: response.message || "Failed to reactivate the account",
      });
      return;
    }

    notifications.show({
      color: "green",
      message: `Account ${reactivating.accountNumber} restored to ${response.data?.restoredStatus.name}${
        response.data?.followupCancelled
          ? " — the data-deletion email was cancelled"
          : ""
      }`,
    });

    if (response.data?.viewpointLogError) {
      notifications.show({
        color: "orange",
        autoClose: false,
        title: "Viewpoint log note not written",
        message: response.data.viewpointLogError,
      });
    }
    setReactivating(null);
    await load();
  }, [load, reactivating]);

  const pageCount = Math.max(1, Math.ceil(total / PAGE_SIZE));

  return (
    <Card className={styles.sectionCard} p="md">
      <Stack gap="sm">
        <Group justify="space-between" align="flex-end">
          <Group gap="xs">
            <IconHistory size={18} />
            <Text fw={600}>Deletion history</Text>
            <Badge variant="light" color="gray">
              {total}
            </Badge>
          </Group>
          <Group gap="xs">
            <TextInput
              placeholder="Account, name, operator or status"
              leftSection={<IconSearch size={14} />}
              value={search}
              onChange={(event) => setSearch(event.currentTarget.value)}
              onKeyDown={(event) => {
                if (event.key === "Enter") {
                  // Page reset on a new term: staying on page 3 of a narrower
                  // result set shows an empty table for a search that matched.
                  setPage(1);
                  setApplied(search.trim());
                }
              }}
              w={280}
            />
            <ActionIcon
              variant="default"
              onClick={() => void load()}
              aria-label="Refresh"
            >
              <IconRefresh size={16} />
            </ActionIcon>
          </Group>
        </Group>

        {loading ? (
          <Skeleton height={200} radius="md" />
        ) : records.length === 0 ? (
          <Text size="sm" c="dimmed" ta="center" py="lg">
            Nothing has been deleted yet.
          </Text>
        ) : (
          <Table highlightOnHover>
            <Table.Thead className={styles.tableHead}>
              <Table.Tr>
                <Table.Th className={styles.th}>Account</Table.Th>
                <Table.Th className={styles.th}>Status change</Table.Th>
                <Table.Th className={styles.th}>Applied</Table.Th>
                <Table.Th className={styles.th}>By</Table.Th>
                <Table.Th className={styles.th}>Notice EDM</Table.Th>
                {/* Not "30-day": the window is a console setting now, and each
                    record carries the one it was retired under. */}
                <Table.Th className={styles.th}>Data-deletion EDM</Table.Th>
                <Table.Th className={styles.th}>Effect</Table.Th>
                <Table.Th className={styles.th} />
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {records.map((record) => (
                <Table.Tr key={record.id}>
                  <Table.Td>
                    <Stack gap={0}>
                      {/*
                        The number is the way through to the member.

                        Every column here is about one membership, and the question
                        a row prompts is almost always "what else is going on with
                        this account" — which lives on the member page's Deletion
                        tab, not in this table. `?tab=deletion` selects it.
                      */}
                      <Anchor
                        component={Link}
                        to={`/admin/members/${record.accountNumber}?tab=deletion`}
                        size="sm"
                        fw={500}
                      >
                        {record.accountNumber}
                      </Anchor>
                      <Group gap={4}>
                        <Text size="xs" c="dimmed">
                          {record.accountName ?? "—"}
                        </Text>
                        {/*
                          The region is on the row because it decides which two
                          letters went out, and "why did this member get the Rest of
                          world letter" is a question the template id alone does not
                          answer legibly.
                        */}
                        {record.region && (
                          <Badge size="xs" variant="outline" color="gray">
                            {REGION_LABEL[record.region] ?? record.region}
                          </Badge>
                        )}
                      </Group>
                    </Stack>
                  </Table.Td>
                  <Table.Td>
                    <Group gap={6}>
                      <Text size="sm" c="dimmed">
                        {record.previousStatus ?? "—"}
                      </Text>
                      <Text size="sm">→</Text>
                      <Badge variant="light">{record.statusName}</Badge>
                    </Group>
                  </Table.Td>
                  <Table.Td>
                    <Tooltip label={record.reason} multiline w={280}>
                      <Text size="sm">{formatWhen(record.createdAt)}</Text>
                    </Tooltip>
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm">{record.performedBy ?? "—"}</Text>
                  </Table.Td>
                  <Table.Td>
                    <EdmCell
                      status={record.noticeEdmStatus}
                      at={record.noticeEdmAt}
                      error={record.noticeEdmError}
                    />
                  </Table.Td>
                  <Table.Td>
                    <EdmCell
                      status={record.followupEdmStatus}
                      at={record.followupEdmAt}
                      error={record.followupEdmError}
                      due={record.followupDueAt}
                    />
                  </Table.Td>
                  <Table.Td>
                    <Stack gap={0}>
                      <Text size="xs" c="dimmed">
                        {record.membersUpdated} member
                        {record.membersUpdated === 1 ? "" : "s"} ·{" "}
                        {record.sessionsRevoked} session
                        {record.sessionsRevoked === 1 ? "" : "s"} dropped
                      </Text>
                      {record.viewpointLogStatus === "failed" && (
                        <Tooltip
                          label={record.viewpointLogError}
                          multiline
                          w={280}
                        >
                          <Badge size="xs" color="orange" variant="light">
                            no Viewpoint note
                          </Badge>
                        </Tooltip>
                      )}
                      {record.localError && (
                        <Tooltip label={record.localError} multiline w={280}>
                          <Badge size="xs" color="orange" variant="light">
                            core not updated
                          </Badge>
                        </Tooltip>
                      )}
                    </Stack>
                  </Table.Td>
                  <Table.Td>
                    {record.reactivatedAt ? (
                      <Tooltip
                        label={`Restored to ${record.reactivatedToStatus ?? "—"} by ${record.reactivatedBy ?? "—"} on ${formatWhen(record.reactivatedAt)}`}
                        multiline
                        w={280}
                      >
                        <Badge color="green" variant="light">
                          reactivated
                        </Badge>
                      </Tooltip>
                    ) : (
                      <Tooltip
                        label="This record does not say what status the account held before, so it cannot be restored automatically."
                        disabled={record.canReactivate}
                        multiline
                        w={280}
                      >
                        <Button
                          size="compact-sm"
                          variant="light"
                          leftSection={<IconRotateClockwise size={14} />}
                          disabled={!record.canReactivate}
                          onClick={() => setReactivating(record)}
                        >
                          Reactivate
                        </Button>
                      </Tooltip>
                    )}
                  </Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        )}

        {pageCount > 1 && (
          <Group justify="flex-end">
            <Pagination value={page} onChange={setPage} total={pageCount} />
          </Group>
        )}
      </Stack>

      <Modal
        opened={Boolean(reactivating)}
        onClose={() => setReactivating(null)}
        title={`Reactivate account ${reactivating?.accountNumber ?? ""}`}
        centered
      >
        <Stack gap="md">
          <Text size="sm">
            The account goes back to{" "}
            <strong>{reactivating?.previousStatus ?? "its previous status"}</strong>{" "}
            in Viewpoint, and the member record and sign-in are re-enabled. This
            writes to Viewpoint, the same live system the deletion did.
          </Text>
          {reactivating?.followupEdmStatus === "pending" && (
            <Text size="sm" c="dimmed">
              The 30-day email is still pending and will be cancelled, so the member
              is not told about a closure that has been reversed.
            </Text>
          )}
          <Text size="sm" c="dimmed">
            Sessions are not restored — they were dropped at deletion, and the member
            signs in again.
          </Text>
          <Group justify="flex-end">
            <Button
              variant="default"
              onClick={() => setReactivating(null)}
              disabled={submitting}
            >
              Cancel
            </Button>
            <Button
              color="green"
              loading={submitting}
              onClick={() => void confirmReactivate()}
            >
              Reactivate
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Card>
  );
};

export default DeletionHistoryTable;
