import api from './api'

export function defaultSection(title = 'Hauptteil') {
  return { title, guidance_notes: '', items: [] }
}

export function exerciseRow() {
  return {
    item_type: 'exercise',
    exercise_id: '',
    exercise_variant_id: '',
    exercise_title: '',
    variants: [],
    planned_duration_min: '',
    actual_duration_min: '',
    notes: '',
    modifications: '',
    source_training_module_id: '',
    source_module_title: '',
  }
}

export async function hydrateExercisePlanningRow(exercise) {
  let variants = Array.isArray(exercise?.variants) ? exercise.variants : []
  let title = exercise?.title || ''
  const id = exercise?.id
  if (!id) return null
  let meta = {}
  if (!variants.length) {
    try {
      const full = await api.getExercise(id)
      variants = Array.isArray(full?.variants) ? full.variants : []
      title = full?.title || title
      meta = {
        exercise_visibility: full?.visibility || 'private',
        exercise_club_id: full?.club_id ?? null,
        exercise_created_by: full?.created_by ?? null,
        exercise_status: full?.status || 'draft',
      }
    } catch {
      variants = []
    }
  } else {
    meta = {
      exercise_visibility: exercise?.visibility ?? null,
      exercise_club_id: exercise?.club_id ?? null,
      exercise_created_by: exercise?.created_by ?? null,
      exercise_status: exercise?.status ?? null,
    }
    if (meta.exercise_visibility == null || meta.exercise_created_by == null) {
      try {
        const full = await api.getExercise(id)
        if (meta.exercise_visibility == null) meta.exercise_visibility = full?.visibility || 'private'
        if (meta.exercise_club_id == null) meta.exercise_club_id = full?.club_id ?? null
        if (meta.exercise_created_by == null) meta.exercise_created_by = full?.created_by ?? null
        if (meta.exercise_status == null) meta.exercise_status = full?.status || 'draft'
      } catch {
        /* keep partial meta */
      }
    }
    meta.exercise_visibility = meta.exercise_visibility || 'private'
    meta.exercise_status = meta.exercise_status || 'draft'
  }
  const row = exerciseRow()
  row.exercise_id = id
  row.exercise_variant_id = ''
  row.exercise_title = title
  row.variants = variants
  Object.assign(row, meta)
  return row
}

export function noteRow() {
  return { item_type: 'note', note_body: '', source_training_module_id: '', source_module_title: '' }
}

/** Zur Serialisierung in die Planungs-API (persistente Modul-Herkunft). */
function parseOptionalSourceTrainingModuleIdForPayload(v) {
  if (v === null || v === undefined || v === '') return null
  const n = typeof v === 'number' ? v : parseInt(String(v).trim(), 10)
  return Number.isFinite(n) && n >= 1 ? n : null
}

export function normalizeUnitToForm(fullUnit) {
  if (fullUnit.sections && fullUnit.sections.length) {
    return fullUnit.sections.map((sec) => ({
      title: sec.title,
      guidance_notes: sec.guidance_notes || '',
      items: (sec.items || []).map((it) => {
        if (it.item_type === 'note') {
          const sm = parseOptionalSourceTrainingModuleIdForPayload(it.source_training_module_id)
          const rowNote = {
            item_type: 'note',
            note_body: it.note_body || '',
            source_training_module_id: '',
            source_module_title: '',
          }
          if (sm != null) {
            rowNote.source_training_module_id = sm
            rowNote.source_module_title = (
              it.source_module_title ||
              it.source_training_module_title ||
              ''
            ).trim()
          }
          return rowNote
        }
        const smEx = parseOptionalSourceTrainingModuleIdForPayload(it.source_training_module_id)
        return {
          item_type: 'exercise',
          exercise_id: it.exercise_id,
          exercise_variant_id: it.exercise_variant_id ?? '',
          exercise_title: it.exercise_title || '',
          variants: [],
          planned_duration_min:
            it.planned_duration_min !== null && it.planned_duration_min !== undefined
              ? String(it.planned_duration_min)
              : '',
          actual_duration_min:
            it.actual_duration_min !== null && it.actual_duration_min !== undefined
              ? String(it.actual_duration_min)
              : '',
          notes: it.notes ?? '',
          modifications: it.modifications ?? '',
          ...(smEx != null
            ? {
                source_training_module_id: smEx,
                source_module_title: (
                  it.source_module_title ||
                  it.source_training_module_title ||
                  ''
                ).trim(),
              }
            : {}),
        }
      }),
    }))
  }
  if (fullUnit.exercises && fullUnit.exercises.length) {
    return [
      {
        title: 'Übungen',
        guidance_notes: '',
        items: fullUnit.exercises.map((ex) => ({
          item_type: 'exercise',
          exercise_id: ex.exercise_id,
          exercise_variant_id: ex.exercise_variant_id ?? '',
          exercise_title: ex.exercise_title || '',
          variants: [],
          planned_duration_min:
            ex.planned_duration_min !== null && ex.planned_duration_min !== undefined
              ? String(ex.planned_duration_min)
              : '',
          actual_duration_min:
            ex.actual_duration_min !== null && ex.actual_duration_min !== undefined
              ? String(ex.actual_duration_min)
              : '',
          notes: ex.notes ?? '',
          modifications: ex.modifications ?? '',
        })),
      },
    ]
  }
  return [defaultSection()]
}

export async function enrichSectionsWithVariants(sections) {
  if (!sections?.length) return sections
  const ids = []
  for (const sec of sections) {
    for (const it of sec.items || []) {
      if (it.item_type === 'note') continue
      if (it.exercise_id) ids.push(it.exercise_id)
    }
  }
  const unique = [...new Set(ids)]
  const cache = new Map()
  await Promise.all(
    unique.map(async (id) => {
      try {
        const ex = await api.getExercise(id)
        cache.set(id, {
          title: ex.title || '',
          variants: Array.isArray(ex.variants) ? ex.variants : [],
          visibility: ex.visibility || 'private',
          club_id: ex.club_id ?? null,
          created_by: ex.created_by ?? null,
          status: ex.status || 'draft',
        })
      } catch {
        cache.set(id, {
          title: '',
          variants: [],
          visibility: 'private',
          club_id: null,
          created_by: null,
          status: 'draft',
        })
      }
    })
  )
  return sections.map((sec) => ({
    ...sec,
    items: (sec.items || []).map((it) => {
      if (it.item_type === 'note') return it
      if (!it.exercise_id) return it
      const c = cache.get(it.exercise_id)
      if (!c) return it
      return {
        ...it,
        exercise_title: it.exercise_title || c.title,
        variants:
          Array.isArray(it.variants) && it.variants.length > 0 ? it.variants : c.variants,
        exercise_visibility: c.visibility,
        exercise_club_id: c.club_id,
        exercise_created_by: c.created_by,
        exercise_status: c.status,
      }
    }),
  }))
}

export function parseMin(v) {
  if (v === '' || v === null || v === undefined) return null
  const n = parseInt(String(v), 10)
  return Number.isFinite(n) ? n : null
}

export function buildSectionsPayload(sections) {
  return sections.map((sec, si) => ({
    order_index: si,
    title: (sec.title || '').trim() || 'Abschnitt',
    guidance_notes: sec.guidance_notes?.trim() ? sec.guidance_notes.trim() : null,
    items: (sec.items || [])
      .map((it, ii) => {
        if (it.item_type === 'note') {
          const sm = parseOptionalSourceTrainingModuleIdForPayload(it.source_training_module_id)
          const row = {
            item_type: 'note',
            order_index: ii,
            note_body: it.note_body ?? '',
          }
          if (sm != null) row.source_training_module_id = sm
          return row
        }
        if (it.exercise_id === '' || it.exercise_id == null || Number.isNaN(Number(it.exercise_id))) {
          return null
        }
        const vid = it.exercise_variant_id
        const smEx = parseOptionalSourceTrainingModuleIdForPayload(it.source_training_module_id)
        const rowEx = {
          item_type: 'exercise',
          order_index: ii,
          exercise_id: parseInt(it.exercise_id, 10),
          exercise_variant_id:
            vid !== '' && vid != null && !Number.isNaN(Number(vid)) ? parseInt(vid, 10) : null,
          planned_duration_min: parseMin(it.planned_duration_min),
          actual_duration_min: parseMin(it.actual_duration_min),
          notes: it.notes?.trim() ? it.notes.trim() : null,
          modifications: it.modifications?.trim() ? it.modifications.trim() : null,
        }
        if (smEx != null) rowEx.source_training_module_id = smEx
        return rowEx
      })
      .filter(Boolean),
  }))
}

/** Fügt die Positionen eines Moduls in lokale Abschnitte ein (wie eine Übung, ohne Zwischenspeichern der Einheit). */
export async function insertTrainingModuleIntoPlanningSections({
  sections,
  moduleDetail,
  sectionIndex,
  insertBeforeItemIndex,
}) {
  const secIx = typeof sectionIndex === 'number' ? sectionIndex : parseInt(String(sectionIndex), 10)
  if (
    !Array.isArray(sections) ||
    !Number.isFinite(secIx) ||
    secIx < 0 ||
    secIx >= sections.length ||
    !moduleDetail ||
    typeof moduleDetail !== 'object'
  ) {
    return sections
  }
  const prev = [...(sections[secIx].items || [])]
  let beforeIx
  if (insertBeforeItemIndex === null || insertBeforeItemIndex === undefined || insertBeforeItemIndex === 'end') {
    beforeIx = prev.length
  } else if (insertBeforeItemIndex === 'start') {
    beforeIx = 0
  } else {
    const n = typeof insertBeforeItemIndex === 'number' ? insertBeforeItemIndex : parseInt(String(insertBeforeItemIndex), 10)
    beforeIx = Number.isFinite(n) ? Math.min(Math.max(n, 0), prev.length) : prev.length
  }

  const midRaw = moduleDetail.id
  const midNum = typeof midRaw === 'number' ? midRaw : parseInt(String(midRaw), 10)
  if (!Number.isFinite(midNum) || midNum < 1) return sections

  const modTitle = (moduleDetail.title || '').trim() || `Modul #${midNum}`
  const modItems = [...(moduleDetail.items || [])].sort(
    (a, b) => (a.order_index ?? 0) - (b.order_index ?? 0)
  )

  const appendRows = []
  for (const mi of modItems) {
    if (mi.item_type === 'note') {
      appendRows.push({
        item_type: 'note',
        note_body: mi.note_body || '',
        source_training_module_id: midNum,
        source_module_title: modTitle,
      })
      continue
    }
    if (!mi.exercise_id) continue
    const hydrated = await hydrateExercisePlanningRow({ id: mi.exercise_id })
    if (!hydrated) continue
    hydrated.source_training_module_id = midNum
    hydrated.source_module_title = modTitle
    if (mi.exercise_variant_id) hydrated.exercise_variant_id = String(mi.exercise_variant_id)
    hydrated.planned_duration_min =
      mi.planned_duration_min !== null && mi.planned_duration_min !== undefined
        ? String(mi.planned_duration_min)
        : ''
    hydrated.notes = mi.notes ?? ''
    appendRows.push(hydrated)
  }

  const mergedItems = [...prev.slice(0, beforeIx), ...appendRows, ...prev.slice(beforeIx)]
  return sections.map((sec, idx) => (idx === secIx ? { ...sec, items: mergedItems } : sec))
}

export function sectionPlannedMinutes(sec) {
  return (sec.items || []).reduce((sum, it) => {
    if (it.item_type !== 'exercise') return sum
    const m = parseMin(it.planned_duration_min)
    return sum + (m || 0)
  }, 0)
}
