import {
  Anchor,
  Badge,
  Box,
  Card,
  Grid,
  Group,
  Progress,
  SegmentedControl,
  Skeleton,
  Stack,
  Text,
  Title,
  Tooltip as MantineTooltip,
} from "@mantine/core";
import { useMemo, useState, type ReactNode } from "react";
import {
  Area,
  AreaChart,
  CartesianGrid,
  LabelList,
  Line,
  LineChart,
  ResponsiveContainer,
  Tooltip as RechartsTooltip,
  XAxis,
  YAxis,
} from "recharts";
import { usePromoTheme } from "@/routes/promo-code-campaigns/_components/appearance";
import styles from "@/routes/promo-code-campaigns/_components/promo.module.css";
import {
  eventTypeShortLabel,
  FUNNEL_ORDER,
  eventTypeLabel,
  type DayActivity,
  type EventSummary,
  type EventTypeAnalyticsResponse,
  type EventTypeAnalyticsRow,
  type FunnelSummary,
  type PropertyActivity,
  type SourceActivity,
  type SourceFunnel,
} from "@/lib/features/event-analytics/types";


const fmtInt = (n: number) => n.toLocaleString("en-US");

function formatElapsed(hours: number): string {
  if (hours < 0.02) return "< 1m";
  if (hours < 1) return `${Math.round(hours * 60)}m`;
  if (hours < 48) {
    const h = Math.floor(hours);
    const m = Math.round((hours - h) * 60);
    return m ? `${h}h ${m}m` : `${h}h`;
  }
  return `${(hours / 24).toFixed(1)} days`;
}

type TimeMetric = "events" | "points" | "members";
type FunnelView = "funnel" | "line";

type Props = {
  summary: EventSummary | null;
  eventTypes: EventTypeAnalyticsResponse | null;
  funnel: FunnelSummary;
  byDay: DayActivity[];
  byProperty: PropertyActivity[];
  bySource: SourceActivity[];
  funnelBySection: SourceFunnel[];
  funnelByUtmSource: SourceFunnel[];
  loading: boolean;
  onOpenEvent: (eventType: string) => void;
  onToggleEventType: (eventType: string) => void;
  activeEventTypes: string[];
};

const TIME_METRIC_LABEL: Record<TimeMetric, string> = {
  events: "Events",
  points: "Points",
  members: "Members",
};

export default function EventDashboard({
  summary,
  eventTypes,
  funnel,
  byDay,
  byProperty,
  bySource,
  loading,
  onOpenEvent,
  onToggleEventType,
  activeEventTypes,
}: Props) {
  const { series } = usePromoTheme();
  const [funnelView, setFunnelView] = useState<FunnelView>("line");
  const [timeMetric, setTimeMetric] = useState<TimeMetric>("events");

  const funnelSteps = useMemo(
    () =>
      funnel.steps.filter(
        (step, i) =>
          /*
           * The entry step is kept even at zero.
           *
           * Every later step is a share of it, so dropping it would leave the
           * remaining steps measured against a base that is not on screen. It
           * It also keeps an added step honest: a funnel that silently began
           * one stage in would report a conversion rate for a sequence it is
           * not actually measuring.
           */
          i === 0 || step.membersAnyOrder > 0 || step.members > 0,
      ),
    [funnel.steps],
  );

  const colors = useMemo(
    () => series(Math.max(3, funnelSteps.length, byProperty.length)),
    [funnelSteps.length, byProperty.length, series],
  );

  const eventTypeMap = useMemo(() => {
    const map = new Map<string, EventTypeAnalyticsRow>();
    eventTypes?.rows.forEach((r) => map.set(r.eventType, r));
    return map;
  }, [eventTypes]);

  const orderedTags = useMemo(() => {
    return FUNNEL_ORDER.map((tag) => ({
      tag,
      row: eventTypeMap.get(tag) ?? null,
    }));
  }, [eventTypeMap]);

  const basisNoun = funnel.basis === "journey" ? "journeys" : "members";
  const smallSample = funnel.entered < 10;
  const completed = funnelSteps.length
    ? (funnelSteps[funnelSteps.length - 1]?.members ?? 0)
    : 0;

  const endToEndAccent =
    colors[Math.max(0, funnelSteps.length - 1)]?.from ??
    "var(--mantine-color-teal-6)";

  const lineData = useMemo(
    () =>
      funnelSteps.map((step) => ({
        // Short on the axis, full name on the tooltip below.
        step: eventTypeShortLabel(step.eventType),
        fullStep: eventTypeLabel(step.eventType),
        members: step.members,
        anyOrder: step.membersAnyOrder,
      })),
    [funnelSteps],
  );

  if (loading && !summary) {
    return (
      <Grid gutter="md">
        {[0, 1].map((i) => (
          <Grid.Col key={i} span={{ base: 12, lg: 6 }}>
            <Skeleton h={260} radius="md" />
          </Grid.Col>
        ))}
      </Grid>
    );
  }

  return (
    <Stack gap="xl">
      {/* ── Row 1: Funnel & App Event Tags ───────────────────────────────── */}
      <Grid gutter="md">
        {/* Left: Booking Funnel */}
        <Grid.Col span={{ base: 12, lg: 6 }}>
          <Card className={styles.sectionCard} p="md" h="100%">
            <Stack gap="sm">
              <Group justify="space-between" align="center" wrap="nowrap">
                <Group gap="xs" align="center" wrap="nowrap">
                  <Title order={5}>
                    {funnel.basis === "journey"
                      ? "Conversion funnel"
                      : "Booking funnel"}
                  </Title>
                  <MantineTooltip
                    withArrow
                    multiline
                    w={300}
                    label={
                      funnel.basis === "journey"
                        ? "One row per booking attempt, correlated by journeyId."
                        : "Tracked in sequence across add_to_cart → booking_hold_initiated → purchase."
                    }
                  >
                    <Badge
                      size="xs"
                      variant="light"
                      color={funnel.basis === "journey" ? "teal" : "yellow"}
                    >
                      {funnel.basis === "journey" ? "by journey" : "by member"}
                    </Badge>
                  </MantineTooltip>
                </Group>
                <SegmentedControl
                  size="xs"
                  value={funnelView}
                  onChange={(v) => setFunnelView(v as FunnelView)}
                  data={[
                    { value: "funnel", label: "Funnel" },
                    { value: "line", label: "Line" },
                  ]}
                />
              </Group>

              {funnelSteps.length === 0 ? (
                <Text c="dimmed" size="sm" py="md">
                  No events recorded in this date range.
                </Text>
              ) : funnelView === "line" ? (
                <Stack gap="xs">
                  <Box style={{ height: 248 }}>
                    <ResponsiveContainer width="100%" height="100%">
                      <LineChart
                        data={lineData}
                        margin={{ top: 18, right: 16, bottom: 12, left: 0 }}
                      >
                        <CartesianGrid
                          strokeDasharray="3 3"
                          vertical={false}
                          opacity={0.25}
                        />
                        <XAxis
                          dataKey="step"
                          tick={{ fontSize: 11 }}
                          interval={0}
                          tickLine={false}
                          /* The first and last steps sit on the plot edges, so
                             their labels were sliced by the container —
                             "Purchase" arrived as "Purchas". */
                          padding={{ left: 20, right: 20 }}
                          height={42}
                          label={{
                            value: "Funnel step",
                            position: "insideBottom",
                            offset: -2,
                            fontSize: 11,
                            fill: "var(--mantine-color-dimmed)",
                          }}
                        />
                        <YAxis
                          allowDecimals={false}
                          tick={{ fontSize: 11 }}
                          tickLine={false}
                          axisLine={false}
                          width={48}
                          label={{
                            value: "Journeys reached",
                            angle: -90,
                            position: "insideLeft",
                            fontSize: 11,
                            fill: "var(--mantine-color-dimmed)",
                            style: { textAnchor: "middle" },
                          }}
                        />
                        <RechartsTooltip
                          contentStyle={{ fontSize: 12, borderRadius: 8 }}
                          /* The axis is abbreviated, so the tooltip carries the
                             step's real name. */
                          labelFormatter={(label, payload) =>
                            (payload?.[0]?.payload as { fullStep?: string })
                              ?.fullStep ?? String(label)
                          }
                          formatter={(value, name) => [
                            fmtInt(Number(value)),
                            String(name),
                          ]}
                        />
                        <Line
                          type="monotone"
                          dataKey="anyOrder"
                          name="Any order"
                          stroke="var(--mantine-color-dimmed)"
                          strokeDasharray="5 4"
                          strokeWidth={1.5}
                          dot={{ r: 3 }}
                        />
                        <Line
                          type="monotone"
                          dataKey="members"
                          name="In sequence"
                          stroke={endToEndAccent}
                          strokeWidth={2.5}
                          dot={{ r: 5, strokeWidth: 2, fill: "#fff" }}
                          activeDot={{ r: 7 }}
                        >
                          <LabelList
                            dataKey="members"
                            position="top"
                            offset={10}
                            style={{ fontSize: 12, fontWeight: 700 }}
                          />
                        </Line>
                      </LineChart>
                    </ResponsiveContainer>
                  </Box>
                  <Group gap="lg" justify="center">
                    <Group gap={6} wrap="nowrap">
                      <Box
                        style={{
                          width: 16,
                          height: 3,
                          borderRadius: 2,
                          background: endToEndAccent,
                        }}
                      />
                      <Text size="xs" c="dimmed">
                        Reached in sequence
                      </Text>
                    </Group>
                    <Group gap={6} wrap="nowrap">
                      <Box
                        style={{
                          width: 16,
                          height: 0,
                          borderTop: "2px dashed var(--mantine-color-dimmed)",
                        }}
                      />
                      <Text size="xs" c="dimmed">
                        Any event of type
                      </Text>
                    </Group>
                  </Group>
                </Stack>
              ) : (
                <Stack gap={2}>
                  {funnelSteps.map((row, i) => {
                    const share = funnel.entered
                      ? (row.members / funnel.entered) * 100
                      : 0;
                    const accent =
                      colors[i]?.from ?? "var(--mantine-color-teal-6)";
                    const previous = i > 0 ? funnelSteps[i - 1] : null;
                    const dropped = previous
                      ? Math.max(0, previous.members - row.members)
                      : 0;
                    const width = row.members > 0 ? Math.max(share, 18) : 0;

                    return (
                      <Box key={row.eventType}>
                        {previous && (
                          <Group justify="center" gap={6} wrap="nowrap" py={6}>
                            <Text
                              size="xs"
                              fw={700}
                              c={dropped ? "red.6" : "teal.6"}
                            >
                              {dropped === 0
                                ? `all ${fmtInt(previous.members)} continued`
                                : `${fmtInt(row.members)} of ${fmtInt(
                                  previous.members,
                                )} continued · ${fmtInt(dropped)} stopped`}
                            </Text>
                            {!smallSample && row.conversionPct !== null && (
                              <Text size="xs" c="dimmed">
                                ({row.conversionPct.toFixed(1)}%)
                              </Text>
                            )}
                            {row.medianHoursFromPrevious !== null && (
                              <Text size="xs" c="dimmed">
                                · {formatElapsed(row.medianHoursFromPrevious)}
                              </Text>
                            )}
                          </Group>
                        )}

                        <MantineTooltip
                          withArrow
                          label={
                            row.members === row.membersAnyOrder
                              ? `${fmtInt(row.members)} ${basisNoun}`
                              : `${fmtInt(row.members)} in sequence · ${fmtInt(
                                row.membersAnyOrder,
                              )} with any event`
                          }
                        >
                          <Box
                            style={{
                              height: 54,
                              display: "flex",
                              alignItems: "center",
                              justifyContent: "center",
                              borderRadius: "var(--mantine-radius-md)",
                              border:
                                "1px dashed var(--mantine-color-default-border)",
                              cursor: "help",
                            }}
                          >
                            {width > 0 ? (
                              <Group
                                justify="space-between"
                                wrap="nowrap"
                                px={14}
                                style={{
                                  width: `${width}%`,
                                  height: "100%",
                                  minWidth: 0,
                                  color: "#fff",
                                  borderRadius: "var(--mantine-radius-md)",
                                  background: accent,
                                  transition: "width 320ms ease",
                                }}
                              >
                                <Stack gap={0} style={{ minWidth: 0 }}>
                                  <Text size="sm" fw={700} lineClamp={1}>
                                    {eventTypeLabel(row.eventType)}
                                  </Text>
                                  <Text
                                    size="xs"
                                    style={{ color: "rgba(255,255,255,.8)" }}
                                  >
                                    {i === 0
                                      ? "entered here"
                                      : smallSample
                                        ? `${fmtInt(row.members)} of ${fmtInt(
                                          funnel.entered,
                                        )}`
                                        : `${share.toFixed(1)}%`}
                                  </Text>
                                </Stack>
                                <Text
                                  fz={24}
                                  fw={800}
                                  lh={1}
                                  className={styles.num}
                                >
                                  {fmtInt(row.members)}
                                </Text>
                              </Group>
                            ) : (
                              <Group
                                justify="space-between"
                                wrap="nowrap"
                                px={14}
                                style={{ width: "100%" }}
                              >
                                <Text size="sm" fw={700} c="dimmed">
                                  {eventTypeLabel(row.eventType)}
                                </Text>
                                <Text fz={24} fw={800} lh={1} c="dimmed">
                                  0
                                </Text>
                              </Group>
                            )}
                          </Box>
                        </MantineTooltip>
                      </Box>
                    );
                  })}

                  {funnelSteps.length > 1 && (
                    <Group
                      justify="space-between"
                      align="center"
                      mt="xs"
                      p="sm"
                      style={{
                        borderRadius: "var(--mantine-radius-md)",
                        background: `color-mix(in srgb, ${endToEndAccent} 12%, transparent)`,
                        border: `1px solid color-mix(in srgb, ${endToEndAccent} 35%, transparent)`,
                      }}
                    >
                      <Stack gap={0}>
                        <Text size="xs" c="dimmed" tt="uppercase" fw={700}>
                          Completed every step
                        </Text>
                        <Text size="xs" c="dimmed">
                          {completed === 0
                            ? `None of the ${fmtInt(funnel.entered)} ${basisNoun} that entered`
                            : `${fmtInt(completed)} of ${fmtInt(
                              funnel.entered,
                            )} ${basisNoun} that entered`}
                        </Text>
                      </Stack>
                      <Text fz={24} fw={800} lh={1} className={styles.num}>
                        {smallSample
                          ? `${fmtInt(completed)}/${fmtInt(funnel.entered)}`
                          : `${funnel.completionPct.toFixed(1)}%`}
                      </Text>
                    </Group>
                  )}
                </Stack>
              )}
            </Stack>
          </Card>
        </Grid.Col>

        {/* Right: App Event Tags Breakdown */}
        <Grid.Col span={{ base: 12, lg: 6 }}>
          <Card className={styles.sectionCard} p="md" h="100%">
            <Stack gap="sm" justify="space-between" h="100%">
              <Stack gap="xs">
                <Stack gap={0}>
                  <Title order={5}>Event tags breakdown</Title>
                </Stack>

                <Group gap="lg" wrap="wrap" my="xs">
                  <Stack gap={0}>
                    <Text size="xs" c="dimmed" tt="uppercase" fw={600}>
                      Total Events
                    </Text>
                    <Text fz={20} fw={700} lh={1.2} className={styles.num}>
                      {fmtInt(summary?.totalEvents ?? 0)}
                    </Text>
                  </Stack>
                  <Stack gap={0}>
                    <Text size="xs" c="dimmed" tt="uppercase" fw={600}>
                      Members
                    </Text>
                    <Text fz={20} fw={700} lh={1.2} className={styles.num}>
                      {fmtInt(summary?.uniqueMembers ?? 0)}
                    </Text>
                  </Stack>
                  <Stack gap={0}>
                    <Text size="xs" c="dimmed" tt="uppercase" fw={600}>
                      Points Earned
                    </Text>
                    <Text fz={20} fw={700} lh={1.2} className={styles.num}>
                      {fmtInt(summary?.totalPoints ?? 0)}
                    </Text>
                  </Stack>
                </Group>

                <Stack gap={8}>
                  {orderedTags.map((t, i) => {
                    const row = t.row;
                    const count = row?.events ?? 0;
                    const mbrs = row?.uniqueMembers ?? 0;
                    const totalEvents = summary?.totalEvents || 1;
                    const share = (count / totalEvents) * 100;
                    const accent = colors[i % colors.length] ?? colors[0];
                    const active = activeEventTypes.includes(t.tag);

                    return (
                      <Box
                        key={t.tag}
                        p="xs"
                        style={{
                          borderRadius: "var(--mantine-radius-sm)",
                          background:
                            "light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-5))",
                        }}
                      >
                        <Group justify="space-between" mb={6} wrap="nowrap">
                          <Group gap="xs" wrap="nowrap" style={{ minWidth: 0 }}>
                            <Text
                              size="xs"
                              fw={700}
                              c="dimmed"
                              w={14}
                              ta="right"
                            >
                              {i + 1}
                            </Text>
                            <Badge
                              size="xs"
                              variant={active ? "filled" : "light"}
                              style={{
                                cursor: "pointer",
                                backgroundColor: active
                                  ? accent?.from
                                  : undefined,
                              }}
                              onClick={() => onToggleEventType(t.tag)}
                            >
                              <Text size="sm" fw={600} lineClamp={1}>
                                {eventTypeLabel(t.tag)}
                              </Text>
                            </Badge>

                          </Group>

                          <Group gap="md" wrap="nowrap">
                            <Text size="xs" c="dimmed">
                              {mbrs} {mbrs === 1 ? "member" : "members"}
                            </Text>
                            <Text size="sm" fw={700} className={styles.num}>
                              {fmtInt(count)}
                            </Text>
                            <Anchor
                              component="button"
                              type="button"
                              size="xs"
                              onClick={() => onOpenEvent(t.tag)}
                            >
                              View →
                            </Anchor>
                          </Group>
                        </Group>

                        <Box
                          ml={22}
                          style={{
                            height: 6,
                            borderRadius: 999,
                            overflow: "hidden",
                            background: "var(--mantine-color-default-border)",
                          }}
                        >
                          <Box
                            style={{
                              height: "100%",
                              width: `${Math.max(4, share)}%`,
                              borderRadius: 999,
                              background: accent.from,
                              transition: "width 300ms ease",
                            }}
                          />
                        </Box>
                      </Box>
                    );
                  })}
                </Stack>
              </Stack>
            </Stack>
          </Card>
        </Grid.Col>
      </Grid>

      {/* ── Row 2: Activity Over Time & Resorts ─────────────────────────── */}
      <Grid gutter="md">
        {/* Left: Activity Over Time */}
        <Grid.Col span={{ base: 12, lg: 6 }}>
          <Card className={styles.sectionCard} p="md" h="100%">
            <Stack gap="sm">
              <Group justify="space-between" align="center" wrap="wrap">
                <Stack gap={0}>
                  <Title order={5}>Activity over time</Title>
                  <Text size="xs" c="dimmed">
                    {byDay.length} day{byDay.length === 1 ? "" : "s"} with
                    activity
                  </Text>
                </Stack>

                <SegmentedControl
                  size="xs"
                  value={timeMetric}
                  onChange={(v) => setTimeMetric(v as TimeMetric)}
                  data={[
                    { value: "events", label: "Events" },
                    { value: "points", label: "Points" },
                    { value: "members", label: "Members" },
                  ]}
                />
              </Group>

              {byDay.length === 0 ? (
                <Text c="dimmed" size="sm" py="md">
                  No dated events in this range.
                </Text>
              ) : (
                <ResponsiveContainer width="100%" height={240}>
                  <AreaChart
                    data={byDay}
                    margin={{ left: 4, right: 12, top: 8, bottom: 12 }}
                  >
                    <defs>
                      <linearGradient
                        id="eventActivityFill"
                        x1="0"
                        y1="0"
                        x2="0"
                        y2="1"
                      >
                        <stop
                          offset="0%"
                          stopColor={colors[0]?.from ?? "#c2a154"}
                          stopOpacity={0.4}
                        />
                        <stop
                          offset="100%"
                          stopColor={colors[0]?.to ?? "#c2a154"}
                          stopOpacity={0.04}
                        />
                      </linearGradient>
                    </defs>
                    <CartesianGrid
                      strokeDasharray="3 3"
                      vertical={false}
                      opacity={0.25}
                    />
                    <XAxis
                      dataKey="day"
                      fontSize={11}
                      tickLine={false}
                      tickFormatter={(d: string) => d.slice(5)}
                      minTickGap={24}
                      height={38}
                      /* The first and last points sit on the plot edges, so their labels were
                         half-clipped by the container. Insetting the scale keeps every date
                         readable — most visible with only a few days in range. */
                      padding={{ left: 14, right: 14 }}
                      label={{
                        value: "Date",
                        position: "insideBottom",
                        offset: -2,
                        fontSize: 11,
                        fill: "var(--mantine-color-dimmed)",
                      }}
                    />
                    <YAxis
                      fontSize={11}
                      tickLine={false}
                      axisLine={false}
                      allowDecimals={false}
                      width={48}
                      label={{
                        value: TIME_METRIC_LABEL[timeMetric],
                        angle: -90,
                        position: "insideLeft",
                        fontSize: 11,
                        fill: "var(--mantine-color-dimmed)",
                        style: { textAnchor: "middle" },
                      }}
                    />
                    <RechartsTooltip
                      contentStyle={{ fontSize: 12, borderRadius: 8 }}
                      formatter={(val) => [
                        Number(val).toLocaleString("en-US"),
                        TIME_METRIC_LABEL[timeMetric],
                      ]}
                    />
                    <Area
                      type="monotone"
                      dataKey={timeMetric}
                      stroke={colors[0]?.from ?? "#c2a154"}
                      strokeWidth={2}
                      dot={{ r: 3, strokeWidth: 2, fill: "#fff" }}
                      activeDot={{ r: 6 }}
                      fill="url(#eventActivityFill)"
                    />
                  </AreaChart>
                </ResponsiveContainer>
              )}
            </Stack>
          </Card>
        </Grid.Col>

        {/* Right: Activity by Resort */}
        <Grid.Col span={{ base: 12, lg: 6 }}>
          <Card className={styles.sectionCard} p="md" h="100%">
            <Stack gap="sm" h="100%">
              <Stack gap={0}>
                <Title order={5}>Activity by resort</Title>
              </Stack>

              {byProperty.length === 0 ? (
                <Text c="dimmed" size="sm" py="md">
                  No property recorded on these events.
                </Text>
              ) : (
                <Stack gap={8}>
                  {byProperty.slice(0, 5).map((prop, i) => {
                    const carts = prop.eventsByType?.add_to_cart ?? 0;
                    const holds =
                      prop.eventsByType?.booking_hold_initiated ?? 0;
                    const purchases = prop.eventsByType?.purchase ?? 0;
                    const accent = colors[i % colors.length] ?? colors[0];

                    return (
                      <Box
                        key={prop.property}
                        p="xs"
                        style={{
                          borderRadius: "var(--mantine-radius-sm)",
                          background:
                            "light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-5))",
                        }}
                      >
                        <Group justify="space-between" mb={4} wrap="nowrap">
                          <Text size="sm" fw={600} lineClamp={1}>
                            {prop.property}
                          </Text>
                          <Group gap="xs" wrap="nowrap">
                            <Text size="xs" c="dimmed">
                              {prop.members} mbr
                            </Text>
                            <Text size="sm" fw={700} className={styles.num}>
                              {fmtInt(prop.events)}
                            </Text>
                          </Group>
                        </Group>

                        <Group gap={4} wrap="nowrap">
                          {carts > 0 && (
                            <Badge size="xs" variant="light" color="gray">
                              {carts} cart
                            </Badge>
                          )}
                          {holds > 0 && (
                            <Badge size="xs" variant="light" color="gray">
                              {holds} hold
                            </Badge>
                          )}
                          {purchases > 0 && (
                            <Badge size="xs" variant="light" color="teal">
                              {purchases} purchase
                            </Badge>
                          )}
                        </Group>
                      </Box>
                    );
                  })}
                </Stack>
              )}
            </Stack>
          </Card>
        </Grid.Col>
      </Grid>
    </Stack>
  );
}
