// @vitest-environment jsdom
//
// FB-36 (P0 compliance, composition profile — ADR 013): the work_mode
// ("Arbeitsort") capture UI must be hideable via the `workModeCapture`
// profile flag. Before this flag existed the radio group always rendered
// unconditionally, so "hidden when false" below is a genuine regression
// test — against the pre-flag component it fails (3 radios would be found,
// not 0).
//
// FIXTURE-DATEN-REGEL: every id/name below is FREE INVENTION.

import { afterEach, describe, expect, it, vi } from 'vitest'
import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import CreateAssignmentModal from '@/components/planning/create-assignment-modal'
import type { Consultant, AppointmentType, PlanningProject } from '@/lib/planning-types'

// FB-36 (P0 compliance, composition profile — ADR 013): recorded `insert()`
// calls for the payload-level test below. Cleared via vi.clearAllMocks() in
// afterEach, same as every other mock in this file.
const insertMock = vi.fn().mockResolvedValue({ error: null })

// CreateAssignmentModal fetches `projects` for the project dropdown on mount
// (`.from('projects').select(...).order(...).then(cb)`) — stub just that
// chain shape so the effect resolves to an empty list instead of throwing
// (createBrowserClient throws without real Supabase env vars, which are not
// set in the test environment). Because `mainProjects` therefore stays
// empty, handleSubmit's `mainProjects.find(...)` always misses and the
// `planning_projects` upsert branch is never hit — no need to mock it.
vi.mock('@/lib/supabase/client', () => {
  interface FakeChain {
    select: () => FakeChain
    order: () => Promise<{ data: unknown[]; error: null }>
  }
  function makeProjectsChain(): FakeChain {
    const chain: FakeChain = {
      select: () => chain,
      order: () => Promise.resolve({ data: [], error: null }),
    }
    return chain
  }
  return {
    createClient: () => ({
      auth: {
        getUser: () =>
          Promise.resolve({ data: { user: { id: '99999999-9999-9999-9999-999999999999' } } }),
      },
      from: (table: string) =>
        table === 'assignments' ? { insert: (rows: unknown) => insertMock(rows) } : makeProjectsChain(),
    }),
  }
})

afterEach(() => {
  cleanup()
  vi.clearAllMocks()
})

const consultants: Consultant[] = [
  {
    id: '11111111-1111-1111-1111-111111111111',
    auth_user_id: null,
    first_name: 'Erika',
    last_name: 'Musterfrau',
    display_name: 'Erika Musterfrau',
    team_code: 'T1',
    role: 'consultant',
    is_active: true,
    capacity_hours_per_day: 8,
    created_at: '2026-01-01T00:00:00Z',
  },
]

const appointmentTypes: AppointmentType[] = [
  { id: '22222222-2222-2222-2222-222222222222', code: 'visit', label: 'Besuch', color: '#037493', sort_order: 1 },
]

const planningProjects: PlanningProject[] = [
  {
    id: '33333333-3333-3333-3333-333333333333',
    code: 'P-1',
    name: 'Projekt Eins',
    supplier_id: null,
    location_label: null,
    country: null,
    is_active: true,
    created_at: '2026-01-01T00:00:00Z',
  },
]

async function renderModal(workModeCapture: boolean) {
  const result = render(
    <CreateAssignmentModal
      consultantId={consultants[0].id}
      date="2026-07-01"
      consultants={consultants}
      appointmentTypes={appointmentTypes}
      planningProjects={planningProjects}
      existingAssignments={[]}
      onClose={() => {}}
      onCreated={() => {}}
      workModeCapture={workModeCapture}
    />,
  )
  // Flush the mounted projects-fetch effect (real Promise from the mock
  // above) so its state update settles inside `act`.
  await act(async () => {})
  return result
}

describe('CreateAssignmentModal — workModeCapture flag (FB-36)', () => {
  it('hides the Arbeitsort radio group when the flag is false', async () => {
    await renderModal(false)
    expect(screen.queryByText('Arbeitsort *')).toBeNull()
    expect(screen.queryAllByRole('radio')).toHaveLength(0)
  })

  it('shows the Arbeitsort radio group when the flag is true', async () => {
    await renderModal(true)
    expect(screen.getByText('Arbeitsort *')).toBeTruthy()
    expect(screen.getAllByRole('radio')).toHaveLength(3)
  })
})

// FB-36 payload-level regression: the DOM-visibility tests above only prove
// the radio group is hidden, not that the write itself is gated. Before the
// `...(workModeCapture ? { work_mode: workMode } : {})` conditional spread
// in create-assignment-modal.tsx, `work_mode` was written unconditionally —
// the first test below fails against that version (work_mode present).
describe('CreateAssignmentModal — insert payload (FB-36)', () => {
  async function fillRequiredFieldsAndSubmit() {
    // Project is the one required field without a prop-supplied default
    // (see renderModal: consultant/type/dates all default to valid values).
    // mainProjects (server fetch) is mocked empty, so the dropdown falls
    // back to rendering the `planningProjects` prop's options.
    const projectSelect = screen.getByDisplayValue('— Projekt wählen —')
    fireEvent.change(projectSelect, { target: { value: planningProjects[0].id } })

    const submitButton = screen.getByRole('button', { name: /Einsatz speichern/ })
    fireEvent.click(submitButton)
    await waitFor(() => expect(insertMock).toHaveBeenCalledTimes(1))
  }

  it('omits work_mode from the insert payload when the flag is false', async () => {
    await renderModal(false)
    await fillRequiredFieldsAndSubmit()
    const rows = insertMock.mock.calls[0][0] as Record<string, unknown>[]
    expect(rows).toHaveLength(1)
    expect('work_mode' in rows[0]).toBe(false)
  })

  it('includes work_mode in the insert payload when the flag is true', async () => {
    await renderModal(true)
    await fillRequiredFieldsAndSubmit()
    const rows = insertMock.mock.calls[0][0] as Record<string, unknown>[]
    // Default `workMode` state in the component is 'onsite'.
    expect(rows[0].work_mode).toBe('onsite')
  })
})
