import { ACTOR_IMAGES, ITEM_IMAGES, LESOUBLIES_CONFIG, PROFILE_KEYS } from "./les-oublies-config.js"

export class LesOubliesUtility {
  static registerHandlebarsHelpers() {
    Handlebars.registerHelper("eq", (left, right) => left === right)
    Handlebars.registerHelper("join", (values, separator = ", ") => Array.isArray(values) ? values.filter(Boolean).join(separator) : "")
    Handlebars.registerHelper("count", (values) => Array.isArray(values) ? values.length : 0)
    Handlebars.registerHelper("concat", (...parts) => parts.slice(0, -1).join(""))
    Handlebars.registerHelper("profileLabel", (key) => LESOUBLIES_CONFIG.profileLabels[key] ?? key)
    Handlebars.registerHelper("skillLabel", (key) => LESOUBLIES_CONFIG.skills[key]?.label ?? key)
    Handlebars.registerHelper("formatPrice", (value) => Number(value) > 0 ? `${value} e` : "—")
    Handlebars.registerHelper("formatSkillBonus", (bonus) => {
      const keys = [bonus.key, ...(bonus.alternativeKeys ?? [])]
        .filter(Boolean)
        .map((key) => LESOUBLIES_CONFIG.skills[key]?.label ?? key)
      const label = keys.join(" ou ")
      const domains = []
      if (Array.isArray(bonus.domainsGranted) && bonus.domainsGranted.length) domains.push(bonus.domainsGranted.join(", "))
      if (Number(bonus.domainsToChoose ?? 0) > 0) {
        const prefix = bonus.domainsToChoose > 1 ? `${bonus.domainsToChoose} choix` : "1 choix"
        domains.push(bonus.domainsChoiceText ? `${prefix} : ${bonus.domainsChoiceText}` : prefix)
      }
      return domains.length ? `${label} +${bonus.base} — ${domains.join(" ; ")}` : `${label} +${bonus.base}`
    })
    Handlebars.registerHelper("formatEquipmentEntry", (entry) => {
      const baseLabel = entry.choiceText || entry.name || ""
      const quantity = Number(entry.quantity ?? 0) > 1 ? ` x${entry.quantity}` : ""
      const extras = []
      if (entry.details) extras.push(entry.details)
      if (Number(entry.ecorces ?? 0) > 0) extras.push(`${entry.ecorces} écorces`)
      return extras.length ? `${baseLabel}${quantity} — ${extras.join(", ")}` : `${baseLabel}${quantity}`
    })
    Handlebars.registerHelper("formatSpellGrant", (grant) => {
      const discipline = LESOUBLIES_CONFIG.skills[grant.skillKey]?.label ?? grant.skillKey ?? grant.tradition
      return `${grant.tradition} (${discipline}) / ${grant.polarity} : ${grant.amount}`
    })
  }

  static getDefaultActorImage(type) {
    return ACTOR_IMAGES[type] ?? "icons/svg/mystery-man.svg"
  }

  static getDefaultItemImage(type) {
    return ITEM_IMAGES[type] ?? "icons/svg/item-bag.svg"
  }

  static createChoices(values = [], labels = {}) {
    return values.map((value) => ({
      value,
      label: labels[value] ?? String(value),
    }))
  }

  static createRangeChoices(min, max, labels = {}) {
    return Array.from({ length: Math.max(max - min + 1, 0) }, (_, index) => min + index).map((value) => ({
      value,
      label: labels[value] ?? String(value),
    }))
  }

  static ensureChoice(choices = [], value, label = null) {
    if (value === undefined || value === null || value === "") return choices
    if (choices.some((choice) => String(choice.value) === String(value))) return choices
    return [{
      value,
      label: label ?? `${value} (personnalisé)`,
    }, ...choices]
  }

  static createEmptyProfiles() {
    return PROFILE_KEYS.reduce((profiles, key) => {
      profiles[key] = 0
      return profiles
    }, {})
  }

  static computeDreamPointTotals(songesValue, cauchemarValue) {
    if (songesValue > cauchemarValue) {
      return {
        songesPoints: songesValue * 2 - cauchemarValue,
        cauchemarPoints: cauchemarValue,
      }
    }
    if (songesValue === cauchemarValue) {
      return {
        songesPoints: songesValue,
        cauchemarPoints: cauchemarValue,
      }
    }
    return {
      songesPoints: songesValue,
      cauchemarPoints: cauchemarValue * 3 - songesValue * 2,
    }
  }

  static sortByName(documents = []) {
    return [...documents].sort((left, right) => left.name.localeCompare(right.name, "fr"))
  }

  static getWeaponBaseDamage(actor, weapon) {
    const sizeMode = String(weapon?.system?.sizeMode || "").toLowerCase()
    if (sizeMode === "variable") {
      const actorSize = Number(actor?.system?.size?.value ?? 0)
      const sizeModifier = Number(weapon?.system?.sizeModifier ?? 0)
      return Math.max(actorSize + sizeModifier, 0)
    }

    const explicitValue = Number(weapon?.system?.sizeValue ?? 0)
    if (explicitValue > 0) return explicitValue

    const damageText = String(weapon?.system?.damage || "")
    const match = damageText.match(/-?\d+/)
    return match ? Number(match[0]) : 0
  }

  static formatWeaponDamage(actor, weapon) {
    const baseLabel = String(weapon?.system?.damage || "").trim()
    const baseDamage = this.getWeaponBaseDamage(actor, weapon)
    const sizeMode = String(weapon?.system?.sizeMode || "").toLowerCase()
    if (sizeMode === "variable" || /taille/i.test(baseLabel)) {
      return baseLabel ? `${baseLabel} (${baseDamage})` : String(baseDamage)
    }
    return baseLabel || String(baseDamage)
  }

  static uniqueStrings(values = []) {
    return [...new Set((Array.isArray(values) ? values : [])
      .map((value) => String(value ?? "").trim())
      .filter(Boolean))]
  }

  static async prepareEnrichedHtml(documentName, type, systemData) {
    const htmlFields = game.system.documentTypes?.[documentName]?.[type]?.htmlFields ?? []
    const enriched = {}

    for (const path of htmlFields) {
      const value = foundry.utils.getProperty(systemData, path) ?? ""
      const html = await foundry.applications.ux.TextEditor.implementation.enrichHTML(value, { async: true })
      foundry.utils.setProperty(enriched, path, html)
    }

    return enriched
  }
}
