import { renderTemplate } from "../constants.js"
import { RdDTimestamp, RDD_HEURES_PAR_JOUR } from "../time/rdd-timestamp.js"
import { ChatUtility } from "../chat-utility.js"
import { DialogNouveauReposCD } from "./dialog-nouveau-repos-cd.js"

export class DialogNouveauRepos extends foundry.applications.api.DialogV2 {
  static async create(actor) {
    if (!actor.isPersonnage()) return
    const now = game.system.rdd.calendrier.timestamp
    const heureCourante = now.heure
    const hourDefs = RdDTimestamp.definitions()
    const data = {
      name: actor.name, img: actor.img, hourDefinitions: hourDefs,
      heureDebutDefaut: heureCourante,
      heureFinDefaut: Math.min(heureCourante + 7, 11),
    }
    const content = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-nouveau-repos.hbs", data)
    new DialogNouveauRepos(content, actor).render({ force: true })
  }

  constructor(content, actor) {
    super({
      title: "Se reposer — " + actor.name,
      content,
      classes: ["dialog-nouveau-repos"],
      position: { width: 450, height: 'fit-content' },
      buttons: [
        { label: "Dormir", action: "dormir", callback: () => this._onDormir() },
        { label: "Passer Château Dormant", action: "chateauDormant", callback: () => this._onChateauDormant() }
      ]
    })
    this.actor = actor
  }

  _onRender(context) {
    super._onRender(context)
    const el = this.element
    el.querySelectorAll('select[name="heure-debut"], select[name="heure-fin"]').forEach(s =>
      s.addEventListener("change", () => this._updateDuree())
    )
    el.querySelector('input[name="reveil-force"]')?.addEventListener("change", () => this._toggleReveilForce())
    this._updateDuree()
  }

  _val(sel) { return this.element.querySelector(sel)?.value ?? "" }

  _updateDuree() {
    const el = this.element
    const debut = Number(el.querySelector('select[name="heure-debut"]')?.value ?? 0)
    const fin = Number(el.querySelector('select[name="heure-fin"]')?.value ?? 0)
    const duree = fin >= debut ? fin - debut + 1 : (RDD_HEURES_PAR_JOUR - debut) + fin + 1
    const d = el.querySelector("#duree-sommeil")
    if (d) d.textContent = duree
  }

  _toggleReveilForce() {
    const el = this.element
    const checked = el.querySelector('input[name="reveil-force"]')?.checked ?? false
    const hf = el.querySelector('input[name="heures-force"]')
    if (hf) hf.disabled = !checked
  }

  async _onDormir() {
    const el = this.element
    const debut = Number(el.querySelector('select[name="heure-debut"]')?.value ?? 0)
    const fin = Number(el.querySelector('select[name="heure-fin"]')?.value ?? 0)
    const reveilForce = el.querySelector('input[name="reveil-force"]')?.checked ?? false
    const heuresForce = Number(el.querySelector('input[name="heures-force"]')?.value ?? 0)
    const duree = fin >= debut ? fin - debut + 1 : (RDD_HEURES_PAR_JOUR - debut) + fin + 1
    const valide = await this._valider(debut, duree, reveilForce, heuresForce)
    if (!valide) return
    this.close()
    await this._executerSommeil(debut, duree, reveilForce, heuresForce)
  }

  async _onChateauDormant() {
    this.close()
    const cdData = await DialogNouveauReposCD.prompt(this.actor)
    if (cdData.stress.valeur > 0) {
      await this.actor.distribuerStress("stress", cdData.stress.valeur, cdData.stress.motif)
    }
    await this.actor.update({
      "system.sommeil": {
        nouveaujour: true,
        date: game.system.rdd.calendrier.getTimestampFinChateauDormant(),
        moral: cdData.moral,
        heures: 0
      }
    })
    await this.actor.$dormirChateauDormant()
  }

  _el(sel) { return this.element.querySelector(sel) }

  async _valider(debut, duree, reveilForce, heuresForce) {
    const av = this._el("#avertissements")
    if (av) { av.innerHTML = ""; av.style.display = "block" }
    const fatigue = this.actor.system.sante.fatigue.value
    const fatigueMin = this.actor.getFatigueMin()
    const aFatigue = fatigue > fatigueMin
    const aHeuresJour = this._aHeuresJour(debut, duree)
    if (aHeuresJour && !aFatigue) {
      if (av) av.innerHTML = '<p class="notification error">Vous n\'avez pas assez de fatigue pour dormir de jour.</p>'
      return false
    }
    if (aHeuresJour && aFatigue) {
      if (av) av.insertAdjacentHTML("beforeend", '<p class="notification warning">Vous vous réveillerez dès la fatigue récupérée (sommeil de jour).</p>')
    }
    if (reveilForce && heuresForce < duree) {
      if (av) av.insertAdjacentHTML("beforeend", "<p class=\"notification info\">Vous serez réveillé après " + heuresForce + " heures.</p>")
    }
    return true
  }

  _aHeuresJour(debut, duree) {
    for (let h = 0; h < duree; h++) {
      const heure = (debut + h) % RDD_HEURES_PAR_JOUR
      if (heure > 0 && heure < 6) return true
    }
    return false
  }

  async _executerSommeil(heureDebut, duree, reveilForce, heuresForce) {
    const message = {
      whisper: ChatUtility.getOwners(this.actor),
      content: this.actor.name + ": "
    }
    const dormi = { heures: 0, etat: "dort", jetsReve: [] }
    const insomnie = this.actor.system.sommeil?.insomnie || duree === 0
    await this.actor.recupereEndurance({ message, demi: insomnie })
    if (insomnie) {
      message.content += "Vous ne trouvez pas le sommeil"
    } else {
      const avaitFatigue = this.actor.system.sante.fatigue.value > this.actor.getFatigueMin()
      if (!avaitFatigue && heureDebut >= 6 && heureDebut <= 11) {
        duree = RDD_HEURES_PAR_JOUR - heureDebut + 1
      }
      let cdProcessed = false
      let h = 0
      while (true) {
        if (dormi.etat !== "dort") break
        if (reveilForce && dormi.heures >= heuresForce) break
        if (!avaitFatigue && h >= duree) break
        if (avaitFatigue && this.actor.system.sante.fatigue.value <= this.actor.getFatigueMin()) break
        await this.actor.$recupererEthylisme(message)
        await this.actor.$recupererFatigue(message)
        await this.actor.$jetRecuperationReve(dormi, message)
        dormi.heures++
        if (dormi.etat !== "dort") break
        if (h % RDD_HEURES_PAR_JOUR === RDD_HEURES_PAR_JOUR - 1 && !cdProcessed) {
          cdProcessed = true
          const cdData = await DialogNouveauReposCD.prompt(this.actor)
          if (cdData.stress.valeur > 0) {
            await this.actor.distribuerStress("stress", cdData.stress.valeur, cdData.stress.motif)
          }
          await this.actor.update({
            "system.sommeil": {
              nouveaujour: true,
              date: game.system.rdd.calendrier.getTimestampFinChateauDormant(),
              moral: cdData.moral,
              heures: Math.max(0, duree - h - 1)
            }
          })
          await this.actor.$dormirChateauDormant()
        }
        h++
      }
      if (dormi.jetsReve.length > 0) {
        message.content += "Vous récupérez " +
          dormi.jetsReve.map(it => it < 0 ? "0 (réveil)" : it).join("+") +
          " Points de rêve. "
      }
      if (dormi.etat === "eveil") {
        await this.actor.reveilReveDeDragon(message, dormi.heures)
      }
      message.content += `Vous avez dormi ${dormi.heures <= 1 ? "une heure" : (dormi.heures + " heures")}. `
    }
    await ChatMessage.create(message)
  }
}
