import { useEffect, useState } from 'react';
import {
  Button,
  Card,
  Group,
  MultiSelect,
  SegmentedControl,
  TextInput,
} from '@mantine/core';
import { DatePickerInput } from '@mantine/dates';
import { IconDownload, IconSearch, IconX } from '@tabler/icons-react';
import type {
  ReportGranularity,
  VesselCategory,
  VesselReport,
  VesselReportQuery,
  VesselStatus,
} from '@ema-platform/api';
import { optionsFrom } from './report-format';

const CATEGORY_OPTIONS = [
  { value: 'SEA_GOING', label: 'Sea-going' },
  { value: 'INLAND_WATERWAY', label: 'Inland waterway' },
];

const STATUS_OPTIONS = [
  { value: 'REGISTERED', label: 'Registered' },
  { value: 'SUSPENDED', label: 'Suspended' },
  { value: 'DEREGISTERED', label: 'Deregistered' },
];

const GRANULARITY_OPTIONS = [
  { value: 'DAY', label: 'Day' },
  { value: 'WEEK', label: 'Week' },
  { value: 'MONTH', label: 'Month' },
];

interface ReportFiltersProps {
  query: VesselReportQuery;
  onChange: (next: VesselReportQuery) => void;
  /**
   * The last successful response. Flag states, ports and vessel types are free
   * text on the register with no lookup endpoint behind them, so the only
   * honest source for the options is what the register actually holds.
   */
  report?: VesselReport;
  onExport: () => void;
  exporting: boolean;
}

export function ReportFilters({
  query,
  onChange,
  report,
  onExport,
  exporting,
}: ReportFiltersProps) {
  // The search box is local so typing does not refetch on every keystroke; it
  // is pushed up on a debounce.
  const [search, setSearch] = useState(query.search ?? '');

  useEffect(() => {
    setSearch(query.search ?? '');
  }, [query.search]);

  useEffect(() => {
    const current = query.search ?? '';
    if (search === current) return;
    const timer = setTimeout(
      () => onChange({ ...query, search: search.trim() || undefined }),
      350,
    );
    return () => clearTimeout(timer);
  }, [search, query, onChange]);

  const set = <K extends keyof VesselReportQuery>(
    key: K,
    value: VesselReportQuery[K],
  ) => onChange({ ...query, [key]: value });

  // Mantine 8 works in `YYYY-MM-DD` strings here, which is exactly what the
  // API wants — no Date round trip, and no timezone to shift the day.
  const range: [string | null, string | null] = [
    query.from ?? null,
    query.to ?? null,
  ];

  const filtered =
    Boolean(query.search) ||
    Boolean(query.from) ||
    Boolean(query.to) ||
    [
      query.category,
      query.status,
      query.flagState,
      query.portOfRegistry,
      query.vesselType,
    ].some((values) => (values ?? []).length > 0);

  return (
    <Card withBorder radius="md" p="md" mb="md">
      <Group align="flex-end" gap="sm" wrap="wrap">
        <DatePickerInput
          type="range"
          label="Period"
          placeholder="Last 12 months"
          value={range}
          // Both ends before refetching: a half-set range would send `from`
          // with no `to` and redraw the charts against a window the user is
          // still in the middle of choosing.
          onChange={([from, to]) => {
            if (from && !to) return;
            onChange({
              ...query,
              from: from ?? undefined,
              to: to ?? undefined,
            });
          }}
          clearable
          w={250}
        />

        <SegmentedControl
          size="sm"
          data={GRANULARITY_OPTIONS}
          value={query.granularity ?? 'MONTH'}
          onChange={(value) => set('granularity', value as ReportGranularity)}
        />

        <MultiSelect
          label="Category"
          placeholder="All"
          data={CATEGORY_OPTIONS}
          value={query.category ?? []}
          onChange={(value) => set('category', value as VesselCategory[])}
          clearable
          w={190}
        />

        <MultiSelect
          label="Status"
          placeholder="All"
          data={STATUS_OPTIONS}
          value={query.status ?? []}
          onChange={(value) => set('status', value as VesselStatus[])}
          clearable
          w={190}
        />

        <MultiSelect
          label="Flag state"
          placeholder="All"
          data={optionsFrom(report?.breakdowns.byFlagState)}
          value={query.flagState ?? []}
          onChange={(value) => set('flagState', value)}
          searchable
          clearable
          w={190}
        />

        <MultiSelect
          label="Port of registry"
          placeholder="All"
          data={optionsFrom(report?.breakdowns.byPortOfRegistry)}
          value={query.portOfRegistry ?? []}
          onChange={(value) => set('portOfRegistry', value)}
          searchable
          clearable
          w={190}
        />

        <MultiSelect
          label="Vessel type"
          placeholder="All"
          data={optionsFrom(report?.breakdowns.byVesselType)}
          value={query.vesselType ?? []}
          onChange={(value) => set('vesselType', value)}
          searchable
          clearable
          w={190}
        />

        <TextInput
          label="Search"
          placeholder="Name, register №, IMO or owner"
          leftSection={<IconSearch size={14} />}
          value={search}
          onChange={(event) => setSearch(event.currentTarget.value)}
          w={250}
        />

        <Group gap="xs" ml="auto">
          {filtered && (
            <Button
              variant="subtle"
              color="gray"
              leftSection={<IconX size={14} />}
              onClick={() => onChange({})}
            >
              Clear
            </Button>
          )}
          <Button
            variant="light"
            leftSection={<IconDownload size={16} />}
            loading={exporting}
            onClick={onExport}
          >
            Export CSV
          </Button>
        </Group>
      </Group>
    </Card>
  );
}
