import { useAppStore } from '../appStore';
import { Race, Tip, UserPreferences } from '../../types';

// Helper to get fresh store state for each test
const resetStore = () => {
  useAppStore.setState({
    selectedRace: null,
    selectedBetType: 'best_bet',
    currentTip: null,
    preferences: null,
    isLoading: false,
  });
};

const mockRace: Race = {
  id: 'race-1',
  racing_type: 'thoroughbred',
  track: 'Flemington',
  race_number: 7,
  start_time: '2026-05-06T14:30:00Z',
  distance: 1600,
  race_class: 'Group 1',
  conditions: 'Good',
  prize_money: 500000,
  runner_count: 12,
};

const mockTip: Tip = {
  id: 'tip-1',
  race_id: 'race-1',
  bet_type: 'best_bet',
  recommended_bet: 'Horse A to Win',
  confidence: 'high',
  runners: [
    {
      id: 'runner-1',
      number: 1,
      name: 'Horse A',
      rider: 'Jockey A',
      trainer: 'Trainer A',
      weight: 58,
      barrier: 3,
      form: '1-2-1',
      win_probability: 35.5,
      place_probability: 65.2,
      badges: ['Favourite'],
    },
  ],
  reasons: [
    { text: 'Strong recent form', type: 'positive' },
    { text: 'Good barrier draw', type: 'positive' },
  ],
  created_at: '2026-05-06T10:00:00Z',
};

const mockPreferences: UserPreferences = {
  id: 'prefs-1',
  default_bet_type: 'win',
  default_lead_time: 30,
  favorite_tracks: ['Flemington', 'Randwick'],
  notification_channels: { push: true, sms: false, email: false },
  onboarding_complete: true,
  preferred_racing_types: ['thoroughbred'],
  preferred_race_classes: ['Group 1'],
  preferred_distances: ['1600m'],
  preferred_conditions: ['Good'],
};

describe('useAppStore', () => {
  beforeEach(() => {
    resetStore();
  });

  describe('initial state', () => {
    it('should initialize with null selectedRace', () => {
      const state = useAppStore.getState();
      expect(state.selectedRace).toBeNull();
    });

    it('should initialize with best_bet as default selectedBetType', () => {
      const state = useAppStore.getState();
      expect(state.selectedBetType).toBe('best_bet');
    });

    it('should initialize with null currentTip', () => {
      const state = useAppStore.getState();
      expect(state.currentTip).toBeNull();
    });

    it('should initialize with null preferences', () => {
      const state = useAppStore.getState();
      expect(state.preferences).toBeNull();
    });

    it('should initialize with false isLoading', () => {
      const state = useAppStore.getState();
      expect(state.isLoading).toBe(false);
    });
  });

  describe('actions - setSelectedRace', () => {
    it('should set a race', () => {
      useAppStore.getState().setSelectedRace(mockRace);
      const state = useAppStore.getState();
      expect(state.selectedRace).toEqual(mockRace);
      expect(state.selectedRace?.track).toBe('Flemington');
    });

    it('should clear race to null', () => {
      useAppStore.getState().setSelectedRace(mockRace);
      useAppStore.getState().setSelectedRace(null);
      const state = useAppStore.getState();
      expect(state.selectedRace).toBeNull();
    });
  });

  describe('actions - setSelectedBetType', () => {
    it('should set the bet type', () => {
      useAppStore.getState().setSelectedBetType('win');
      expect(useAppStore.getState().selectedBetType).toBe('win');
    });

    it('should change bet type multiple times', () => {
      useAppStore.getState().setSelectedBetType('place');
      expect(useAppStore.getState().selectedBetType).toBe('place');

      useAppStore.getState().setSelectedBetType('exacta');
      expect(useAppStore.getState().selectedBetType).toBe('exacta');
    });
  });

  describe('actions - setCurrentTip', () => {
    it('should set a tip', () => {
      useAppStore.getState().setCurrentTip(mockTip);
      const state = useAppStore.getState();
      expect(state.currentTip).toEqual(mockTip);
      expect(state.currentTip?.recommended_bet).toBe('Horse A to Win');
    });

    it('should clear tip to null', () => {
      useAppStore.getState().setCurrentTip(mockTip);
      useAppStore.getState().setCurrentTip(null);
      expect(useAppStore.getState().currentTip).toBeNull();
    });
  });

  describe('actions - setPreferences', () => {
    it('should set user preferences', () => {
      useAppStore.getState().setPreferences(mockPreferences);
      const state = useAppStore.getState();
      expect(state.preferences).toEqual(mockPreferences);
      expect(state.preferences?.default_bet_type).toBe('win');
      expect(state.preferences?.favorite_tracks).toContain('Flemington');
    });
  });

  describe('actions - setIsLoading', () => {
    it('should set loading to true', () => {
      useAppStore.getState().setIsLoading(true);
      expect(useAppStore.getState().isLoading).toBe(true);
    });

    it('should set loading to false', () => {
      useAppStore.getState().setIsLoading(true);
      useAppStore.getState().setIsLoading(false);
      expect(useAppStore.getState().isLoading).toBe(false);
    });
  });

  describe('actions - resetTipFlow', () => {
    it('should reset tip flow state while preserving preferences', () => {
      // Set various states
      useAppStore.getState().setSelectedRace(mockRace);
      useAppStore.getState().setSelectedBetType('exacta');
      useAppStore.getState().setCurrentTip(mockTip);
      useAppStore.getState().setPreferences(mockPreferences);

      // Reset tip flow
      useAppStore.getState().resetTipFlow();

      const state = useAppStore.getState();
      expect(state.selectedRace).toBeNull();
      expect(state.selectedBetType).toBe('best_bet');
      expect(state.currentTip).toBeNull();
      // isLoading and preferences should be unchanged
      expect(state.preferences).toEqual(mockPreferences);
      expect(state.isLoading).toBe(false);
    });
  });

  describe('state transitions', () => {
    it('should handle a complete tip generation flow', () => {
      // Step 1: User selects a race
      useAppStore.getState().setSelectedRace(mockRace);
      expect(useAppStore.getState().selectedRace?.id).toBe('race-1');

      // Step 2: User selects bet type
      useAppStore.getState().setSelectedBetType('win');
      expect(useAppStore.getState().selectedBetType).toBe('win');

      // Step 3: Loading state
      useAppStore.getState().setIsLoading(true);
      expect(useAppStore.getState().isLoading).toBe(true);

      // Step 4: Tip is generated
      useAppStore.getState().setCurrentTip(mockTip);
      expect(useAppStore.getState().currentTip?.confidence).toBe('high');

      // Step 5: Loading finished
      useAppStore.getState().setIsLoading(false);
      expect(useAppStore.getState().isLoading).toBe(false);

      // Verify full state
      const finalState = useAppStore.getState();
      expect(finalState.selectedRace).toBeTruthy();
      expect(finalState.currentTip).toBeTruthy();
      expect(finalState.isLoading).toBe(false);
    });

    it('should be independent of race and tip state', () => {
      useAppStore.getState().setSelectedRace(mockRace);
      useAppStore.getState().setCurrentTip(mockTip);
      useAppStore.getState().setSelectedBetType('place');

      // Change race without affecting tip
      const anotherRace = { ...mockRace, id: 'race-2', track: 'Randwick' };
      useAppStore.getState().setSelectedRace(anotherRace);

      const state = useAppStore.getState();
      expect(state.selectedRace?.track).toBe('Randwick');
      expect(state.currentTip?.id).toBe('tip-1');
      expect(state.selectedBetType).toBe('place');
    });
  });
});
