import { RdDItem } from "../item.js";
import { Misc } from "../misc.js";
import { RdDTimestamp } from "../time/rdd-timestamp.js";
import { ChatUtility } from "../chat-utility.js";

const BASE_TACHE_SOIN_BLESSURE = {
  type: "tache",
  img: 'systems/foundryvtt-reve-de-dragon/icons/competence_chirurgie.webp',
  system: { carac: "dexterite", competence: "Chirurgie", periodicite: "1 round", fatigue: 0, }
}
const TACHES_SOIN_BLESSURE = {
  6: { name: 'Blessure critique', system: { difficulte: -6, points_de_tache: 6 } },
  4: { name: 'Blessure grave', system: { difficulte: -4, points_de_tache: 4 } },
  2: { name: 'Blessure légère', system: { difficulte: -2, points_de_tache: 2 } },
}

const definitionsBlessures = [
  { type: "contusion", gravite: 0, endurance: "1d4", vie: 0, label: 'Contusion/éraflure', max: 100, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/eraflure.webp" },
  { type: "legere", gravite: 2, endurance: "1d6", vie: 0, label: 'Légère', max: 5, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
  { type: "grave", gravite: 4, endurance: "2d6", vie: -2, label: 'Grave', max: 2, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
  { type: "critique", gravite: 6, endurance: "-100", vie: -4, label: 'Critique', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
  { type: "mort", gravite: 8, label: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" }
]

export class RdDItemBlessure extends RdDItem {

  static get defaultIcon() {
    return "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp";
  }

  prepareDerivedData() {
    super.prepareDerivedData();
    this.system.label = RdDItemBlessure.getLabelGravite(this.system.gravite)
  }

  static prepareTacheSoin(gravite) {
    const tache = TACHES_SOIN_BLESSURE[gravite]
    if (!tache) {
      ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
      return undefined;
    }
    return foundry.utils.mergeObject(BASE_TACHE_SOIN_BLESSURE, tache, { inplace: false })
  }

  static async applyFullBlessure(actor, gravite) {
    const definition = foundry.utils.duplicate(RdDItemBlessure.getDefinition(gravite))

    if (definition.vie) {
      await actor.santeIncDec("vie", definition.vie)
    }
    const lostEndurance = await RdDItemBlessure.rollLostEndurance(definition.endurance)
    if (lostEndurance) {
      await actor.santeIncDec("endurance", -Number(lostEndurance));
    }
    await this.createBlessure(actor, gravite)

    ChatMessage.create({
      //TODO: hbs
      content: `Blessure ${definition.label} appliquée à ${actor.name}<br>Perte d'endurance : ${lostEndurance} (${definition.endurance})<br>Perte de Vie : ${definition.vie}`,
      whisper: ChatUtility.getOwners(actor)
    });
    actor.sheet?.render()
  }

  static async rollLostEndurance(formula) {
    if (formula) {
      const roll = new Roll(formula)
      await roll.evaluate()
      return roll.total
    }
    return 0
  }

  static async createBlessure(actor, gravite, localisation = '', attackerToken) {
    const definition = RdDItemBlessure.getDefinition(gravite)
    const blessure = {
      name: definition.label,
      type: 'blessure',
      img: definition.icon,
      system: {
        gravite: gravite,
        difficulte: - gravite,
        localisation: localisation,
        origine: attackerToken?.name ?? ""
      }
    }
    const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
    return blessures[0]
  }

  static async createTacheSoinBlessure(actor, gravite) {
    const tache = RdDItemBlessure.prepareTacheSoin(gravite)
    if (tache) {
      const taches = await actor.createEmbeddedDocuments('Item', [tache], { renderSheet: false });
      return taches[0];
    }
    return undefined
  }

  async updateTacheSoinBlessure(tache) {
    if (tache) {
      await tache.update({
        system: {
          itemId: this.id,
          difficulte: Math.min(this.system.difficulte, tache.system.difficulte),
          points_de_tache_courant: Math.max(0, this.system.premierssoins.tache)
        }
      });
    }
  }

  async setSoinsBlessure(systemUpdate = {}) {
    systemUpdate = foundry.utils.mergeObject(systemUpdate, this.system, { overwrite: false })
    systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done
    await this.update({
      img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done),
      system: systemUpdate
    })
  }

  async recuperationBlessure({ actor, timestamp, message, isMaladeEmpoisonne, blessures }) {
    if (this.parent != actor || actor == undefined) {
      return
    }
    if (new RdDTimestamp(this.system.temporel.fin).compare(timestamp) > 0) {
      // attente periode
      return
    }
    if (this.system.gravite > 0) {
      const update = { system: { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } } }
      const gravite = this.system.gravite
      const graviteMoindre = gravite - 2
      const moindres = blessures.filter(it => it.system.gravite == graviteMoindre, 'blessures').length
      const label = RdDItemBlessure.getLabelGravite(this.system.gravite)

      let rolled = await actor.jetRecuperationConstitution(this.system.soinscomplets.bonus, message);

      if (rolled.isETotal) {
        message.content += ` -- une blessure ${label} s'infecte (temps de guérison augmenté de ${gravite} jours, perte de vie)`;
        await actor.santeIncDec("vie", -1);
        foundry.utils.mergeObject(update, {
          system: { fin: { indexDate: timestamp.addJours(gravite).indexDate } }
        });
      }
      else {
        if (!isMaladeEmpoisonne && rolled.isSuccess && this.peutRetrograder(graviteMoindre, moindres)) {
          message.content += ` -- une blessure ${label} cicatrise`;
          foundry.utils.mergeObject(update, {
            system: {
              gravite: graviteMoindre,
              temporel: { fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } }
            }
          });
        }
        else {
          message.content += ` -- une blessure ${label} reste stable`;
        }
      }
      await this.update(update);
    }
  }

  peutRetrograder(graviteMoindre, moindres) {
    return moindres < RdDItemBlessure.maxBlessures(graviteMoindre)
  }

  async calculerFinPeriodeTemporel(debut) {
    return debut.nouveauJour().addJours(this.system.gravite);
  }

  async onFinPeriode(oldTimestamp, newTimestamp) {
    if (this.system.gravite <= 0) {
      await super.onFinPeriode(oldTimestamp, newTimestamp)
    }
  }

  getImgSoins(gravite, soins) {
    let img = 'blessure'
    if (gravite > 6) {
      img = 'mort'
    }
    if (gravite <= 0) {
      img = 'eraflure'
    }
    return `systems/foundryvtt-reve-de-dragon/icons/sante/${soins ? 'blessure-soins' : img}.webp`
  }

  static getLabelGravite(gravite) {
    return definitionsBlessures.find(it => it.gravite >= gravite).label
  }

  static getDefinition(gravite) {
    return definitionsBlessures.find(it => it.gravite >= gravite)
  }

  static maxBlessures(gravite) {
    return definitionsBlessures.find(it => it.gravite >= gravite).max
  }

  isContusion() {
    return this.system.gravite <= 0
  }
  isLegere() {
    return this.system.gravite > 0 && this.system.gravite <= 2
  }
  isGrave() {
    return this.system.gravite > 2 && this.system.gravite <= 4
  }
  isCritique() {
    return this.system.gravite > 4 && this.system.gravite <= 6
  }
  isMort() {
    return this.system.gravite > 6
  }

  getProprietes() {
    return [
      RdDItem.propertyIfDefined('Causée par', this.system.origine, this.system.origine),
      `<b>Heure et Date</b>: ${new RdDTimestamp(this.system.temporel.debut).formatDateHeure()}`,
      RdDItem.propertyIfDefined('Blessé', this.parent?.name, this.parent),
      `<b>Localisation</b>: ${this.system.localisation}`,
      `<b>Gravité</b>: ${this.system.label}`,
      `<b>Difficulté des soins</b>: ${this.system.difficulte}`,
      (this.system.soinscomplets.done ?
        `<b>Bonus soins complets</b>: ${this.system.soinscomplets.bonus}` :
        (this.system.premierssoins.done ?
          `<b>Bonus premiers soins</b>: ${this.system.premierssoins.bonus}` :
          `<b>Points de tâche</b>: ${this.system.premierssoins.tache}`
        )
      ),
    ];
  }
}