import type { Agenda, AgendaProjectContext, AgendaLanguage, AgendaItemType } from './types'
import { columnLabels, label, type ColumnLabels } from './i18n'
import type { HostOrg } from './host'
import { resolveItemColor } from './colors'

/**
 * Pure, render-agnostic export model.
 *
 * Both the PDF and the Excel exporter consume this normalised structure, so all
 * the formatting + localisation logic lives here (and is unit-tested) while the
 * exporters only deal with their library specifics (layout, logos, page setup).
 */

export interface ExportParticipant {
  name: string
  company: string
  department: string
  position: string
  role: string
  email: string
  comment: string
}

export interface ExportRow {
  time: string
  subject: string
  duration: string
  responsible: string
  participants: string
  info: string
  itemType: AgendaItemType
  /** Resolved row colour (custom override or item-type default), as hex. */
  color: string
}

export interface ExportDay {
  heading: string
  dateLabel: string
  isTravelDay: boolean
  rows: ExportRow[]
}

export interface AgendaExportModel {
  title: string
  language: AgendaLanguage
  columns: ColumnLabels
  labels: {
    participants: string
    hostParticipants: string
    supplierParticipants: string
    objective: string
    supplier: string
    location: string
    date: string
  }
  projectCode: string | null
  supplierName: string
  location: string
  dateRangeLabel: string
  objective: string
  hostParticipants: ExportParticipant[]
  supplierParticipants: ExportParticipant[]
  days: ExportDay[]
}

function transliterate(value: string): string {
  return value
    .replace(/ä/g, 'ae')
    .replace(/ö/g, 'oe')
    .replace(/ü/g, 'ue')
    .replace(/Ä/g, 'Ae')
    .replace(/Ö/g, 'Oe')
    .replace(/Ü/g, 'Ue')
    .replace(/ß/g, 'ss')
}

function sanitizeFilenamePart(value: string): string {
  return transliterate(value)
    .normalize('NFD')
    .replace(/[̀-ͯ]/g, '')
    .replace(/[^a-zA-Z0-9]+/g, '_')
    .replace(/^_+|_+$/g, '')
}

/** Localised date string. `de`/`es` → DD.MM.YYYY, `en` → MM/DD/YYYY, `zh` → YYYY-MM-DD. */
export function formatExportDate(date: string | null, lang: AgendaLanguage): string {
  if (!date) return ''
  const match = date.trim().match(/^(\d{4})-(\d{2})-(\d{2})$/)
  if (!match) return date
  const [, year, month, day] = match
  switch (lang) {
    case 'en':
      return `${month}/${day}/${year}`
    case 'zh':
      return `${year}-${month}-${day}`
    case 'es':
    case 'de':
    default:
      return `${day}.${month}.${year}`
  }
}

function compactDate(date: string | null): string {
  if (!date) {
    const now = new Date()
    return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, '0')}${String(now.getUTCDate()).padStart(2, '0')}`
  }
  return date.replace(/-/g, '')
}

/** `Agenda_[Supplier]_[Location]_[YYYYMMDD].<ext>` */
export function buildExportFilename(
  ctx: AgendaProjectContext,
  agenda: Agenda,
  ext: 'pdf' | 'xlsx',
): string {
  const parts = ['Agenda', sanitizeFilenamePart(ctx.supplierName || 'Supplier')]
  const location = ctx.plantLocation ? sanitizeFilenamePart(ctx.plantLocation) : ''
  if (location) parts.push(location)
  parts.push(compactDate(agenda.start_date))
  return `${parts.filter(Boolean).join('_')}.${ext}`
}

function toParticipant(p: Agenda['participants'][number]): ExportParticipant {
  return {
    name: p.name,
    company: p.company ?? '',
    department: p.department ?? '',
    position: p.position ?? '',
    role: p.role ?? '',
    email: p.email ?? '',
    comment: p.comment ?? '',
  }
}

function formatDuration(minutes: number): string {
  return `${Math.max(0, minutes)} min`
}

function formatTimeSpan(start: string | null, end: string | null): string {
  if (start && end) return `${start} – ${end}`
  if (start) return start
  return ''
}

function combineInfo(requiredInformation: string | null, comments: string | null): string {
  return [requiredInformation, comments].filter((v) => v && v.trim()).join(' · ')
}

export function buildExportModel(
  agenda: Agenda,
  ctx: AgendaProjectContext,
  hostOrg?: HostOrg,
): AgendaExportModel {
  const lang = agenda.language
  const sortedParticipants = [...agenda.participants].sort((a, b) => a.sort_order - b.sort_order)
  const hostHeading = hostOrg?.label?.trim() ? hostOrg.label.trim() : label('hostParticipants', lang)

  const days: ExportDay[] = [...agenda.days]
    .sort((a, b) => a.sort_order - b.sort_order)
    .map((day) => ({
      heading: day.title ?? '',
      dateLabel: formatExportDate(day.date, lang),
      isTravelDay: day.is_travel_day,
      rows: [...day.items]
        .sort((a, b) => a.sort_order - b.sort_order)
        .map((item) => ({
          time: formatTimeSpan(item.start_time, item.end_time),
          subject: item.title,
          duration: formatDuration(item.duration_minutes),
          responsible: item.responsible ?? '',
          participants: item.participant_group ?? '',
          info: combineInfo(item.required_information, item.comments),
          itemType: item.item_type,
          color: resolveItemColor(item),
        })),
    }))

  const startLabel = formatExportDate(agenda.start_date, lang)
  const endLabel = formatExportDate(agenda.end_date, lang)
  const dateRangeLabel = startLabel && endLabel && startLabel !== endLabel ? `${startLabel} – ${endLabel}` : startLabel

  return {
    title: agenda.title,
    language: lang,
    columns: columnLabels(lang),
    labels: {
      participants: label('participants', lang),
      hostParticipants: hostHeading,
      supplierParticipants: label('supplierParticipants', lang),
      objective: label('objective', lang),
      supplier: label('supplier', lang),
      location: label('location', lang),
      date: label('date', lang),
    },
    projectCode: ctx.projectCode,
    supplierName: ctx.supplierName,
    location: ctx.plantLocation ?? '',
    dateRangeLabel,
    objective: agenda.objective ?? '',
    hostParticipants: sortedParticipants.filter((p) => p.participant_type === 'host').map(toParticipant),
    supplierParticipants: sortedParticipants
      .filter((p) => p.participant_type === 'supplier' || p.participant_type === 'external')
      .map(toParticipant),
    days,
  }
}
