/**
 * Galaxy Strike Online — Mission System (GDD §8.3, §15)
 * Fleet Missions: Attack, Mine, Patrol, Transport
 * Reward formula: base_reward = difficulty × 100 × (1 + level × 0.02)
 */

const MISSION_TYPES = {
  patrol: {
    label: 'Patrol', icon: '🛡',
    desc: 'Patrol a sector — passive XP and chance of intercepting pirates.',
    baseDurationMin: 3, baseDurationMax: 5, // minutes
    rewards: (level) => ({ xp: Math.floor(50 * (1 + level * 0.02)), credits: Math.floor(30 * (1 + level * 0.02)) }),
    riskFactor: 0.05,
  },
  mine: {
    label: 'Mining Run', icon: '⛏',
    desc: 'Send fleet to mine asteroids in a sector. Returns Metal and Gas.',
    baseDurationMin: 5, baseDurationMax: 10,
    rewards: (level) => ({
      xp: Math.floor(30 * (1 + level * 0.02)),
      metal: Math.floor(200 * (1 + level * 0.05)),
      gas: Math.floor(80 * (1 + level * 0.05)),
    }),
    riskFactor: 0.02,
  },
  transport: {
    label: 'Trade Run', icon: '🚚',
    desc: 'Transport cargo between sectors for credits.',
    baseDurationMin: 8, baseDurationMax: 15,
    rewards: (level) => ({ xp: Math.floor(40 * (1 + level * 0.02)), credits: Math.floor(150 * (1 + level * 0.03)) }),
    riskFactor: 0.01,
  },
  attack: {
    label: 'Raid', icon: '⚔',
    desc: 'Raid a pirate outpost. High rewards, high risk.',
    baseDurationMin: 10, baseDurationMax: 20,
    rewards: (level) => ({
      xp: Math.floor(120 * (1 + level * 0.02)),
      credits: Math.floor(200 * (1 + level * 0.03)),
      loot: true,
    }),
    riskFactor: 0.25,
  },
  explore: {
    label: 'Explore', icon: '🔭',
    desc: 'Explore an unknown sector for intel and resources.',
    baseDurationMin: 6, baseDurationMax: 12,
    rewards: (level) => ({ xp: Math.floor(80 * (1 + level * 0.02)), darkMatter: Math.floor(2 + Math.floor(level / 5)) }),
    riskFactor: 0.10,
  },
};

// Random loot table for raid missions
const RAID_LOOT = ['repair_kit','warp_token','shield_charge','metal_cache','crystal_shard'];

class MissionSystem {
  constructor() {
    this.MISSION_TYPES = MISSION_TYPES;
  }

  /** Start a fleet mission */
  startMission(playerData, { missionType, fleetShipIds = [] }) {
    if (!MISSION_TYPES[missionType]) throw new Error('Unknown mission type: ' + missionType);
    const type = MISSION_TYPES[missionType];
    const level = playerData.stats?.level || 1;

    // Need at least one ship
    const ships = (playerData.inventory || []).filter(i => i.type === 'ship' && fleetShipIds.includes(i.id));
    if (ships.length === 0) throw new Error('Select at least one ship for the mission.');

    // Ships can't be on multiple missions
    const activeMissions = playerData.fleetMissions || [];
    const busyShips = new Set(activeMissions.flatMap(m => m.shipIds || []));
    const conflicting = fleetShipIds.filter(id => busyShips.has(id));
    if (conflicting.length > 0) throw new Error('Some ships are already on a mission.');

    const durationMin = type.baseDurationMin + Math.random() * (type.baseDurationMax - type.baseDurationMin);
    const durationMs = Math.round(durationMin * 60 * 1000);
    const now = Date.now();

    const mission = {
      id: 'mission_' + now + '_' + Math.random().toString(36).slice(2, 7),
      type: missionType,
      label: type.label,
      icon: type.icon,
      shipIds: fleetShipIds,
      startedAt: now,
      completesAt: now + durationMs,
      level,
      status: 'active',
    };

    playerData.fleetMissions = [...activeMissions, mission];
    return mission;
  }

  /** Collect completed missions, apply rewards, return results */
  collectMissions(playerData, resourceSystem) {
    const now = Date.now();
    const active = playerData.fleetMissions || [];
    const done = active.filter(m => m.completesAt <= now && m.status === 'active');
    const remaining = active.filter(m => m.completesAt > now || m.status !== 'active');
    playerData.fleetMissions = remaining;

    const results = [];
    for (const mission of done) {
      const type = MISSION_TYPES[mission.type];
      if (!type) continue;
      const rewards = type.rewards(mission.level || 1);

      // Risk roll — small chance mission fails
      const failed = Math.random() < type.riskFactor;
      if (failed) {
        results.push({ mission, success: false, message: `Mission failed! Fleet was intercepted.` });
        continue;
      }

      // Apply XP + credits
      if (rewards.xp)      playerData.stats.experience = (playerData.stats.experience || 0) + rewards.xp;
      if (rewards.credits) playerData.stats.credits    = (playerData.stats.credits    || 0) + rewards.credits;

      // Apply resource rewards
      const resGains = {};
      if (rewards.metal)      resGains.metal      = rewards.metal;
      if (rewards.gas)        resGains.gas        = rewards.gas;
      if (rewards.crystal)    resGains.crystal    = rewards.crystal;
      if (rewards.darkMatter) resGains.darkMatter = rewards.darkMatter;
      if (Object.keys(resGains).length > 0 && resourceSystem) {
        resourceSystem.initResources(playerData);
        resourceSystem.add(playerData, resGains);
      }

      // Random loot for raids
      const lootItem = rewards.loot ? RAID_LOOT[Math.floor(Math.random() * RAID_LOOT.length)] : null;
      if (lootItem) {
        if (!playerData.inventory) playerData.inventory = [];
        playerData.inventory.push({ id: lootItem + '_' + Date.now(), type: 'consumable', name: lootItem.replace('_', ' '), icon: '📦', description: 'Mission loot' });
      }

      results.push({ mission, success: true, rewards, lootItem, message: `${type.label} completed successfully!` });
    }
    return results;
  }

  /** Recall a mission early (no rewards, ships return instantly) */
  recallMission(playerData, missionId) {
    const idx = (playerData.fleetMissions || []).findIndex(m => m.id === missionId);
    if (idx < 0) throw new Error('Mission not found');
    playerData.fleetMissions.splice(idx, 1);
  }

  getMissionTypes() { return MISSION_TYPES; }

  getMissionsForPlayer(playerData) {
    return {
      active: (playerData.fleetMissions || []).filter(m => m.status === 'active'),
      types: MISSION_TYPES,
    };
  }
}

module.exports = MissionSystem;

// ── Faction NPC Missions (GDD §15.1) ─────────────────────────────────────
const fs = require('fs');
const path = require('path');

let FACTION_MISSIONS = [];
try {
  const p = path.join(__dirname, '../data/gso/missions/faction_missions.json');
  FACTION_MISSIONS = JSON.parse(fs.readFileSync(p, 'utf8')).missions;
} catch(e) { /* data not loaded */ }

MissionSystem.prototype.getAvailableFactionMissions = function(playerData) {
  const level = playerData.stats?.level || 1;
  const rep   = playerData.reputation || {};
  return FACTION_MISSIONS.filter(m => {
    if (m.minLevel > level) return false;
    if (m.requires_rep !== undefined) {
      const fRep = rep[m.faction] || 0;
      if (fRep < m.requires_rep) return false;
    }
    return true;
  });
};

MissionSystem.prototype.startFactionMission = function(playerData, missionId) {
  const mission = FACTION_MISSIONS.find(m => m.id === missionId);
  if (!mission) throw new Error('Faction mission not found: ' + missionId);
  const level = playerData.stats?.level || 1;
  if (mission.minLevel > level) throw new Error(`Requires Commander Level ${mission.minLevel}`);

  const now = Date.now();
  const job = {
    id:          'fmission_' + now,
    type:        'faction',
    factionMissionId: mission.id,
    label:       mission.name,
    icon:        '📋',
    faction:     mission.faction,
    startedAt:   now,
    completesAt: now + mission.duration * 1000,
    status:      'active',
    rewards:     mission.rewards,
  };
  playerData.fleetMissions = [...(playerData.fleetMissions||[]), job];
  return job;
};

MissionSystem.prototype.collectFactionMissions = function(playerData, resourceSystem, reputationSystem) {
  const now = Date.now();
  const done = (playerData.fleetMissions||[]).filter(m => m.type==='faction' && m.completesAt <= now && m.status==='active');
  playerData.fleetMissions = (playerData.fleetMissions||[]).filter(m => !(m.type==='faction' && m.completesAt <= now && m.status==='active'));

  const results = [];
  for (const job of done) {
    const r = job.rewards || {};
    if (r.credits)     playerData.stats.credits    = (playerData.stats.credits||0)    + r.credits;
    if (r.xp)          playerData.addExperience?.(r.xp);
    if (r.metal || r.gas || r.crystal || r.darkMatter) {
      resourceSystem?.initResources(playerData);
      const gains = {};
      if (r.metal)      gains.metal      = r.metal;
      if (r.gas)        gains.gas        = r.gas;
      if (r.crystal)    gains.crystal    = r.crystal;
      if (r.darkMatter) gains.darkMatter = r.darkMatter;
      resourceSystem?.add(playerData, gains);
    }
    if (r.reputation && reputationSystem) {
      for (const [factionId, delta] of Object.entries(r.reputation)) {
        reputationSystem.adjustReputation(playerData, factionId, delta);
      }
    }
    results.push({ mission: job, success: true, rewards: r });
  }
  return results;
};
