import { useState, useEffect, useCallback, useRef } from 'react';
import { purchaserApi } from '../api';
import type { PlanDetail } from '../api/purchaser';
import { CACHE_CONFIG, PAGINATION_CONFIG } from '../config/app';
import { usePlanRealtime } from './useRealtime';
import type {
  PlanWithSteps,
  Company,
  PlanFactory,
  YarnRatio,
} from '../types';

interface UsePlanDataOptions {
  companyId: string | null;
  pageSize?: number;
}

interface PlanDataState {
  plans: PlanWithSteps[];
  factories: Company[];
  planFactories: PlanFactory[];
  operatorNames: Record<string, string>;
  yarnRatios: Record<string, YarnRatio[]>;
  loading: boolean;
  loadingMore: boolean;
  hasMore: boolean;
  currentPage: number;
  error: Error | null;
}

function mapPlanDetail(plan: PlanDetail): PlanWithSteps {
  return {
    ...plan,
    processSteps: plan.process_steps,
    inventoryRecords: plan.inventory_records,
    priceHistory: plan.price_history,
  };
}

export function usePlanData({ companyId, pageSize = PAGINATION_CONFIG.defaultPageSize }: UsePlanDataOptions) {
  const [state, setState] = useState<PlanDataState>({
    plans: [],
    factories: [],
    planFactories: [],
    operatorNames: {},
    yarnRatios: {},
    loading: true,
    loadingMore: false,
    hasMore: true,
    currentPage: 1,
    error: null
  });

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

  const CACHE_DURATION = CACHE_CONFIG.planDataDuration;

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

    const isFirstPage = page === 1;

    if (isFirstPage) {
      const now = Date.now();
      if (cacheRef.current.data && now - cacheRef.current.timestamp < CACHE_DURATION) {
        setState(cacheRef.current.data);
        return;
      }
      setState(prev => ({ ...prev, loading: true, error: null }));
    } else {
      setState(prev => ({ ...prev, loadingMore: true }));
    }

    try {
      const res = await purchaserApi.listPlans({ page, page_size: pageSize });
      const rawData = res.data;

      // API returns plain array when backend doesn't wrap in object
      const planDetails: PlanDetail[] = Array.isArray(rawData)
        ? rawData
        : (rawData?.plans || []);
      const factories: Company[] = Array.isArray(rawData) ? [] : (rawData?.factories || []);
      const plan_factories: PlanFactory[] = Array.isArray(rawData) ? [] : (rawData?.plan_factories || []);
      const operator_names: Record<string, string> = Array.isArray(rawData) ? {} : (rawData?.operator_names || {});

      const plansWithSteps = planDetails.map(mapPlanDetail);

      const yarnRatiosMap: Record<string, YarnRatio[]> = {};
      planDetails.forEach(p => {
        if (p.yarn_ratios && p.yarn_ratios.length > 0) {
          yarnRatiosMap[p.id] = p.yarn_ratios;
        }
      });

      setState(prev => {
        const newState: PlanDataState = {
          plans: append ? [...prev.plans, ...plansWithSteps] : plansWithSteps,
          factories: isFirstPage ? factories : prev.factories,
          planFactories: isFirstPage ? plan_factories : prev.planFactories,
          operatorNames: isFirstPage ? operator_names : { ...prev.operatorNames, ...operator_names },
          yarnRatios: isFirstPage ? yarnRatiosMap : { ...prev.yarnRatios, ...yarnRatiosMap },
          loading: false,
          loadingMore: false,
          hasMore: res.meta?.has_more ?? planDetails.length === pageSize,
          currentPage: page,
          error: null
        };

        if (isFirstPage) {
          cacheRef.current = { data: newState, timestamp: Date.now() };
        }

        return newState;
      });
    } catch (err) {
      setState(prev => ({
        ...prev,
        loading: false,
        loadingMore: false,
        error: err instanceof Error ? err : new Error('Unknown error')
      }));
    }
  }, [companyId, pageSize]);

  const loadMore = useCallback(() => {
    if (state.loadingMore || !state.hasMore) return;
    fetchData(state.currentPage + 1, true);
  }, [fetchData, state.currentPage, state.hasMore, state.loadingMore]);

  const refetch = useCallback(() => {
    cacheRef.current.timestamp = 0;
    fetchData(1, false);
  }, [fetchData]);

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

  usePlanRealtime(companyId, () => {
    cacheRef.current.timestamp = 0;
    fetchData(1, false);
  });

  return {
    ...state,
    loadMore,
    refetch
  };
}
