// Pure payload builder extracted from `project-edit-form.tsx` handleSave (R-05).
// The shape of this object IS the API contract with the `projects` table; any
// drift silently breaks persisted data. Characterized by
// __tests__/project-edit-form-payload.test.ts so column additions/removals
// can no longer slip through a visual diff.
// tdd-guard:skip — test lives at __tests__/project-edit-form-payload.test.ts (repo-root __tests__, not sibling)

import type { ComboboxValue } from '@/lib/master-data/types'

export interface ProjectEditFormState {
  status_id: string
  responsibility_id: string
  project_lead_id: string
  collaborator_ids: string[]
  supplier_id: string
  delivery_scope: string
  vehicle_project: string
  product_line: string
  kpi_board_de: string
  kpi_board_international: string
  customer_satisfaction_email: string
  customer_satisfaction_language: string
  project_folder_link: string
  billing_possible: '' | 'Ja' | 'Nein'
  billing_denial_reason: string
  billing_denial_other: string
  planned_amount: string
  estimated_savings_eur: string
  actual_savings_eur: string
  order_reason: string
  order_objective: string
  invest_sharepoint_id: string
  is_mo2_plt_lead: '' | 'Ja' | 'Nein'
  plt_complexity: string
  order_received_date: string
  expected_end_date: string
  visit_date: string
  // F-002/F-003 (KAR-632)
  department_id: string
  reporting_relevant: boolean
  // KAR-790 (R42): release flag — gated to admin/lead by the DB guard
  is_released: boolean
}

export interface BuildProjectUpdateInput {
  form: ProjectEditFormState
  selectedTypeIds: string[]
  selectedSupplierName: string | null
  fallbackSupplierName: string
  kifag: ComboboxValue
  qmt: ComboboxValue
  einkauf: ComboboxValue
  costEng: ComboboxValue
  erstbesuchStart: string
  erstbesuchEnd: string
  erstbesuchCalendarCreated: boolean
  erstbesuchDatesChanged: boolean
  folgetermine: Array<{ start: string; end: string; calendar_created: boolean }>
}

export interface ProjectUpdatePayload {
  responsibility_id: string | null
  project_lead_id: string | null
  supplier_id: string | null
  supplier_name: string
  status_id: string | null
  order_received_date: string | null
  expected_end_date: string | null
  visit_date: string
  vehicle_project: string | null
  product_line: string | null
  delivery_scope: string | null
  kpi_board_de: string | null
  kpi_board_international: string | null
  kifag_area_id: string | null
  qmt_value_id: string | null
  qmt_free_text: string | null
  einkauf_value_id: string | null
  einkauf_free_text: string | null
  cost_engineering_value_id: string | null
  cost_engineering_free_text: string | null
  customer_satisfaction_email: string | null
  customer_satisfaction_language: string | null
  project_folder_link: string | null
  billing_possible: string | null
  billing_denial_reason: string | null
  billing_denial_other: string | null
  planned_amount: string | null
  estimated_savings_eur: number | null
  actual_savings_eur: number | null
  order_reason: string | null
  order_objective: string | null
  invest_sharepoint_id: string | null
  is_mo2_plt_lead: string | null
  plt_complexity: string | null
  erstbesuch_start: string | null
  erstbesuch_end: string | null
  erstbesuch_calendar_created: boolean
  folgetermine: Array<{ start: string; end: string; calendar_created: boolean }>
  // F-002/F-003 (KAR-632)
  department_id: string | null
  reporting_relevant: boolean
  is_released: boolean
}

const nullIfEmpty = (s: string): string | null => (s ? s : null)

export function buildProjectUpdatePayload(
  input: BuildProjectUpdateInput,
): ProjectUpdatePayload {
  const {
    form,
    selectedTypeIds,
    selectedSupplierName,
    fallbackSupplierName,
    kifag,
    qmt,
    einkauf,
    costEng,
    erstbesuchStart,
    erstbesuchEnd,
    erstbesuchCalendarCreated,
    erstbesuchDatesChanged,
    folgetermine,
  } = input

  // project_type_id intentionally omitted — Junction (project_type_assignments)
  // is the single source of truth since Phase 2b3-iii.
  void selectedTypeIds
  return {
    responsibility_id: nullIfEmpty(form.responsibility_id),
    project_lead_id: nullIfEmpty(form.project_lead_id),
    supplier_id: nullIfEmpty(form.supplier_id),
    supplier_name: selectedSupplierName ?? fallbackSupplierName,
    status_id: nullIfEmpty(form.status_id),
    order_received_date: nullIfEmpty(form.order_received_date),
    expected_end_date: nullIfEmpty(form.expected_end_date),
    visit_date: form.visit_date,
    vehicle_project: nullIfEmpty(form.vehicle_project),
    product_line: nullIfEmpty(form.product_line),
    delivery_scope: nullIfEmpty(form.delivery_scope),
    kpi_board_de: nullIfEmpty(form.kpi_board_de),
    kpi_board_international: nullIfEmpty(form.kpi_board_international),
    kifag_area_id: kifag.valueId || null,
    qmt_value_id: qmt.valueId || null,
    qmt_free_text: qmt.freeText || null,
    einkauf_value_id: einkauf.valueId || null,
    einkauf_free_text: einkauf.freeText || null,
    cost_engineering_value_id: costEng.valueId || null,
    cost_engineering_free_text: costEng.freeText || null,
    customer_satisfaction_email: nullIfEmpty(form.customer_satisfaction_email),
    customer_satisfaction_language: nullIfEmpty(form.customer_satisfaction_language),
    project_folder_link: nullIfEmpty(form.project_folder_link),
    billing_possible: nullIfEmpty(form.billing_possible),
    billing_denial_reason: nullIfEmpty(form.billing_denial_reason),
    billing_denial_other: nullIfEmpty(form.billing_denial_other),
    planned_amount: nullIfEmpty(form.planned_amount),
    estimated_savings_eur:
      form.estimated_savings_eur !== '' ? parseFloat(form.estimated_savings_eur) : null,
    actual_savings_eur:
      form.actual_savings_eur !== '' ? parseFloat(form.actual_savings_eur) : null,
    order_reason: nullIfEmpty(form.order_reason),
    order_objective: nullIfEmpty(form.order_objective),
    invest_sharepoint_id: nullIfEmpty(form.invest_sharepoint_id),
    is_mo2_plt_lead: nullIfEmpty(form.is_mo2_plt_lead),
    plt_complexity: nullIfEmpty(form.plt_complexity),
    erstbesuch_start: erstbesuchStart || null,
    erstbesuch_end: erstbesuchEnd || null,
    erstbesuch_calendar_created: erstbesuchDatesChanged
      ? false
      : erstbesuchCalendarCreated,
    folgetermine: folgetermine.map((f) => ({
      start: f.start,
      end: f.end,
      calendar_created: f.calendar_created,
    })),
    // F-002/F-003 (KAR-632)
    department_id: nullIfEmpty(form.department_id),
    reporting_relevant: form.reporting_relevant,
    is_released: form.is_released,
  }
}

export interface BuildConsultantEntriesInput {
  projectId: string
  projectLeadId: string
  collaboratorIds: string[]
}

export interface ConsultantEntry {
  project_id: string
  consultant_id: string
  role_in_project: 'lead' | 'collaborator'
}

export function buildConsultantEntries(
  input: BuildConsultantEntriesInput,
): ConsultantEntry[] {
  const { projectId, projectLeadId, collaboratorIds } = input
  const entries: ConsultantEntry[] = []
  if (projectLeadId) {
    entries.push({
      project_id: projectId,
      consultant_id: projectLeadId,
      role_in_project: 'lead',
    })
  }
  for (const cid of collaboratorIds) {
    if (cid && cid !== projectLeadId) {
      entries.push({
        project_id: projectId,
        consultant_id: cid,
        role_in_project: 'collaborator',
      })
    }
  }
  return entries
}

export interface BuildTypeAssignmentRowsInput {
  projectId: string
  selectedTypeIds: string[]
  projectTypes: Array<{ id: string; code: string }>
}

export interface TypeAssignmentRow {
  project_id: string
  project_type_code: string
}

export function buildTypeAssignmentRows(
  input: BuildTypeAssignmentRowsInput,
): TypeAssignmentRow[] {
  const { projectId, selectedTypeIds, projectTypes } = input
  return selectedTypeIds
    .map((id) => ({
      project_id: projectId,
      project_type_code: projectTypes.find((t) => t.id === id)?.code ?? '',
    }))
    .filter((r) => r.project_type_code)
}
