/**
 * Chroniques de l'Étrange — Système FoundryVTT
 *
 * Chroniques de l'Étrange est un jeu de rôle édité par Antre-Monde Éditions.
 * Ce système FoundryVTT est une implémentation indépendante et n'est pas
 * affilié à Antre-Monde Éditions,
 * mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
 *
 * @author    LeRatierBretonnien
 * @copyright 2024–2026 LeRatierBretonnien
 * @license   CC BY-NC-SA 4.0 – https://creativecommons.org/licenses/by-nc-sa/4.0/
 */

import { parseLegacyJson } from "../../migration/migrator.js"

const MIGRATION_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/apps/cde-migration-app.html"

/**
 * Dialog for importing legacy CDE actor JSON files into the current system.
 *
 * Accessible via the System Settings menu (registerMenu).
 * Supports multi-file selection and shows a preview table before importing.
 */
export class CDEMigrationApp extends foundry.applications.api.HandlebarsApplicationMixin(
  foundry.applications.api.ApplicationV2
) {
  static DEFAULT_OPTIONS = {
    id:      "cde-migration-app",
    classes: ["cde-migration-app"],
    tag:     "div",
    window: {
      title:     "CDE.MigrationTitle",
      icon:      "fas fa-file-import",
      resizable: false,
    },
    position: { width: 560, height: "auto" },
    actions: {
      clearFiles:   CDEMigrationApp.#clearFiles,
      doImport:     CDEMigrationApp.#doImport,
    },
  }

  static PARTS = {
    form: { template: MIGRATION_TEMPLATE },
  }

  /** @type {Array<{name: string, type: string, img: string, system: object, items: object[], _srcFile: string}>} */
  #pending = []

  /** @type {string[]} - error messages per file */
  #errors = []

  async _prepareContext(options) {
    return {
      pending:    this.#pending,
      errors:     this.#errors,
      hasPending: this.#pending.length > 0,
      hasErrors:  this.#errors.length > 0,
      count:      this.#pending.length,
    }
  }

  /** After render, wire up the file input. */
  _onRender(context, options) {
    super._onRender(context, options)
    const input = this.element.querySelector(".cde-migration-file-input")
    input?.addEventListener("change", this.#onFileChange.bind(this))

    const dropZone = this.element.querySelector(".cde-migration-drop-zone")
    if (dropZone) {
      dropZone.addEventListener("dragover", (e) => { e.preventDefault(); dropZone.classList.add("is-dragover") })
      dropZone.addEventListener("dragleave", () => dropZone.classList.remove("is-dragover"))
      dropZone.addEventListener("drop", (e) => {
        e.preventDefault()
        dropZone.classList.remove("is-dragover")
        this.#processFiles(Array.from(e.dataTransfer.files))
      })
    }
  }

  async #onFileChange(event) {
    const files = Array.from(event.target.files ?? [])
    event.target.value = ""
    await this.#processFiles(files)
  }

  async #processFiles(files) {
    for (const file of files) {
      if (!file.name.endsWith(".json")) {
        this.#errors.push(game.i18n.format("CDE.MigrationErrorNotJson", { file: file.name }))
        continue
      }
      try {
        const text = await file.text()
        const actors = parseLegacyJson(text)
        for (const actor of actors) {
          actor._srcFile = file.name
          // Avoid duplicates by name
          if (!this.#pending.some(p => p.name === actor.name)) {
            this.#pending.push(actor)
          }
        }
      } catch (err) {
        this.#errors.push(game.i18n.format("CDE.MigrationErrorParse", { file: file.name, error: err.message }))
      }
    }
    this.render()
  }

  static async #clearFiles() {
    this.#pending = []
    this.#errors = []
    this.render()
  }

  static async #doImport() {
    if (!this.#pending.length) return

    const created = []
    const failed  = []

    for (const data of this.#pending) {
      try {
        const { _srcFile, ...actorData } = data
        const actor = await Actor.create(actorData)
        created.push(actor.name)
      } catch (err) {
        failed.push(`${data.name}: ${err.message}`)
        console.error(`CHRONIQUESDELETRANGE | Migration failed for "${data.name}":`, err)
      }
    }

    this.#pending = []
    this.#errors = failed
    this.render()

    if (created.length) {
      ui.notifications.info(
        game.i18n.format("CDE.MigrationSuccess", { count: created.length, names: created.join(", ") })
      )
    }
    if (failed.length) {
      ui.notifications.warn(
        game.i18n.format("CDE.MigrationPartialError", { count: failed.length })
      )
    }
  }
}
