// PeriodFilter - Reusable component for filtering by date periods

import { useState, useMemo } from 'react';
import { Space, Select, DatePicker, Typography } from 'antd';
import { CalendarOutlined } from '@ant-design/icons';
import dayjs, { Dayjs } from 'dayjs';
import quarterOfYear from 'dayjs/plugin/quarterOfYear';
import { usePeriodStore } from '@/stores/periodStore';
import { spacing } from '@/styles/designTokens';

dayjs.extend(quarterOfYear);

const { RangePicker } = DatePicker;
const { Text } = Typography;

export type PeriodPreset =
  | 'today'
  | 'yesterday'
  | 'this_week'
  | 'last_week'
  | 'this_month'
  | 'last_month'
  | 'this_quarter'
  | 'last_quarter'
  | 'this_year'
  | 'last_year'
  | 'custom';

export interface DateRange {
  startDate: Dayjs;
  endDate: Dayjs;
}

export interface PeriodFilterProps {
  value?: PeriodPreset;
  dateRange?: DateRange;
  onChange?: (preset: PeriodPreset, dateRange: DateRange) => void;
  showLabel?: boolean;
  size?: 'small' | 'middle' | 'large';
}

const presetOptions: { value: PeriodPreset; label: string }[] = [
  { value: 'today', label: 'I dag' },
  { value: 'yesterday', label: 'I går' },
  { value: 'this_week', label: 'Denne uge' },
  { value: 'last_week', label: 'Sidste uge' },
  { value: 'this_month', label: 'Denne måned' },
  { value: 'last_month', label: 'Sidste måned' },
  { value: 'this_quarter', label: 'Dette kvartal' },
  { value: 'last_quarter', label: 'Sidste kvartal' },
  { value: 'this_year', label: 'Dette regnskabsår' },
  { value: 'last_year', label: 'Sidste regnskabsår' },
  { value: 'custom', label: 'Vælg datoer...' },
];

export function getDateRangeForPreset(preset: PeriodPreset, fiscalYearStartMonth?: number): DateRange {
  const today = dayjs();
  const fyStart = fiscalYearStartMonth || 1; // Default to January

  // Helper to get fiscal year start date
  const getFiscalYearStart = (year: number) => {
    const fy = dayjs().year(year).month(fyStart - 1).startOf('month');
    // If we're before the fiscal year start month, use previous year
    if (today.isBefore(dayjs().month(fyStart - 1).startOf('month'))) {
      return fy.subtract(1, 'year');
    }
    return fy;
  };

  switch (preset) {
    case 'today':
      return { startDate: today.startOf('day'), endDate: today.endOf('day') };

    case 'yesterday':
      return {
        startDate: today.subtract(1, 'day').startOf('day'),
        endDate: today.subtract(1, 'day').endOf('day'),
      };

    case 'this_week':
      return {
        startDate: today.startOf('week'),
        endDate: today.endOf('week'),
      };

    case 'last_week':
      return {
        startDate: today.subtract(1, 'week').startOf('week'),
        endDate: today.subtract(1, 'week').endOf('week'),
      };

    case 'this_month':
      return {
        startDate: today.startOf('month'),
        endDate: today.endOf('month'),
      };

    case 'last_month':
      return {
        startDate: today.subtract(1, 'month').startOf('month'),
        endDate: today.subtract(1, 'month').endOf('month'),
      };

    case 'this_quarter':
      return {
        startDate: today.startOf('quarter'),
        endDate: today.endOf('quarter'),
      };

    case 'last_quarter':
      return {
        startDate: today.subtract(1, 'quarter').startOf('quarter'),
        endDate: today.subtract(1, 'quarter').endOf('quarter'),
      };

    case 'this_year': {
      const fyStartDate = getFiscalYearStart(today.year());
      return {
        startDate: fyStartDate,
        endDate: fyStartDate.add(1, 'year').subtract(1, 'day'),
      };
    }

    case 'last_year': {
      const fyStartDate = getFiscalYearStart(today.year()).subtract(1, 'year');
      return {
        startDate: fyStartDate,
        endDate: fyStartDate.add(1, 'year').subtract(1, 'day'),
      };
    }

    case 'custom':
    default:
      return { startDate: today.startOf('month'), endDate: today.endOf('month') };
  }
}

export function PeriodFilter({
  value = 'this_month',
  dateRange: externalDateRange,
  onChange,
  showLabel = true,
  size = 'middle',
}: PeriodFilterProps) {
  const { currentFiscalYear } = usePeriodStore();
  const [selectedPreset, setSelectedPreset] = useState<PeriodPreset>(value);
  const [customRange, setCustomRange] = useState<[Dayjs, Dayjs] | null>(null);

  const fiscalYearStartMonth = currentFiscalYear?.startDate
    ? dayjs(currentFiscalYear.startDate).month() + 1
    : 1;

  const currentDateRange = useMemo(() => {
    if (externalDateRange) return externalDateRange;
    if (selectedPreset === 'custom' && customRange) {
      return { startDate: customRange[0], endDate: customRange[1] };
    }
    return getDateRangeForPreset(selectedPreset, fiscalYearStartMonth);
  }, [selectedPreset, customRange, externalDateRange, fiscalYearStartMonth]);

  const handlePresetChange = (newPreset: PeriodPreset) => {
    setSelectedPreset(newPreset);
    if (newPreset !== 'custom') {
      const newRange = getDateRangeForPreset(newPreset, fiscalYearStartMonth);
      onChange?.(newPreset, newRange);
    }
  };

  const handleCustomRangeChange = (dates: [Dayjs, Dayjs] | null) => {
    setCustomRange(dates);
    if (dates) {
      onChange?.('custom', { startDate: dates[0], endDate: dates[1] });
    }
  };

  const formatDateRange = () => {
    const { startDate, endDate } = currentDateRange;
    if (startDate.isSame(endDate, 'day')) {
      return startDate.format('D. MMM YYYY');
    }
    if (startDate.isSame(endDate, 'year')) {
      return `${startDate.format('D. MMM')} - ${endDate.format('D. MMM YYYY')}`;
    }
    return `${startDate.format('D. MMM YYYY')} - ${endDate.format('D. MMM YYYY')}`;
  };

  return (
    <Space size={spacing.sm}>
      {showLabel && (
        <Space size={4}>
          <CalendarOutlined />
          <Text type="secondary">Periode:</Text>
        </Space>
      )}

      <Select
        value={selectedPreset}
        onChange={handlePresetChange}
        options={presetOptions}
        style={{ minWidth: 160 }}
        size={size}
      />

      {selectedPreset === 'custom' && (
        <RangePicker
          value={customRange}
          onChange={(dates) => handleCustomRangeChange(dates as [Dayjs, Dayjs] | null)}
          format="DD-MM-YYYY"
          size={size}
          allowClear={false}
        />
      )}

      {selectedPreset !== 'custom' && (
        <Text type="secondary" style={{ marginLeft: spacing.xs }}>
          {formatDateRange()}
        </Text>
      )}
    </Space>
  );
}

export default PeriodFilter;
