import { Group, SegmentedControl, Stack, Text } from "@mantine/core";
import { IconCalendarStats } from "@tabler/icons-react";
import { useMemo } from "react";
import {
  formatDateParam,
  formatDateRange,
  type EventAnalyticsFilters,
} from "@/lib/features/event-analytics/types";
import type { ComparePeriod } from "../_hooks/useComparePeriod";

const DAY_MS = 24 * 60 * 60 * 1000;

const toDateParam = (d: Date) => {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
};

/**
 * The ranges worth one click.
 *
 * "All" is kept and is the default: this dataset is young, and defaulting to a
 * window would hide most of it behind a filter nobody set. The presets are for
 * narrowing, and narrowing is also what turns the trend arrows on, since a
 * comparison needs a range to shift.
 */
const PRESETS = [
  { value: "7", label: "7 days" },
  { value: "28", label: "28 days" },
  { value: "90", label: "90 days" },
  { value: "all", label: "All time" },
];

/**
 * Date range presets with the comparison window named underneath.
 *
 * Modelled on the Firebase/GA console header: the range selector and the period
 * it is being measured against sit together, so a reader who sees "↑ 27.1%" on a
 * tile can see what it is 27% more *than* without opening the filter drawer.
 */
export default function PeriodBar({
  filters,
  onChange,
  compare,
}: {
  filters: EventAnalyticsFilters;
  onChange: (next: Partial<EventAnalyticsFilters>) => void;
  compare: ComparePeriod;
}) {
  /*
   * Which preset is active, derived from the dates rather than stored.
   *
   * The range can also be set from the drawer's date picker or arrive in a
   * pasted URL, and a stored selection would then disagree with the dates
   * actually in force.
   */
  const active = useMemo(() => {
    if (!filters.from || !filters.to) return "all";
    const match = PRESETS.find((p) => {
      if (p.value === "all") return false;
      const days = Number(p.value);
      const to = new Date();
      const from = new Date(to.getTime() - (days - 1) * DAY_MS);
      return (
        filters.from === toDateParam(from) && filters.to === toDateParam(to)
      );
    });
    return match?.value ?? "custom";
  }, [filters.from, filters.to]);

  const apply = (value: string) => {
    if (value === "all") {
      onChange({ from: null, to: null });
      return;
    }
    const days = Number(value);
    const to = new Date();
    const from = new Date(to.getTime() - (days - 1) * DAY_MS);
    onChange({ from: toDateParam(from), to: toDateParam(to) });
  };

  return (
    /*
     * Right-aligned beside the title on a desktop, full width underneath it on
     * a phone — where a right-aligned control sits against the screen edge with
     * its caption trailing off, and the four segments are too narrow to tap.
     */
    <Stack
      gap={4}
      align="flex-end"
      style={{ flex: "1 1 260px", minWidth: 0 }}
    >
      <SegmentedControl
        size="xs"
        radius="md"
        fullWidth
        value={active === "custom" ? "" : active}
        onChange={apply}
        data={
          // A custom range picked in the drawer is shown as its own segment, so
          // the control never looks like it has nothing selected.
          active === "custom"
            ? [{ value: "", label: "Custom" }, ...PRESETS]
            : PRESETS
        }
      />
      {/* The caption wraps rather than pushing the layout wider: on a narrow
          screen "compare 12 Nov – 9 Dec" belongs on its own line. */}
      <Group gap={6} wrap="wrap" justify="flex-end">
        <IconCalendarStats size={13} opacity={0.6} />
        <Text size="xs" c="dimmed">
          {formatDateRange(filters.from, filters.to)}
        </Text>
        {compare.range && (
          <Text size="xs" c="dimmed">
            · compare {formatDateParam(compare.range.from)} –{" "}
            {formatDateParam(compare.range.to)}
          </Text>
        )}
      </Group>
    </Stack>
  );
}
