import { inferWeaponSkillFromName } from './mgt2eSkills.js';

const MODULE_ID = 'mgt2-compendium-amiral-denisov';
const MIGRATION_SETTING = 'mgt2eMigrationVersion';
const MIGRATION_VERSION = 2;

const ITEM_PACKS = [
  'armures',
  'competences',
  'maladie-poison-and-blessure',
  'objet',
  'equipement',
  'ordinateur',
  'contenant-sac-coffre',
  'espece',
  'armes',
  'talents-psioniques',
  'carrieres',
];

Hooks.once('init', () => {
  game.settings.register(MODULE_ID, MIGRATION_SETTING, {
    scope: 'world',
    config: false,
    type: Number,
    default: 0,
  });
});

Hooks.once('ready', async () => {
  if (game.system?.id !== 'mgt2e' || !game.user?.isGM) return;

  const currentVersion = game.settings.get(MODULE_ID, MIGRATION_SETTING) ?? 0;
  if (currentVersion >= MIGRATION_VERSION) return;

  ui.notifications.info('Migration mgt2e du module en cours...');

  try {
    for (const packName of ITEM_PACKS) {
      await migrateItemPack(packName);
    }

    await game.settings.set(MODULE_ID, MIGRATION_SETTING, MIGRATION_VERSION);
    ui.notifications.info('Migration mgt2e du module terminée.');
  } catch (error) {
    console.error(`${MODULE_ID} | Migration mgt2e impossible`, error);
    ui.notifications.error(`Migration mgt2e inachevee : ${error.message}`);
  }
});

async function migrateItemPack(packName) {
  const collection = `${MODULE_ID}.${packName}`;
  const pack = game.packs.get(collection);
  if (!pack || pack.documentName !== 'Item') return;

  const originalLocked = pack.locked;
  if (originalLocked) {
    await pack.configure({ locked: false });
  }

  try {
    const documents = await pack.getDocuments();
    const folderNames = buildFolderNameMap(pack);
    const failures = [];

    for (const document of documents) {
      const folderId = document.folder?.id ?? document.folder ?? null;
      const update = buildMigratedItemData(document, packName, folderNames.get(folderId));
      if (!update) continue;

      try {
        await document.update(update, { diff: false, recursive: false });
      } catch (error) {
        failures.push(`${document.name}: ${error.message}`);
      }
    }

    if (failures.length) {
      throw new Error(`${packName} (${failures.length} erreurs) — ${failures.slice(0, 5).join(' | ')}`);
    }
  } finally {
    if (originalLocked) {
      await pack.configure({ locked: true });
    }
  }
}

function buildFolderNameMap(pack) {
  const folders = new Map();
  for (const folder of pack.folders ?? []) {
    folders.set(folder.id, folder.name ?? '');
  }
  return folders;
}

function buildMigratedItemData(document, packName, folderName = '') {
  const legacyType = document.type;
  const folderId = document.folder?.id ?? document.folder ?? null;
  const common = {
    name: document.name,
    img: document.img,
    flags: foundry.utils.mergeObject(document.flags ?? {}, {
      [MODULE_ID]: {
        legacyType,
        migratedToMgt2e: MIGRATION_VERSION,
      },
    }),
    folder: folderId,
    sort: document.sort,
    ownership: document.ownership,
  };

  switch (legacyType) {
    case 'armor':
      return {
        ...common,
        type: 'armour',
        system: buildArmourSystem(document),
      };
    case 'weapon':
      return {
        ...common,
        type: 'weapon',
        system: buildWeaponSystem(document),
      };
    case 'equipment':
      return {
        ...common,
        type: isAugmentFolder(folderName) ? 'augment' : 'item',
        system: isAugmentFolder(folderName) ? buildAugmentSystem(document) : buildSimpleItemSystem(document),
      };
    case 'computer':
      return {
        ...common,
        type: 'hardware',
        system: buildHardwareSystem(document),
      };
    case 'item':
      if (document.system?.subType === 'software') {
        return {
          ...common,
          type: 'software',
          system: buildSoftwareSystem(document),
        };
      }
      return {
        ...common,
        type: 'item',
        system: buildSimpleItemSystem(document),
      };
    case 'career':
      return {
        ...common,
        type: 'item',
        system: buildReferenceItemSystem(document, 'Carriere', packName),
      };
    case 'talent':
      return {
        ...common,
        type: 'item',
        system: buildReferenceItemSystem(document, document.system?.subType === 'psionic' ? 'Talent psionique' : 'Competence', packName),
      };
    case 'disease':
      return {
        ...common,
        type: 'item',
        system: buildDiseaseItemSystem(document),
      };
    default:
      return {
        ...common,
        type: 'item',
        system: buildReferenceItemSystem(document, legacyType, packName),
      };
  }
}

function buildWeaponSystem(document) {
  const system = document.system ?? {};
  const traits = normalizeTraits(system.traits);
  const melee = Boolean(system.range?.isMelee);

  return {
    tl: normalizeTl(system.tl),
    weight: toNumber(system.weight),
    cost: toNumber(system.cost),
    notes: traits.notes,
    active: Boolean(system.equipped),
    quantity: toNumber(system.quantity, 1),
    status: system.trash ? 'broken' : null,
    legality: 9,
    weapon: {
      scale: 'traveller',
      range: melee ? 0 : toNumber(system.range?.value),
      minRange: 0,
      damage: normalizeDamage(system.damage),
      magazine: toNumber(system.magazine),
      ammo: toNumber(system.magazine),
      magazineCost: toNumber(system.magazineCost),
      characteristic: melee ? 'STR' : 'DEX',
      skill: inferWeaponSkillFromName(document.name, melee),
      parryBonus: 0,
      damageBonus: melee ? 'STR' : '',
      damageType: 'standard',
      attackBonus: 0,
      traits: traits.names,
    },
    description: formatDescription(system.description),
  };
}

function buildArmourSystem(document) {
  const system = document.system ?? {};
  return {
    tl: normalizeTl(system.tl),
    weight: toNumber(system.weight),
    cost: toNumber(system.cost),
    notes: buildLines([
      system.requireSkillLevel != null ? `Combi requise: ${system.requireSkillLevel}` : '',
    ]),
    active: Boolean(system.equipped),
    quantity: toNumber(system.quantity, 1),
    status: system.trash ? 'broken' : null,
    legality: 9,
    armour: {
      protection: toNumber(String(system.protection ?? '').replace(/[^\d-]/g, '')),
      otherProtection: 0,
      otherTypes: '',
      rad: toNumber(system.radiations),
      archaic: 0,
      skill: toNumber(system.requireSkillLevel) > 0 ? 'vaccsuit' : '',
      duration: 0,
      slots: 0,
      form: 'standard',
      layered: 0,
      ablat: 0,
      powered: Boolean(system.powered) ? 1 : 0,
      psi: 0,
      worn: Boolean(system.equipped) ? 1 : 0,
    },
    description: formatDescription(system.description),
  };
}

function buildSimpleItemSystem(document) {
  const system = document.system ?? {};
  return {
    tl: normalizeTl(system.tl),
    weight: toNumber(system.weight),
    cost: toNumber(system.cost),
    notes: '',
    active: Boolean(system.equipped),
    quantity: toNumber(system.quantity, 1),
    status: system.trash ? 'broken' : null,
    legality: 9,
    description: formatDescription(system.description),
  };
}

function buildAugmentSystem(document) {
  const system = buildSimpleItemSystem(document);
  return system;
}

function buildHardwareSystem(document) {
  const system = document.system ?? {};
  return {
    tl: normalizeTl(system.tl),
    weight: toNumber(system.weight),
    cost: toNumber(system.cost),
    notes: buildLines([
      system.overload ? 'Surcharge: oui' : '',
      system.processing != null ? `Traitement: ${system.processing}` : '',
      system.processingUsed != null ? `Traitement utilise: ${system.processingUsed}` : '',
    ]),
    active: false,
    quantity: toNumber(system.quantity, 1),
    status: system.trash ? 'broken' : null,
    legality: 9,
    hardware: {
      system: 'computer',
      tons: 0,
      power: toNumber(system.processing),
      rating: inferRating(document.name),
      variables: {
        max: 0,
        tl: normalizeTl(system.tl),
        cost: toNumber(system.cost),
      },
    },
    description: formatDescription(system.description),
  };
}

function buildSoftwareSystem(document) {
  const system = document.system ?? {};
  return {
    quantity: toNumber(system.quantity, 1),
    tl: normalizeTl(system.tl),
    software: {
      bandwidth: toNumber(system.software?.bandwidth),
    },
    cost: toNumber(system.cost),
    description: formatDescription(system.description),
  };
}

function buildReferenceItemSystem(document, category, packName) {
  const system = document.system ?? {};
  const isSkillReference = packName === 'competences';
  return {
    tl: normalizeTl(system.tl),
    weight: toNumber(system.weight),
    cost: toNumber(system.cost),
    notes: buildLines([
      isSkillReference ? 'Référence documentaire uniquement — les compétences de jeu utilisent désormais actor.system.skills et la localisation MGT2.Skills.*.' : '',
      category ? `Categorie legacy: ${category}` : '',
      system.subType ? `Sous-type legacy: ${system.subType}` : '',
      system.level != null ? `Niveau legacy: ${system.level}` : '',
      system.assignment ? `Affectations: ${system.assignment}` : '',
    ]),
    active: false,
    quantity: toNumber(system.quantity, 1),
    status: null,
    legality: 9,
      description: isSkillReference
        ? formatDescription([system.description, '<p><strong>Note mgt2e :</strong> cette entrée sert de référence documentaire. Les compétences jouables sont natives à la fiche de personnage `mgt2e`.</p>'].filter(Boolean).join('\n\n'))
        : formatDescription(system.description),
  };
}

function buildDiseaseItemSystem(document) {
  const system = document.system ?? {};
  return {
    tl: '0',
    weight: 0,
    cost: 0,
    notes: buildLines([
      system.subType ? `Sous-type: ${system.subType}` : '',
      system.difficulty ? `Difficulte: ${system.difficulty}` : '',
      system.damage ? `Degats: ${system.damage}` : '',
      system.interval ? `Intervalle: ${system.interval}` : '',
    ]),
    active: false,
    quantity: 1,
    status: null,
    legality: 9,
    description: formatDescription(system.description),
  };
}

function isAugmentFolder(folderName) {
  return /augmentation/i.test(folderName ?? '');
}

function normalizeTl(value) {
  const match = String(value ?? '').match(/(\d+)/);
  return match ? match[1] : '0';
}

function normalizeDamage(value) {
  return String(value ?? '1D6').replace(/d/g, 'D');
}

function toNumber(value, fallback = 0) {
  const parsed = Number.parseInt(String(value ?? ''), 10);
  return Number.isFinite(parsed) ? parsed : fallback;
}

function inferRating(name) {
  const match = String(name ?? '').match(/\/(\d+)/);
  return match ? Number.parseInt(match[1], 10) : 0;
}

function normalizeTraits(traits) {
  if (!Array.isArray(traits) || !traits.length) return { names: '', notes: '' };

  const names = traits
    .map((trait) => trait?.name ?? trait)
    .filter(Boolean)
    .join(', ');
  const notes = traits
    .filter((trait) => trait?.description)
    .map((trait) => `${trait.name}: ${trait.description}`)
    .join('\n');

  return { names, notes };
}

function formatDescription(value) {
  const text = String(value ?? '').trim();
  if (!text) return '';
  if (text.includes('<')) return text;

  const paragraphs = text
    .split(/\n{2,}/)
    .map((part) => part.trim())
    .filter(Boolean)
    .map((part) => `<p>${part.replace(/\n/g, '<br>')}</p>`);

  return paragraphs.join('');
}

function buildLines(lines) {
  return lines.filter(Boolean).join('\n');
}
