import { useState, useEffect, useCallback, useRef } from 'react';
import { purchaserApi, textileApi, washingApi } from '../api';
import type { ProductionPlan, WashingPlan } from '../types';

export type DashboardRole = 'purchaser' | 'textile' | 'washing';

interface DashboardStats {
  all: number;
  producing: number;
  completed: number;
}

interface UseDashboardDataOptions {
  role: DashboardRole;
  companyId: string | null;
}

interface DashboardDataState<T> {
  plans: T[];
  stats: DashboardStats;
  loading: boolean;
  error: Error | null;
  rejectedPlanIds: Set<string>;
}

export function useDashboardData<T = ProductionPlan | WashingPlan>({
  role,
  companyId
}: UseDashboardDataOptions) {
  const [state, setState] = useState<DashboardDataState<T>>({
    plans: [],
    stats: { all: 0, producing: 0, completed: 0 },
    loading: true,
    error: null,
    rejectedPlanIds: new Set()
  });

  const cacheRef = useRef<{
    data: DashboardDataState<T> | null;
    timestamp: number;
  }>({ data: null, timestamp: 0 });

  const CACHE_DURATION = 5000;

  const fetchPurchaserData = useCallback(async () => {
    const [statsData, plansRes] = await Promise.all([
      purchaserApi.dashboardStats(),
      purchaserApi.listPlans(),
    ]);
    const rawData = plansRes.data;
    const plans = (Array.isArray(rawData) ? rawData : (rawData?.plans || [])) as unknown as T[];
    const stats: DashboardStats = {
      all: statsData.total_plans ?? 0,
      producing: statsData.producing_plans ?? 0,
      completed: statsData.completed_plans ?? 0,
    };
    return { plans, stats, rejectedPlanIds: new Set<string>() };
  }, []);

  const fetchTextileData = useCallback(async () => {
    const [statsData, plansRes] = await Promise.all([
      textileApi.dashboardStats(),
      textileApi.listPlans(),
    ]);
    const plans = (plansRes.data || []) as unknown as T[];
    const stats: DashboardStats = {
      all: statsData.total_plans,
      producing: statsData.producing_plans,
      completed: statsData.completed_plans,
    };
    return { plans, stats, rejectedPlanIds: new Set<string>() };
  }, []);

  const fetchWashingData = useCallback(async () => {
    const [statsData, plansRes] = await Promise.all([
      washingApi.dashboardStats(),
      washingApi.listPlans(),
    ]);
    const plans = plansRes.data as unknown as T[];
    const stats: DashboardStats = {
      all: statsData.total_plans,
      producing: statsData.processing_plans,
      completed: statsData.completed_plans,
    };
    return { plans, stats, rejectedPlanIds: new Set<string>() };
  }, []);

  const fetchData = useCallback(async () => {
    if (!companyId) {
      setState(prev => ({ ...prev, loading: false }));
      return;
    }

    const now = Date.now();
    if (cacheRef.current.data && (now - cacheRef.current.timestamp) < CACHE_DURATION) {
      setState(cacheRef.current.data);
      return;
    }

    try {
      let result: { plans: T[]; stats: DashboardStats; rejectedPlanIds: Set<string> } | undefined;

      switch (role) {
        case 'purchaser':
          result = await fetchPurchaserData();
          break;
        case 'textile':
          result = await fetchTextileData();
          break;
        case 'washing':
          result = await fetchWashingData();
          break;
      }

      if (result) {
        const newState: DashboardDataState<T> = {
          plans: result.plans,
          stats: result.stats,
          loading: false,
          error: null,
          rejectedPlanIds: result.rejectedPlanIds
        };
        setState(newState);
        cacheRef.current = { data: newState, timestamp: now };
      }
    } catch (err) {
      setState(prev => ({
        ...prev,
        loading: false,
        error: err instanceof Error ? err : new Error('Unknown error')
      }));
    }
  }, [companyId, role, fetchPurchaserData, fetchTextileData, fetchWashingData]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const refresh = useCallback(() => {
    cacheRef.current = { data: null, timestamp: 0 };
    fetchData();
  }, [fetchData]);

  return {
    ...state,
    refresh
  };
}
