import 'server-only'
// tdd-guard:skip — Supabase I/O glue. Verified via integration/E2E once the
// migration is applied (see docs/agenda-feature-plan.md test plan).

import type { SupabaseClient } from '@supabase/supabase-js'
import type {
  Agenda,
  AgendaDay,
  AgendaItem,
  AgendaParticipant,
  AgendaProjectContext,
} from './types'

export interface AgendaListResult {
  /** false when the agenda tables do not exist yet (migration not applied). */
  provisioned: boolean
  /** All language variants for the project, oldest first. */
  agendas: Agenda[]
}

type Row = Record<string, unknown>

const str = (v: unknown): string => (typeof v === 'string' ? v : '')
const strOrNull = (v: unknown): string | null => (typeof v === 'string' ? v : null)
const bool = (v: unknown): boolean => v === true
const num = (v: unknown): number => (typeof v === 'number' ? v : 0)

function rowToItem(r: Row): AgendaItem {
  return {
    id: str(r.id),
    agenda_day_id: str(r.agenda_day_id),
    sort_order: num(r.sort_order),
    start_time: strOrNull(r.start_time),
    end_time: strOrNull(r.end_time),
    duration_minutes: num(r.duration_minutes),
    title: str(r.title),
    description: strOrNull(r.description),
    responsible: strOrNull(r.responsible),
    participant_group: strOrNull(r.participant_group),
    location: strOrNull(r.location),
    item_type: (strOrNull(r.item_type) ?? 'workshop') as AgendaItem['item_type'],
    comments: strOrNull(r.comments),
    required_information: strOrNull(r.required_information),
    is_time_fixed: bool(r.is_time_fixed),
    color: strOrNull(r.color),
  }
}

function rowToParticipant(r: Row): AgendaParticipant {
  return {
    id: str(r.id),
    agenda_id: str(r.agenda_id),
    person_id: strOrNull(r.person_id),
    name: str(r.name),
    company: strOrNull(r.company),
    department: strOrNull(r.department),
    department_id: strOrNull(r.department_id),
    position: strOrNull(r.position),
    role: strOrNull(r.role),
    participant_type: (strOrNull(r.participant_type) ?? 'supplier') as AgendaParticipant['participant_type'],
    email: strOrNull(r.email),
    comment: strOrNull(r.comment),
    is_auto_imported_from_project: bool(r.is_auto_imported_from_project),
    sort_order: num(r.sort_order),
  }
}

function rowToDay(r: Row, items: AgendaItem[]): AgendaDay {
  return {
    id: str(r.id),
    agenda_id: str(r.agenda_id),
    date: strOrNull(r.date),
    day_index: num(r.day_index),
    title: strOrNull(r.title),
    is_travel_day: bool(r.is_travel_day),
    start_time: strOrNull(r.start_time),
    end_time: strOrNull(r.end_time),
    sort_order: num(r.sort_order),
    items,
  }
}

async function assembleAgenda(supabase: SupabaseClient, agendaRow: Row): Promise<Agenda> {
  const agendaId = str(agendaRow.id)
  const [daysResult, participantsResult] = await Promise.all([
    supabase.from('agenda_day').select('*').eq('agenda_id', agendaId).order('sort_order', { ascending: true }),
    supabase.from('agenda_participant').select('*').eq('agenda_id', agendaId).order('sort_order', { ascending: true }),
  ])

  const dayRows = (daysResult.data as Row[] | null) ?? []
  const dayIds = dayRows.map((d) => str(d.id))
  const itemRows = dayIds.length
    ? (((await supabase.from('agenda_item').select('*').in('agenda_day_id', dayIds).order('sort_order', { ascending: true })).data) as Row[] | null) ?? []
    : []

  const days = dayRows.map((d) =>
    rowToDay(d, itemRows.filter((i) => str(i.agenda_day_id) === str(d.id)).map(rowToItem)),
  )
  const participants = ((participantsResult.data as Row[] | null) ?? []).map(rowToParticipant)

  return {
    id: agendaId,
    project_id: str(agendaRow.project_id),
    title: str(agendaRow.title),
    language: (strOrNull(agendaRow.language) ?? 'de') as Agenda['language'],
    agenda_type: (strOrNull(agendaRow.agenda_type) ?? 'sonstiges') as Agenda['agenda_type'],
    generation_mode: (strOrNull(agendaRow.generation_mode) ?? 'suggest') as Agenda['generation_mode'],
    start_date: strOrNull(agendaRow.start_date),
    end_date: strOrNull(agendaRow.end_date),
    first_day_is_travel_day: bool(agendaRow.first_day_is_travel_day),
    start_mode: (strOrNull(agendaRow.start_mode) ?? 'morning') as Agenda['start_mode'],
    default_day_start_time: str(agendaRow.default_day_start_time) || '08:30',
    default_day_end_time: str(agendaRow.default_day_end_time) || '17:00',
    objective: strOrNull(agendaRow.objective),
    status: (strOrNull(agendaRow.status) ?? 'draft') as Agenda['status'],
    created_by: strOrNull(agendaRow.created_by),
    updated_by: strOrNull(agendaRow.updated_by),
    created_at: str(agendaRow.created_at),
    updated_at: str(agendaRow.updated_at),
    days,
    participants,
  }
}

/**
 * Load all agendas (language variants) for a project as nested aggregates.
 * Returns `provisioned: false` when the agenda tables are missing, so the page
 * can show an informative state instead of crashing before the migration.
 */
export async function loadProjectAgendas(
  supabase: SupabaseClient,
  projectId: string,
): Promise<AgendaListResult> {
  const { data, error } = await supabase
    .from('agenda')
    .select('*')
    .eq('project_id', projectId)
    .order('created_at', { ascending: true })

  if (error) return { provisioned: false, agendas: [] }
  const rows = (data as Row[] | null) ?? []
  const agendas = await Promise.all(rows.map((row) => assembleAgenda(supabase, row)))
  return { provisioned: true, agendas }
}

/** Build the agenda project-context (supplier, location, logos) from a project row. */
export function toAgendaProjectContext(project: {
  id: string
  project_code?: string | null
  supplier_name?: string | null
  plant_location?: string | null
  supplier_master_data?: { supplier_name?: string | null; logo_storage_key?: string | null } | Array<{ supplier_name?: string | null; logo_storage_key?: string | null }> | null
}): AgendaProjectContext {
  const supplierMaster = Array.isArray(project.supplier_master_data)
    ? project.supplier_master_data[0]
    : project.supplier_master_data
  const supplierName = project.supplier_name || supplierMaster?.supplier_name || ''
  const logoKey = supplierMaster?.logo_storage_key
  return {
    projectId: project.id,
    projectCode: project.project_code ?? null,
    supplierName,
    plantLocation: project.plant_location ?? null,
    supplierLogoKeys: logoKey ? [logoKey] : [],
  }
}
