import { create } from 'zustand';
import type {
  FunnelEntry,
  FunnelStage,
  FunnelConversionStats,
  FunnelClientDetail,
  AssignClientDto,
  MoveStageDto,
  TransferClientDto,
  RefuseClientDto,
} from '../types/funnel';
import { funnelService } from '../services/funnel';

interface EntriesByStage {
  data: FunnelEntry[];
  cursor: string | null;
  hasMore: boolean;
  total: number;
}

const emptyEntries: EntriesByStage = {
  data: [],
  cursor: null,
  hasMore: false,
  total: 0,
};

interface FunnelState {
  entriesByStage: Record<FunnelStage, EntriesByStage>;
  activeStage: FunnelStage;
  clientDetail: FunnelClientDetail | null;
  stats: FunnelConversionStats | null;
  isLoading: boolean;
  isLoadingMore: boolean;
  isLoadingDetail: boolean;
  isSubmitting: boolean;
  error: string | null;

  setActiveStage: (stage: FunnelStage) => void;
  fetchByStage: (stage: FunnelStage, refresh?: boolean) => Promise<void>;
  fetchMore: (stage: FunnelStage) => Promise<void>;
  fetchClientDetail: (clientId: string) => Promise<void>;
  assignClient: (dto: AssignClientDto) => Promise<void>;
  moveStage: (clientId: string, dto: MoveStageDto) => Promise<void>;
  transferClient: (clientId: string, dto: TransferClientDto) => Promise<void>;
  refuseClient: (clientId: string, dto: RefuseClientDto) => Promise<void>;
  fetchStats: (dateFrom?: string, dateTo?: string) => Promise<void>;
  clearError: () => void;
}

export const useFunnelStore = create<FunnelState>((set, get) => ({
  entriesByStage: {
    NEW: { ...emptyEntries },
    ASSIGNED: { ...emptyEntries },
    APPOINTMENT_SET: { ...emptyEntries },
    COMPLETED: { ...emptyEntries },
    REGULAR: { ...emptyEntries },
    TRANSFERRED: { ...emptyEntries },
    REFUSED: { ...emptyEntries },
  },
  activeStage: 'NEW',
  clientDetail: null,
  stats: null,
  isLoading: false,
  isLoadingMore: false,
  isLoadingDetail: false,
  isSubmitting: false,
  error: null,

  setActiveStage: (stage: FunnelStage) => {
    set({ activeStage: stage });
    const entries = get().entriesByStage[stage];
    if (entries.data.length === 0) {
      get().fetchByStage(stage);
    }
  },

  fetchByStage: async (stage: FunnelStage, refresh = false) => {
    set({ isLoading: true, error: null });
    try {
      const response = await funnelService.getFunnelEntries({
        stage,
        limit: 20,
      });
      set((state) => ({
        entriesByStage: {
          ...state.entriesByStage,
          [stage]: {
            data: response.data,
            cursor: response.cursor,
            hasMore: response.hasMore,
            total: response.total,
          },
        },
        isLoading: false,
      }));
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Ошибка загрузки воронки';
      set({ error: message, isLoading: false });
    }
  },

  fetchMore: async (stage: FunnelStage) => {
    const entries = get().entriesByStage[stage];
    if (!entries.hasMore || get().isLoadingMore) return;

    set({ isLoadingMore: true });
    try {
      const response = await funnelService.getFunnelEntries({
        stage,
        cursor: entries.cursor ?? undefined,
        limit: 20,
      });
      set((state) => ({
        entriesByStage: {
          ...state.entriesByStage,
          [stage]: {
            data: [...entries.data, ...response.data],
            cursor: response.cursor,
            hasMore: response.hasMore,
            total: response.total,
          },
        },
        isLoadingMore: false,
      }));
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Ошибка загрузки';
      set({ error: message, isLoadingMore: false });
    }
  },

  fetchClientDetail: async (clientId: string) => {
    set({ isLoadingDetail: true, error: null, clientDetail: null });
    try {
      const detail = await funnelService.getClientFunnel(clientId);
      set({ clientDetail: detail, isLoadingDetail: false });
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Ошибка загрузки клиента';
      set({ error: message, isLoadingDetail: false });
    }
  },

  assignClient: async (dto: AssignClientDto) => {
    set({ isSubmitting: true, error: null });
    try {
      await funnelService.assignClient(dto);
      await get().fetchByStage('NEW', true);
      await get().fetchByStage('ASSIGNED', true);
      set({ isSubmitting: false });
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Ошибка назначения';
      set({ error: message, isSubmitting: false });
      throw err;
    }
  },

  moveStage: async (clientId: string, dto: MoveStageDto) => {
    set({ isSubmitting: true, error: null });
    try {
      await funnelService.moveStage(clientId, dto);
      const activeStage = get().activeStage;
      await get().fetchByStage(activeStage, true);
      await get().fetchByStage(dto.toStage, true);
      set({ isSubmitting: false });
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Ошибка перемещения';
      set({ error: message, isSubmitting: false });
      throw err;
    }
  },

  transferClient: async (clientId: string, dto: TransferClientDto) => {
    set({ isSubmitting: true, error: null });
    try {
      await funnelService.transferClient(clientId, dto);
      const activeStage = get().activeStage;
      await get().fetchByStage(activeStage, true);
      set({ isSubmitting: false });
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Ошибка передачи';
      set({ error: message, isSubmitting: false });
      throw err;
    }
  },

  refuseClient: async (clientId: string, dto: RefuseClientDto) => {
    set({ isSubmitting: true, error: null });
    try {
      await funnelService.refuseClient(clientId, dto);
      const activeStage = get().activeStage;
      await get().fetchByStage(activeStage, true);
      await get().fetchByStage('REFUSED', true);
      set({ isSubmitting: false });
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Ошибка отказа';
      set({ error: message, isSubmitting: false });
      throw err;
    }
  },

  fetchStats: async (dateFrom?: string, dateTo?: string) => {
    set({ isLoading: true, error: null });
    try {
      const stats = await funnelService.getConversionStats(dateFrom, dateTo);
      set({ stats, isLoading: false });
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Ошибка загрузки статистики';
      set({ error: message, isLoading: false });
    }
  },

  clearError: () => {
    set({ error: null });
  },
}));
