import { useState, useCallback, useMemo } from 'react';
import type { TimeRange, TimeGranularity } from '../../types';

export type PresetTimeRange =
  | 'today'
  | 'yesterday'
  | 'last7days'
  | 'last30days'
  | 'last90days'
  | 'thisMonth'
  | 'lastMonth'
  | 'thisYear'
  | 'custom';

interface UseTimeRangeOptions {
  initialPreset?: PresetTimeRange;
  initialRange?: TimeRange;
}

interface UseTimeRangeReturn {
  timeRange: TimeRange;
  preset: PresetTimeRange;
  setPreset: (preset: PresetTimeRange) => void;
  setCustomRange: (range: TimeRange) => void;
  suggestedGranularity: TimeGranularity;
}

const getPresetRange = (preset: PresetTimeRange): TimeRange => {
  const now = new Date();
  const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate());

  switch (preset) {
    case 'today':
      return {
        start: startOfDay,
        end: now,
      };
    case 'yesterday': {
      const yesterday = new Date(startOfDay);
      yesterday.setDate(yesterday.getDate() - 1);
      return {
        start: yesterday,
        end: startOfDay,
      };
    }
    case 'last7days': {
      const start = new Date(startOfDay);
      start.setDate(start.getDate() - 7);
      return { start, end: now };
    }
    case 'last30days': {
      const start = new Date(startOfDay);
      start.setDate(start.getDate() - 30);
      return { start, end: now };
    }
    case 'last90days': {
      const start = new Date(startOfDay);
      start.setDate(start.getDate() - 90);
      return { start, end: now };
    }
    case 'thisMonth': {
      const start = new Date(now.getFullYear(), now.getMonth(), 1);
      return { start, end: now };
    }
    case 'lastMonth': {
      const start = new Date(now.getFullYear(), now.getMonth() - 1, 1);
      const end = new Date(now.getFullYear(), now.getMonth(), 0);
      return { start, end };
    }
    case 'thisYear': {
      const start = new Date(now.getFullYear(), 0, 1);
      return { start, end: now };
    }
    default:
      return {
        start: startOfDay,
        end: now,
      };
  }
};

const getSuggestedGranularity = (range: TimeRange): TimeGranularity => {
  const diffMs = range.end.getTime() - range.start.getTime();
  const diffDays = diffMs / (1000 * 60 * 60 * 24);

  if (diffDays <= 1) return 'hour';
  if (diffDays <= 7) return 'day';
  if (diffDays <= 90) return 'day';
  if (diffDays <= 365) return 'week';
  return 'month';
};

export function useTimeRange(options: UseTimeRangeOptions = {}): UseTimeRangeReturn {
  const { initialPreset = 'last7days', initialRange } = options;

  const [preset, setPresetState] = useState<PresetTimeRange>(
    initialRange ? 'custom' : initialPreset
  );
  const [customRange, setCustomRangeState] = useState<TimeRange | null>(
    initialRange || null
  );

  const timeRange = useMemo(() => {
    if (preset === 'custom' && customRange) {
      return customRange;
    }
    return getPresetRange(preset);
  }, [preset, customRange]);

  const suggestedGranularity = useMemo(
    () => getSuggestedGranularity(timeRange),
    [timeRange]
  );

  const setPreset = useCallback((newPreset: PresetTimeRange) => {
    setPresetState(newPreset);
    if (newPreset !== 'custom') {
      setCustomRangeState(null);
    }
  }, []);

  const setCustomRange = useCallback((range: TimeRange) => {
    setPresetState('custom');
    setCustomRangeState(range);
  }, []);

  return {
    timeRange,
    preset,
    setPreset,
    setCustomRange,
    suggestedGranularity,
  };
}
