import { describe, it, expect, beforeEach, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import SimulationControlView from '@/views/SimulationControlView.vue'

const {
  fetchScenarios,
  fetchSessions,
  fetchRuns,
  fetchSimulationConfig,
  fetchDataSummary,
  startRun,
  startSession,
  stopRun,
  purgeData,
} = vi.hoisted(() => ({
  fetchScenarios: vi.fn(),
  fetchSessions: vi.fn(),
  fetchRuns: vi.fn(),
  fetchSimulationConfig: vi.fn(),
  fetchDataSummary: vi.fn(),
  startRun: vi.fn(),
  startSession: vi.fn(),
  stopRun: vi.fn(),
  purgeData: vi.fn(),
}))

vi.mock('@/api/simulation', () => ({
  fetchScenarios,
  fetchSessions,
  fetchRuns,
  fetchSimulationConfig,
  fetchDataSummary,
  startRun,
  startSession,
  stopRun,
  purgeData,
  fetchRun: vi.fn(),
}))

vi.mock('@/stores/ward', () => ({
  useWardStore: () => ({ loadEncounters: vi.fn() }),
}))

vi.mock('@/stores/alerts', () => ({
  useAlertStore: () => ({ loadGlobalAlerts: vi.fn() }),
}))

const scenarios = [
  {
    id: 'uti-sepsis-elderly-01',
    name: 'UTI Sepsis Elderly',
    description: 'Elderly patient with UTI progressing to sepsis.',
    durationMinutes: 480,
    tags: ['sepsis', 'uti'],
    department: 'GeneralMedicine',
    eventCount: 200,
  },
  {
    id: 'stable-baseline-01',
    name: 'Stable Baseline',
    description: 'Control scenario.',
    durationMinutes: 480,
    tags: ['control', 'stable'],
    department: 'Surgery',
    eventCount: 312,
  },
]

const sessions = [
  {
    id: 'session-a-orientation',
    name: 'Session A — Quick orientation',
    goal: 'Learn the interface.',
    estimatedMinutes: 25,
    defaultSpeed: 60,
    scenarios: [
      { id: 'stable-baseline-01', name: 'Stable Baseline' },
      { id: 'uti-sepsis-elderly-01', name: 'UTI Sepsis Elderly' },
    ],
  },
]

describe('SimulationControlView', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    setActivePinia(createPinia())
    fetchScenarios.mockResolvedValue(scenarios)
    fetchSessions.mockResolvedValue(sessions)
    fetchRuns.mockResolvedValue([])
    fetchDataSummary.mockResolvedValue({
      simulatedPatients: 0,
      encounters: 0,
      observations: 0,
      alerts: 0,
      activeRuns: 0,
    })
    fetchSimulationConfig.mockResolvedValue({
      enabled: true,
      maxSpeed: 600,
      maxConcurrentRuns: 2,
    })
  })

  it('defaultsToSessionsTab', async () => {
    const wrapper = mount(SimulationControlView)
    await vi.waitFor(() => expect(wrapper.text()).toContain('Session A — Quick orientation'))
    expect(wrapper.text()).toContain('Testing sessions')
    expect(wrapper.text()).not.toContain('Scenario catalogue')
  })

  it('switchesToScenariosTab', async () => {
    const wrapper = mount(SimulationControlView)
    await vi.waitFor(() => expect(wrapper.text()).toContain('Session A'))

    const scenariosTab = wrapper.findAll('button').find(b => b.text() === 'Scenarios')
    await scenariosTab.trigger('click')

    await vi.waitFor(() => expect(wrapper.text()).toContain('Scenario catalogue'))
    expect(wrapper.text()).toContain('UTI Sepsis Elderly')
  })

  it('showsWallClockDurationForSelectedScenarioSpeed', async () => {
    const wrapper = mount(SimulationControlView)
    await vi.waitFor(() => expect(wrapper.text()).toContain('Session A'))

    const scenariosTab = wrapper.findAll('button').find(b => b.text() === 'Scenarios')
    await scenariosTab.trigger('click')
    await vi.waitFor(() => expect(wrapper.text()).toContain('UTI Sepsis Elderly'))

    // Default Fast (60×): 480 sim minutes → 8 wall-clock minutes
    expect(wrapper.text()).toMatch(/8 minutes for selected scenario/)

    const realTime = wrapper.findAll('button').find(b => b.text().includes('Real time'))
    expect(realTime.text()).toMatch(/8 hours for selected scenario/)

    const instant = wrapper.findAll('button').find(b => b.text().includes('Instant'))
    expect(instant.text()).toMatch(/1 minute for selected scenario/)
  })

  it('filtersCatalogueByTag', async () => {
    const wrapper = mount(SimulationControlView)
    await vi.waitFor(() => expect(wrapper.text()).toContain('Session A'))

    const scenariosTab = wrapper.findAll('button').find(b => b.text() === 'Scenarios')
    await scenariosTab.trigger('click')
    await vi.waitFor(() => expect(wrapper.text()).toContain('Stable Baseline'))

    const sepsisChip = wrapper.findAll('button').find(b => b.text() === 'sepsis')
    await sepsisChip.trigger('click')

    expect(wrapper.text()).toContain('UTI Sepsis Elderly')
    expect(wrapper.text()).not.toContain('Stable Baseline')
  })

  it('showsEmptyStateWhenCatalogueMissing', async () => {
    fetchScenarios.mockResolvedValue([])
    const wrapper = mount(SimulationControlView)
    await vi.waitFor(() => expect(wrapper.text()).toContain('Session A'))

    const scenariosTab = wrapper.findAll('button').find(b => b.text() === 'Scenarios')
    await scenariosTab.trigger('click')

    await vi.waitFor(() =>
      expect(wrapper.text()).toContain('Simulation:ScenarioDirectory'),
    )
  })
})
