import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { createRouter, createMemoryHistory } from 'vue-router'

// Mock auth store before any imports
vi.mock('../../../stores/auth.js', () => ({
  useAuthStore: vi.fn(),
}))

// Mock api/client to avoid HTTP calls
vi.mock('../../../api/client.js', () => ({
  changePassword: vi.fn(),
  totpDisable: vi.fn(),
}))

// Mock toast store — capture show() calls so we can assert on them
const mockShow = vi.fn()
vi.mock('../../../stores/toast.js', () => ({
  useToastStore: () => ({ show: mockShow }),
}))

import { useAuthStore } from '../../../stores/auth.js'
import { changePassword as changePasswordMock, totpDisable as totpDisableMock } from '../../../api/client.js'
import SettingsAccountTab from '../SettingsAccountTab.vue'

// Minimal router — required because the component calls useRouter() in script setup
const testRouter = createRouter({
  history: createMemoryHistory(),
  routes: [
    { path: '/', component: { template: '<div />' } },
    { path: '/login', component: { template: '<div />' } },
    { path: '/settings', component: { template: '<div />' } },
  ],
})

const globalStubs = {
  TotpEnrollment: { template: '<div data-stub="TotpEnrollment" />' },
  ConfirmBlock: { template: '<div data-stub="ConfirmBlock" />', props: ['message', 'confirmLabel', 'cancelLabel'] },
  PasswordStrengthBar: { template: '<div data-stub="PasswordStrengthBar" />', props: ['password'] },
  AppSpinner: { template: '<span />' },
}

beforeEach(() => {
  setActivePinia(createPinia())
  vi.clearAllMocks()
  mockShow.mockClear()
})

// ─── GAP 1 & 2: Sessions revoked toast (CR-01, CR-03) ──────────────────────

describe('SettingsAccountTab — sessions revoked toast (CR-01, CR-03)', () => {
  // Stub for ConfirmBlock that renders a button triggering @confirmed emission
  const ConfirmBlockEmitter = {
    name: 'ConfirmBlock',
    template: '<div data-stub="ConfirmBlock"><button data-action="confirm" @click="$emit(\'confirmed\')">confirm</button></div>',
    props: ['message', 'confirmLabel', 'cancelLabel'],
    emits: ['confirmed', 'cancelled'],
  }

  it('calls toastStore.show("Other sessions have been terminated.") after changePassword returns sessions_revoked > 0 (CR-01)', async () => {
    useAuthStore.mockReturnValue({
      user: { email: 'test@example.com', handle: 'testuser', role: 'user', totp_enabled: false },
      logoutAll: vi.fn(),
    })

    vi.mocked(changePasswordMock).mockResolvedValueOnce({
      message: 'Password updated',
      sessions_revoked: 2,
    })

    const wrapper = mount(SettingsAccountTab, {
      global: {
        plugins: [createPinia(), testRouter],
        stubs: { ...globalStubs, ConfirmBlock: ConfirmBlockEmitter },
      },
    })

    // Submit the change-password form to invoke changePassword()
    await wrapper.find('form').trigger('submit')
    await flushPromises()

    expect(mockShow).toHaveBeenCalledWith('Other sessions have been terminated.', 'success')
  })

  it('does NOT call toastStore.show after changePassword when sessions_revoked is 0 (CR-01 negative)', async () => {
    useAuthStore.mockReturnValue({
      user: { email: 'test@example.com', handle: 'testuser', role: 'user', totp_enabled: false },
      logoutAll: vi.fn(),
    })

    vi.mocked(changePasswordMock).mockResolvedValueOnce({
      message: 'Password updated',
      sessions_revoked: 0,
    })

    const wrapper = mount(SettingsAccountTab, {
      global: {
        plugins: [createPinia(), testRouter],
        stubs: { ...globalStubs, ConfirmBlock: ConfirmBlockEmitter },
      },
    })

    await wrapper.find('form').trigger('submit')
    await flushPromises()

    expect(mockShow).not.toHaveBeenCalled()
  })

  it('calls toastStore.show("Other sessions have been terminated.") after disableTotp returns sessions_revoked > 0 (CR-03)', async () => {
    const user = { email: 'test@example.com', handle: 'testuser', role: 'user', totp_enabled: true }
    useAuthStore.mockReturnValue({
      user,
      logoutAll: vi.fn(),
    })

    vi.mocked(totpDisableMock).mockResolvedValueOnce({
      message: 'TOTP disabled',
      sessions_revoked: 1,
    })

    const wrapper = mount(SettingsAccountTab, {
      global: {
        plugins: [createPinia(), testRouter],
        stubs: { ...globalStubs, ConfirmBlock: ConfirmBlockEmitter },
      },
    })

    // Click "Disable 2FA" to reveal the ConfirmBlock
    const disableBtn = wrapper.findAll('button').find(b => b.text().includes('Disable 2FA'))
    await disableBtn.trigger('click')

    // Click the confirm button rendered by the ConfirmBlockEmitter stub
    await wrapper.find('[data-action="confirm"]').trigger('click')
    await flushPromises()

    expect(mockShow).toHaveBeenCalledWith('Other sessions have been terminated.', 'success')
  })
})

describe('SettingsAccountTab — four section headings (AUTH-03, AUTH-04)', () => {
  it('renders all 4 required section headings when totp_enabled is false', () => {
    useAuthStore.mockReturnValue({
      user: { email: 'test@example.com', handle: 'testuser', role: 'user', totp_enabled: false },
      logoutAll: vi.fn(),
    })

    const wrapper = mount(SettingsAccountTab, {
      global: {
        plugins: [createPinia(), testRouter],
        stubs: globalStubs,
      },
    })

    const text = wrapper.text()
    expect(text).toContain('Account information')
    expect(text).toContain('Two-factor authentication')
    expect(text).toContain('Change password')
    expect(text).toContain('Sessions')
  })

  it('renders TotpEnrollment stub when totp_enabled is false', () => {
    useAuthStore.mockReturnValue({
      user: { email: 'test@example.com', handle: 'testuser', role: 'user', totp_enabled: false },
      logoutAll: vi.fn(),
    })

    const wrapper = mount(SettingsAccountTab, {
      global: {
        plugins: [createPinia(), testRouter],
        stubs: globalStubs,
      },
    })

    expect(wrapper.find('[data-stub="TotpEnrollment"]').exists()).toBe(true)
  })

  it('shows "Enabled" status and "Disable 2FA" button when totp_enabled is true', () => {
    useAuthStore.mockReturnValue({
      user: { email: 'test@example.com', handle: 'testuser', role: 'user', totp_enabled: true },
      logoutAll: vi.fn(),
    })

    const wrapper = mount(SettingsAccountTab, {
      global: {
        plugins: [createPinia(), testRouter],
        stubs: globalStubs,
      },
    })

    // "Enabled" text must appear (inside the 2FA section)
    expect(wrapper.text()).toContain('Enabled')

    // "Disable 2FA" button must be present
    const buttons = wrapper.findAll('button')
    const disableBtn = buttons.find(b => b.text().includes('Disable 2FA'))
    expect(disableBtn).toBeDefined()
  })

  it('does NOT render TotpEnrollment stub when totp_enabled is true', () => {
    useAuthStore.mockReturnValue({
      user: { email: 'test@example.com', handle: 'testuser', role: 'user', totp_enabled: true },
      logoutAll: vi.fn(),
    })

    const wrapper = mount(SettingsAccountTab, {
      global: {
        plugins: [createPinia(), testRouter],
        stubs: globalStubs,
      },
    })

    expect(wrapper.find('[data-stub="TotpEnrollment"]').exists()).toBe(false)
  })
})
