import { VermineUtils } from "../roll.mjs";

const { HandlebarsApplicationMixin } = foundry.applications.api;

export default class RollDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {

  #actor;

  get title() {
    return game.i18n.localize("VERMINE.roll");
  }

  static DEFAULT_OPTIONS = {
    classes: ["vermine-roll"],
    tag: "form",
    window: {
      icon: "fas fa-dice-d10",
      resizable: false
    },
    position: {
      width: 520,
      height: 600
    },
    actions: {
      roll: RollDialog.#onRoll,
      cancel: RollDialog.#onCancel
    }
  };

  static PARTS = {
    main: { template: "systems/vermine2047/templates/dialogs/roll-dialog.hbs" }
  };

  static async create(data = {}) {
    const actorId = data.actorId ?? game.user.character?.id ?? canvas.tokens.controlled[0]?.actor?.id;
    if (!actorId || typeof actorId !== "string") {
      ui.notifications.warn(game.i18n.localize("VERMINE.error_no_actor_selected"));
      return null;
    }
    const actor = await game.actors.get(actorId);
    if (!actor) {
      ui.notifications.warn(game.i18n.localize("VERMINE.error_no_actor_selected"));
      return null;
    }
    return new RollDialog({ actor, label: data.label, rolltype: data.rolltype });
  }

  constructor(options = {}) {
    super(options);
    this.#actor = options.actor;
    this.label = options.label ?? null;
    this.rolltype = options.rolltype ?? null;
  }

  async _prepareContext() {
    const actor = this.#actor;
    return {
      actor,
      system: actor.system,
      config: CONFIG.VERMINE,
      label: this.label,
      rollType: this.rolltype,
      labelKey: this.label,
      speakerId: actor.id,
      ability: null,
      help: false,
      specialty: false,
      availableSpecialties: actor.items.filter(i => i.type === "specialty"),
      availableItems: actor.items.filter(i => i.type === "item")
    };
  }

  async _onRender(context, options) {
    this.element.dataset.actorId = this.#actor.id;

    for (const inp of this.element.querySelectorAll("[data-roll]")) {
      inp.addEventListener("change", this.#onInputChange.bind(this));
    }

    const ability = this.element.querySelector("#ability");
    if (ability) {
      ability.addEventListener("change", this.#onChangeAbility.bind(this));
      const selfControl = this.element.querySelector("#self_control");
      if (selfControl) selfControl.max = ability.value;
    }

    const selfControl = this.element.querySelector("#self_control");
    if (selfControl) {
      selfControl.addEventListener("change", this.#onChangeSelfControl.bind(this));
    }

    this.element.querySelector("#difficulty")?.addEventListener("change", () => this.#updateUI());
    this.element.querySelector("#handicap")?.addEventListener("change", () => this.#updateUI());
    this.element.querySelector("#human-totem")?.addEventListener("change", () => this.#updateUI());
    this.element.querySelector("#adapted-totem")?.addEventListener("change", () => this.#updateUI());

    this.#displaySpecialties();
    this.#updateUI();

    if (ability?.value !== "0") {
      this.element.querySelector("#self_control")?.dispatchEvent(new Event("change"));
    }
  }

  // ── Getters ──────────────────────────────────────────────────────────

  get #el() { return this.element; }

  #getAbility() { return this.#el.querySelector("#ability"); }
  #getSkill() { return this.#el.querySelector("#skill"); }
  #getDifficulty() { return this.#el.querySelector("#difficulty"); }
  #getHandicap() { return this.#el.querySelector("#handicap"); }
  #getSelfCtrl() { return this.#el.querySelector("#self_control"); }

  getDicePool() {
    const abil = this.#getAbility();
    const abilVal = parseInt(abil?.options[abil?.selectedIndex]?.value, 10) || 0;
    const skill = this.#getSkill();
    const skillPool = parseInt(skill?.options[skill?.selectedIndex]?.dataset?.pool, 10) || 0;
    const sc = parseInt(this.#getSelfCtrl()?.value, 10) || 0;
    const specChecked = this.#el.querySelector("#usingSpecialization")?.checked;
    const helped = this.#el.querySelector("#helped")?.checked;
    const tools = this.#el.querySelector("input[name='usingTools']:checked")?.value !== "0";
    const bonuses = (specChecked ? 1 : 0) + (helped ? 1 : 0) + (tools ? 1 : 0);
    return (abilVal + sc + skillPool + bonuses) || 0;
  }

  getDifficultySelect() {
    const sel = this.#getDifficulty();
    const idx = sel?.selectedIndex ?? 0;
    return parseInt(sel?.options[idx]?.value, 10) || 7;
  }

  getReroll() {
    const sel = this.#getSkill();
    const idx = sel?.selectedIndex ?? 0;
    return parseInt(sel?.options[idx]?.dataset?.reroll, 10) || 0;
  }

  getHandicapSelect() {
    const sel = this.#getHandicap();
    return Math.max(0, (parseInt(sel?.value, 10) || 1) - 1);
  }

  getSkillCategory() {
    const sel = this.#getSkill();
    const idx = sel?.selectedIndex ?? 0;
    return sel?.options[idx]?.dataset?.category ?? null;
  }

  getSkillLevel() {
    const sel = this.#getSkill();
    const idx = sel?.selectedIndex ?? 0;
    const val = sel?.options[idx]?.value;
    return val ? parseInt(val, 10) : null;
  }

  hasSpecialtySelected() {
    const checked = this.#el.querySelector("input[name='usingSpecialization']:checked");
    return checked && checked.value !== "aucune";
  }

  getRollType() {
    const sel = this.#getSkill();
    return sel?.value ? "skill" : "ability";
  }

  getLabel() {
    const type = this.getRollType();
    if (type === "skill") {
      const sel = this.#getSkill();
      const idx = sel?.selectedIndex ?? 0;
      return sel?.options[idx]?.dataset?.label ?? "";
    }
    const sel = this.#getAbility();
    const idx = sel?.selectedIndex ?? 0;
    return sel?.options[idx]?.dataset?.label ?? "";
  }

  getSelfControl() {
    return parseInt(this.#getSelfCtrl()?.value, 10) || 0;
  }

  getMaxEffort() {
    const sel = this.#getAbility();
    return parseInt(sel?.value, 10) || 0;
  }

  getTotems() {
    return {
      human: this.#el.querySelector("#human-totem")?.checked ?? false,
      adapted: this.#el.querySelector("#adapted-totem")?.checked ?? false
    };
  }

  getKeepTotem() {
    return this.#el.querySelector("#keep-totem-select")?.value ?? null;
  }

  // ── UI ───────────────────────────────────────────────────────────────

  #displaySpecialties() {
    for (const el of this.#el.querySelectorAll("[data-spec-skill]")) {
      el.style.display = "inline";
    }
  }

  #calculateBonusCount() {
    let b = 0;
    if (this.#el.querySelector("#helped")?.checked) b += 1;
    b += parseInt(this.#el.querySelector("#group")?.value, 10) || 0;
    b += parseInt(this.#getSelfCtrl()?.value, 10) || 0;
    const tools = this.#el.querySelector("input[name='usingTools']:checked");
    if (tools && tools.value !== "0") b += 1;
    const human = this.#el.querySelector("#human-totem");
    if (human?.checked) b += parseInt(this.#actor?.system?.adaptation?.totems?.human?.value, 10) || 0;
    const adapted = this.#el.querySelector("#adapted-totem");
    if (adapted?.checked) b += parseInt(this.#actor?.system?.adaptation?.totems?.adapted?.value, 10) || 0;
    if (this.hasSpecialtySelected()) b += 1;
    return b;
  }

  #updateUI() {
    const total = this.getDicePool();
    const totalEl = this.#el.querySelector("#dice-pool-total");
    if (totalEl) totalEl.textContent = `${total}D`;

    const bonusEl = this.#el.querySelector("#total-bonus");
    if (bonusEl) bonusEl.textContent = this.#calculateBonusCount();

    const diffSel = this.#getDifficulty();
    const diffEl = this.#el.querySelector("#current-difficulty");
    if (diffEl && diffSel) {
      const idx = diffSel.selectedIndex;
      const val = diffSel.options[idx].value;
      const lbl = diffSel.options[idx].text.split(" ")[0];
      diffEl.textContent = `${lbl} (${val})`;
    }

    const handSel = this.#getHandicap();
    const handEl = this.#el.querySelector("#current-handicap");
    if (handEl && handSel) {
      handEl.textContent = handSel.options[handSel.selectedIndex].text;
    }

    const abilSel = this.#getAbility();
    const abilValEl = this.#el.querySelector("#abilityScoreValue");
    if (abilSel && abilValEl) {
      const idx = abilSel.selectedIndex;
      abilValEl.textContent = idx > 0 ? abilSel.options[idx].value : "0";
    }

    const specChecked = this.#el.querySelector("input[name='usingSpecialization']:checked");
    const specEl = this.#el.querySelector(".current-specialty");
    if (specEl && specChecked) {
      specEl.textContent = specChecked.value === "aucune"
        ? game.i18n.localize("VERMINE.none")
        : specChecked.value;
    }
  }

  // ── Event handlers ───────────────────────────────────────────────────

  #onInputChange() {
    this.#updateUI();
  }

  #onChangeAbility(ev) {
    const sel = ev.currentTarget;
    const score = sel.options[sel.selectedIndex]?.value ?? "0";
    const scoreEl = this.#el.querySelector("#abilityScore");
    if (scoreEl) scoreEl.value = score;
    const sc = this.#getSelfCtrl();
    if (sc) sc.max = score;
    this.#updateUI();
  }

  #onChangeSelfControl(ev) {
    const valEl = this.#el.querySelector("#self_control_value");
    if (valEl) valEl.textContent = ev.currentTarget.value;
  }

  static async #onCancel(event, target) {
    this.close();
  }

  static async #onRoll(event, target) {
    const selfCtrl = this.getSelfControl();
    if (selfCtrl > 0) {
      const current = this.#actor?.system?.attributes?.self_control?.value ?? 0;
      if (current < selfCtrl) {
        ui.notifications.warn(game.i18n.localize("VERMINE.error_not_enough_self_control"));
        return;
      }
    }

    const abilityVal = this.#el.querySelector('[name="ability"]')?.value;
    if (!abilityVal || abilityVal === "0") {
      ui.notifications.warn(game.i18n.localize("VERMINE.error_select_ability"));
      return;
    }

    if (selfCtrl > 0) {
      const newVal = this.#actor.system.attributes.self_control.value - selfCtrl;
      await this.#actor.update({ "system.attributes.self_control.value": newVal });
    }

    await VermineUtils.roll({
      actor: this.#actor,
      NoD: this.getDicePool(),
      Reroll: this.getReroll(),
      difficulty: this.getDifficultySelect(),
      handicap: this.getHandicapSelect(),
      rollLabel: this.getLabel(),
      totems: this.getTotems(),
      self_control: selfCtrl,
      max_effort: this.getMaxEffort(),
      keepTotem: this.getKeepTotem(),
      skillCategory: this.getSkillCategory(),
      skillLevel: this.getSkillLevel(),
      hasSpecialty: this.hasSpecialtySelected()
    });

    this.close();
  }

}
