// Pure form-level validation for the OEE Kalkulator.
// No React, no side effects — safe to import from any context.

import type { FormState } from '@/components/oee/oee-form-constants'

export interface OeeValidationError {
  field: keyof FormState
  reason: 'missing' | 'implausible'
}

/**
 * Validates an OEE form and returns a list of errors.
 * Empty array → form is valid and ready for finalisation.
 *
 * Pflichtfelder:
 *   - plantName  (Werk)
 *   - lineName   (Linie / Anlage)
 *   - Active cycle-time field: idealCycleTimeSec when taktMode==='ideal',
 *     otherwise optimumTaktTimeSec
 *   - producedOutput
 *   - goodOutput
 *
 * Numeric defaults (calendarWeek/year/daysPerWeek/hoursPerDay/shiftsPerDay)
 * carry non-zero defaults but are still plausibility-checked (> 0).
 *
 * Plausibility rules:
 *   - producedOutput > 0
 *   - goodOutput <= producedOutput
 *   - active cycle time > 0
 *   - numeric outputs >= 0
 *   - daysPerWeek, hoursPerDay, shiftsPerDay > 0
 */
export function validateOeeForm(form: FormState): OeeValidationError[] {
  const errors: OeeValidationError[] = []

  // ── Required text fields ─────────────────────────────────────────────────
  if (!form.plantName || form.plantName.trim() === '') {
    errors.push({ field: 'plantName', reason: 'missing' })
  }

  if (!form.lineName || form.lineName.trim() === '') {
    errors.push({ field: 'lineName', reason: 'missing' })
  }

  // ── Active cycle-time field ───────────────────────────────────────────────
  const activeCycleField: keyof FormState =
    form.taktMode === 'ideal' ? 'idealCycleTimeSec' : 'optimumTaktTimeSec'
  const activeCycleValue =
    form.taktMode === 'ideal' ? form.idealCycleTimeSec : form.optimumTaktTimeSec

  if (!activeCycleValue || activeCycleValue.trim() === '') {
    errors.push({ field: activeCycleField, reason: 'missing' })
  } else {
    const cycleNum = Number(activeCycleValue)
    if (!Number.isFinite(cycleNum) || cycleNum <= 0) {
      errors.push({ field: activeCycleField, reason: 'implausible' })
    }
  }

  // ── producedOutput ────────────────────────────────────────────────────────
  if (form.producedOutput === '' || form.producedOutput === null) {
    errors.push({ field: 'producedOutput', reason: 'missing' })
  } else {
    const produced = Number(form.producedOutput)
    if (!Number.isFinite(produced) || produced <= 0) {
      errors.push({ field: 'producedOutput', reason: 'implausible' })
    }
  }

  // ── goodOutput ────────────────────────────────────────────────────────────
  if (form.goodOutput === '' || form.goodOutput === null) {
    errors.push({ field: 'goodOutput', reason: 'missing' })
  } else {
    const good = Number(form.goodOutput)
    if (!Number.isFinite(good) || good < 0) {
      errors.push({ field: 'goodOutput', reason: 'implausible' })
    } else {
      // Cross-field: goodOutput <= producedOutput
      const produced = Number(form.producedOutput)
      if (Number.isFinite(produced) && good > produced) {
        errors.push({ field: 'goodOutput', reason: 'implausible' })
      }
    }
  }

  // ── Numeric defaults — plausibility only (they always have values) ────────
  if (!Number.isFinite(form.daysPerWeek) || form.daysPerWeek <= 0) {
    errors.push({ field: 'daysPerWeek', reason: 'implausible' })
  }
  if (!Number.isFinite(form.hoursPerDay) || form.hoursPerDay <= 0) {
    errors.push({ field: 'hoursPerDay', reason: 'implausible' })
  }
  if (!Number.isFinite(form.shiftsPerDay) || form.shiftsPerDay <= 0) {
    errors.push({ field: 'shiftsPerDay', reason: 'implausible' })
  }

  return errors
}

/**
 * Returns a human-readable German summary of errors for the finalise banner.
 * Only includes fields visible to the user, deduplicated.
 */
export function formatValidationErrors(errors: OeeValidationError[]): string {
  const fieldLabels: Partial<Record<keyof FormState, string>> = {
    plantName: 'Werk',
    lineName: 'Linie / Anlage',
    idealCycleTimeSec: 'Ideale Zykluszeit',
    optimumTaktTimeSec: 'Optimale Taktzeit',
    producedOutput: 'Produzierte Menge',
    goodOutput: 'Gutmenge',
    daysPerWeek: 'Arbeitstage',
    hoursPerDay: 'Std./Tag',
    shiftsPerDay: 'Schichten',
  }

  // goodOutput implausible = cross-field error; gets dedicated wording
  const goodImplausible = errors.find(
    e => e.field === 'goodOutput' && e.reason === 'implausible',
  )
  const parts: string[] = []

  for (const err of errors) {
    if (err.field === 'goodOutput' && err.reason === 'implausible') continue
    const label = fieldLabels[err.field]
    if (label) parts.push(label)
  }

  const messages: string[] = []
  if (parts.length > 0) {
    messages.push(`Fehlend oder ungültig: ${parts.join(', ')}`)
  }
  if (goodImplausible) {
    messages.push('Gutmenge ≤ Produzierte Menge erforderlich')
  }

  return messages.join(' · ')
}
