import {
  ActionIcon,
  Badge,
  Button,
  Card,
  Center,
  Code,
  Collapse,
  Group,
  Loader,
  Stack,
  Table,
  Text,
} from "@mantine/core";
import styles from "@/routes/promo-code-campaigns/_components/promo.module.css";
import { IconChevronDown, IconChevronRight } from "@tabler/icons-react";
import { Fragment, useState } from "react";
import {
  eventTypeLabel,
  type EventRecord,
} from "@/lib/features/event-analytics/types";

/**
 * Date for display, falling back to the producer's raw string.
 *
 * `occurredAt` is the parsed value and reads better, but it is null whenever
 * parsing fails — and a "—" where Firestore plainly holds a date reads as
 * missing data rather than as a formatting problem. Showing the raw string is
 * uglier and correct.
 */
const fmtDateTime = (record: { occurredAt: string | null; createdAtRaw: string | null }) => {
  if (record.occurredAt) return record.occurredAt.replace("T", " ").slice(0, 19);
  return record.createdAtRaw ?? "—";
};

const fmtMoney = (revenue: number | null, currency: string | null) => {
  if (revenue === null) return "—";
  const amount = revenue.toLocaleString("en-US", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });
  return currency ? `${currency} ${amount}` : amount;
};

type Props = {
  records: EventRecord[];
  loading: boolean;
  total: number | null;
  hasMore: boolean;
  page: number;
  onNextPage: () => void;
  onPrevPage: () => void;
};

export default function EventRecords({
  records,
  loading,
  total,
  hasMore,
  page,
  onNextPage,
  onPrevPage,
}: Props) {
  const [expanded, setExpanded] = useState<string | null>(null);

  if (loading && records.length === 0) {
    return (
      <Center py="xl">
        <Loader size="sm" />
      </Center>
    );
  }

  if (records.length === 0) {
    return (
      <Card className={styles.sectionCard} p="xl">
        <Text c="dimmed" ta="center">
          No event records for these filters.
        </Text>
      </Card>
    );
  }

  return (
    <Stack gap="sm">
      <Group justify="space-between">
        <Text size="sm" c="dimmed">
          {/* Null total means a text search is active and core could not count
              the matches — showing the unfiltered count would be a lie. */}
          {total === null
            ? "Total unavailable while searching"
            : `${total.toLocaleString("en-US")} matching events`}
        </Text>
        <Text size="sm" c="dimmed">
          Page {page}
        </Text>
      </Group>

      <Card className={styles.tableCard} p={0}>
        <Table.ScrollContainer minWidth={1000}>
        <Table highlightOnHover verticalSpacing="sm" horizontalSpacing="md">
          <Table.Thead className={styles.tableHead}>
            <Table.Tr>
              <Table.Th w={40} />
              <Table.Th>Created at</Table.Th>
              <Table.Th>Event type</Table.Th>
              <Table.Th>Source</Table.Th>
              <Table.Th>Member</Table.Th>
              <Table.Th>Property</Table.Th>
              <Table.Th>Experience / offer</Table.Th>
              <Table.Th ta="right">Points</Table.Th>
              <Table.Th ta="right">Revenue</Table.Th>
            </Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {records.map((record) => {
              const open = expanded === record.id;
              return (
                <Fragment key={record.id}>
                  <Table.Tr>
                    <Table.Td>
                      <ActionIcon
                        variant="subtle"
                        color="gray"
                        size="sm"
                        aria-label={open ? "Hide raw document" : "Show raw document"}
                        onClick={() => setExpanded(open ? null : record.id)}
                      >
                        {open ? (
                          <IconChevronDown size={15} />
                        ) : (
                          <IconChevronRight size={15} />
                        )}
                      </ActionIcon>
                    </Table.Td>
                    <Table.Td>{fmtDateTime(record)}</Table.Td>
                    <Table.Td>
                      <Badge variant="light" color="gray">
                        {eventTypeLabel(record.eventType)}
                      </Badge>
                    </Table.Td>
                    <Table.Td>{record.source ?? "—"}</Table.Td>
                    <Table.Td>{record.memberName ?? record.memberId ?? "—"}</Table.Td>
                    <Table.Td>{record.propertyName ?? "—"}</Table.Td>
                    <Table.Td>
                      {/* The producer fills at most one of these per event. */}
                      {record.experienceName ?? record.memberOffer ?? "—"}
                    </Table.Td>
                    <Table.Td ta="right">
                      {record.points === null
                        ? "—"
                        : record.points.toLocaleString("en-US")}
                    </Table.Td>
                    <Table.Td ta="right">
                      {fmtMoney(record.revenue, record.currency)}
                    </Table.Td>
                  </Table.Tr>
                  <Table.Tr>
                    <Table.Td colSpan={9} p={0} style={{ borderBottom: open ? undefined : "none" }}>
                      <Collapse in={open}>
                        {/* The untouched Firestore document. Worth keeping while
                            the producer's schema is still being confirmed — it is
                            the fastest way to see a field the mapper missed. */}
                        <Code block p="md" style={{ fontSize: 12 }}>
                          {JSON.stringify(record.raw, null, 2)}
                        </Code>
                      </Collapse>
                    </Table.Td>
                  </Table.Tr>
                </Fragment>
              );
            })}
          </Table.Tbody>
        </Table>
        </Table.ScrollContainer>
      </Card>

      {/* Cursor paging: forward only from the current position, so there is no
          page-number jump. Deep paging stays as cheap as page one. */}
      <Group justify="flex-end">
        <Button
          variant="default"
          size="sm"
          disabled={page === 1 || loading}
          onClick={onPrevPage}
        >
          Previous
        </Button>
        <Button
          variant="default"
          size="sm"
          disabled={!hasMore || loading}
          onClick={onNextPage}
        >
          Next
        </Button>
      </Group>
    </Stack>
  );
}
