import { describe, it, expect } from 'vitest'
import {
  buildProjectUpdatePayload,
  buildConsultantEntries,
  buildTypeAssignmentRows,
  type ProjectEditFormState,
  type BuildProjectUpdateInput,
} from '@/components/project/project-edit-form.payload'

const BASE_FORM: ProjectEditFormState = {
  status_id: 'status-1',
  responsibility_id: 'resp-1',
  project_lead_id: 'lead-1',
  collaborator_ids: ['co-1', 'co-2'],
  supplier_id: 'sup-1',
  delivery_scope: 'a scope',
  vehicle_project: 'G-05',
  product_line: 'PL-A',
  kpi_board_de: 'Board DE',
  kpi_board_international: 'Board Int',
  customer_satisfaction_email: 'a@b.c',
  customer_satisfaction_language: 'DE',
  project_folder_link: 'https://example/folder',
  billing_possible: 'Ja',
  billing_denial_reason: '',
  billing_denial_other: '',
  planned_amount: '1000',
  estimated_savings_eur: '500',
  actual_savings_eur: '',
  order_reason: 'reason',
  order_objective: 'objective',
  invest_sharepoint_id: 'INV-1',
  is_mo2_plt_lead: '',
  plt_complexity: '',
  order_received_date: '2025-01-01',
  expected_end_date: '2025-06-30',
  visit_date: '2025-03-15',
  // F-002/F-003 (KAR-632)
  department_id: 'dept-1',
  reporting_relevant: true,
  is_released: false,
}

const BASE_INPUT: BuildProjectUpdateInput = {
  form: BASE_FORM,
  selectedTypeIds: ['type-1', 'type-2'],
  selectedSupplierName: 'Acme',
  fallbackSupplierName: 'Fallback Supplier',
  kifag: { valueId: 'k-1', freeText: null },
  qmt: { valueId: 'q-1', freeText: 'qmt-free' },
  einkauf: { valueId: null, freeText: 'einkauf-free' },
  costEng: { valueId: null, freeText: null },
  erstbesuchStart: '2025-03-10',
  erstbesuchEnd: '2025-03-14',
  erstbesuchCalendarCreated: true,
  erstbesuchDatesChanged: false,
  folgetermine: [{ start: '2025-04-01', end: '2025-04-03', calendar_created: false }],
}

describe('buildProjectUpdatePayload', () => {
  it('serializes all baseline fields with selected supplier and parsed savings', () => {
    const p = buildProjectUpdatePayload(BASE_INPUT)
    // project_type_id removed in Phase 2b3-iii — Junction is source of truth.
    expect('project_type_id' in p).toBe(false)
    expect(p.supplier_name).toBe('Acme')
    expect(p.supplier_id).toBe('sup-1')
    expect(p.estimated_savings_eur).toBe(500)
    expect(p.actual_savings_eur).toBeNull()
    expect(p.visit_date).toBe('2025-03-15')
    expect(p.erstbesuch_start).toBe('2025-03-10')
    expect(p.erstbesuch_end).toBe('2025-03-14')
    expect(p.erstbesuch_calendar_created).toBe(true)
    expect(p.folgetermine).toEqual([
      { start: '2025-04-01', end: '2025-04-03', calendar_created: false },
    ])
  })

  it('resets erstbesuch_calendar_created to false when dates changed', () => {
    const p = buildProjectUpdatePayload({ ...BASE_INPUT, erstbesuchDatesChanged: true })
    expect(p.erstbesuch_calendar_created).toBe(false)
  })

  it('falls back to fallbackSupplierName when no supplier selected', () => {
    const p = buildProjectUpdatePayload({ ...BASE_INPUT, selectedSupplierName: null })
    expect(p.supplier_name).toBe('Fallback Supplier')
  })

  it('maps empty strings to null on every nullable text field', () => {
    const blank: ProjectEditFormState = {
      ...BASE_FORM,
      status_id: '',
      responsibility_id: '',
      project_lead_id: '',
      supplier_id: '',
      delivery_scope: '',
      vehicle_project: '',
      product_line: '',
      kpi_board_de: '',
      kpi_board_international: '',
      customer_satisfaction_email: '',
      customer_satisfaction_language: '',
      project_folder_link: '',
      billing_possible: '',
      billing_denial_reason: '',
      billing_denial_other: '',
      planned_amount: '',
      estimated_savings_eur: '',
      actual_savings_eur: '',
      order_reason: '',
      order_objective: '',
      invest_sharepoint_id: '',
      is_mo2_plt_lead: '',
      plt_complexity: '',
      order_received_date: '',
      expected_end_date: '',
      department_id: '',
      reporting_relevant: true,
      is_released: false,
    }
    const p = buildProjectUpdatePayload({ ...BASE_INPUT, form: blank })
    expect(p.status_id).toBeNull()
    expect(p.responsibility_id).toBeNull()
    expect(p.project_lead_id).toBeNull()
    expect(p.supplier_id).toBeNull()
    expect(p.vehicle_project).toBeNull()
    expect(p.planned_amount).toBeNull()
    expect(p.estimated_savings_eur).toBeNull()
    expect(p.actual_savings_eur).toBeNull()
    expect(p.order_received_date).toBeNull()
    expect(p.expected_end_date).toBeNull()
  })

  it('preserves combobox valueId + freeText independently', () => {
    const p = buildProjectUpdatePayload(BASE_INPUT)
    expect(p.kifag_area_id).toBe('k-1')
    expect(p.qmt_value_id).toBe('q-1')
    expect(p.qmt_free_text).toBe('qmt-free')
    expect(p.einkauf_value_id).toBeNull()
    expect(p.einkauf_free_text).toBe('einkauf-free')
    expect(p.cost_engineering_value_id).toBeNull()
    expect(p.cost_engineering_free_text).toBeNull()
  })

  it('omits project_type_id from update payload regardless of selection (Junction is source of truth)', () => {
    const p = buildProjectUpdatePayload({ ...BASE_INPUT, selectedTypeIds: [] })
    expect('project_type_id' in p).toBe(false)
  })

  it('nulls erstbesuch dates when empty', () => {
    const p = buildProjectUpdatePayload({
      ...BASE_INPUT,
      erstbesuchStart: '',
      erstbesuchEnd: '',
    })
    expect(p.erstbesuch_start).toBeNull()
    expect(p.erstbesuch_end).toBeNull()
  })

  // F-002/F-003 (KAR-632)
  it('includes department_id and reporting_relevant in update payload', () => {
    const p = buildProjectUpdatePayload(BASE_INPUT)
    expect(p.department_id).toBe('dept-1')
    expect(p.reporting_relevant).toBe(true)
  })

  it('maps empty department_id to null', () => {
    const p = buildProjectUpdatePayload({
      ...BASE_INPUT,
      form: { ...BASE_FORM, department_id: '' },
    })
    expect(p.department_id).toBeNull()
  })

  it('preserves reporting_relevant = false', () => {
    const p = buildProjectUpdatePayload({
      ...BASE_INPUT,
      form: { ...BASE_FORM, reporting_relevant: false },
    })
    expect(p.reporting_relevant).toBe(false)
  })

  // KAR-790 (R42)
  it('passes is_released through the update payload', () => {
    expect(buildProjectUpdatePayload(BASE_INPUT).is_released).toBe(false)
    const released = buildProjectUpdatePayload({
      ...BASE_INPUT,
      form: { ...BASE_FORM, is_released: true },
    })
    expect(released.is_released).toBe(true)
  })
})

describe('buildConsultantEntries', () => {
  it('places the lead first with role=lead', () => {
    const rows = buildConsultantEntries({
      projectId: 'p-1',
      projectLeadId: 'lead-1',
      collaboratorIds: ['co-1'],
    })
    expect(rows[0]).toEqual({ project_id: 'p-1', consultant_id: 'lead-1', role_in_project: 'lead' })
    expect(rows[1]).toEqual({ project_id: 'p-1', consultant_id: 'co-1', role_in_project: 'collaborator' })
  })

  it('dedupes when lead is also in collaborator list', () => {
    const rows = buildConsultantEntries({
      projectId: 'p-1',
      projectLeadId: 'lead-1',
      collaboratorIds: ['lead-1', 'co-2'],
    })
    expect(rows).toEqual([
      { project_id: 'p-1', consultant_id: 'lead-1', role_in_project: 'lead' },
      { project_id: 'p-1', consultant_id: 'co-2', role_in_project: 'collaborator' },
    ])
  })

  it('omits lead row when lead id is empty', () => {
    const rows = buildConsultantEntries({
      projectId: 'p-1',
      projectLeadId: '',
      collaboratorIds: ['co-1'],
    })
    expect(rows).toEqual([
      { project_id: 'p-1', consultant_id: 'co-1', role_in_project: 'collaborator' },
    ])
  })

  it('returns empty when no lead and no collaborators', () => {
    expect(
      buildConsultantEntries({ projectId: 'p-1', projectLeadId: '', collaboratorIds: [] }),
    ).toEqual([])
  })
})

describe('buildTypeAssignmentRows', () => {
  const types = [
    { id: 't-1', code: 'fabrikanalyse' },
    { id: 't-2', code: 'kapa_workshop' },
    { id: 't-3', code: '' },
  ]

  it('maps selected ids to their codes', () => {
    const rows = buildTypeAssignmentRows({
      projectId: 'p-1',
      selectedTypeIds: ['t-1', 't-2'],
      projectTypes: types,
    })
    expect(rows).toEqual([
      { project_id: 'p-1', project_type_code: 'fabrikanalyse' },
      { project_id: 'p-1', project_type_code: 'kapa_workshop' },
    ])
  })

  it('drops ids that resolve to an empty code', () => {
    const rows = buildTypeAssignmentRows({
      projectId: 'p-1',
      selectedTypeIds: ['t-3'],
      projectTypes: types,
    })
    expect(rows).toEqual([])
  })

  it('drops unknown ids silently', () => {
    const rows = buildTypeAssignmentRows({
      projectId: 'p-1',
      selectedTypeIds: ['t-1', 'ghost'],
      projectTypes: types,
    })
    expect(rows).toEqual([{ project_id: 'p-1', project_type_code: 'fabrikanalyse' }])
  })
})
