/**
 * Galaxy Strike Online - Galaxy System
 * Procedurally generates and manages sectors
 */
class GalaxySystem {
  constructor() {
    this.GRID_W = 30;
    this.GRID_H = 20;
    this.TYPES  = ['empty','empty','empty','asteroid','asteroid','trade_hub','npc_territory','ruins','void_rift'];
    this._sectors = null;
  }

  /** Lazy-generate the galaxy grid once */
  getSectors() {
    if (!this._sectors) this._sectors = this._generate();
    return this._sectors;
  }

  _generate() {
    const sectors = {};
    for (let y = 0; y < this.GRID_H; y++) {
      for (let x = 0; x < this.GRID_W; x++) {
        const id = `${x}_${y}`;
        const distFromCenter = Math.hypot(x - 15, y - 10) / 18;
        // Richer regions further from core
        const typeRoll = Math.random();
        let type = 'empty';
        if (typeRoll > 0.70) type = 'asteroid';
        if (typeRoll > 0.88) type = 'npc_territory';
        if (typeRoll > 0.94) type = 'trade_hub';
        if (typeRoll > 0.97 && distFromCenter > 0.4) type = 'ruins';
        if (typeRoll > 0.99 && distFromCenter > 0.6) type = 'void_rift';

        const richness = Math.random();
        sectors[id] = {
          id, x, y, type,
          name: this._sectorName(x, y),
          threat: Math.min(10, Math.floor(distFromCenter * 10 + Math.random() * 3)),
          richness: type === 'asteroid' ? (0.3 + richness * 0.7) : 0,
          owner: null,
          explored: false,
        };
      }
    }
    // Always make start sector safe
    sectors['15_10'] = { id:'15_10', x:15, y:10, type:'trade_hub', name:'New Haven', threat:0, richness:0, owner:null, explored:true };
    return sectors;
  }

  _sectorName(x, y) {
    const prefixes = ['Alpha','Beta','Gamma','Delta','Sigma','Tau','Zeta','Omega','Nova','Vega','Lyra','Cygni'];
    const suffixes = ['Prime','Station','Reach','Deep','Expanse','Crossing','Rift','Gate','Void','Fields'];
    const seed = (x * 31 + y * 17) % (prefixes.length * suffixes.length);
    return prefixes[seed % prefixes.length] + ' ' + suffixes[Math.floor(seed / prefixes.length) % suffixes.length];
  }

  /** Returns the sector or null */
  getSector(id) {
    return this.getSectors()[id] || null;
  }

  /** Mark a sector explored by a player */
  exploreSector(sectorId, playerData) {
    const sector = this.getSector(sectorId);
    if (!sector) throw new Error('Sector not found');
    const explored = playerData.exploredSectors || [];
    if (!explored.includes(sectorId)) {
      explored.push(sectorId);
      playerData.exploredSectors = explored;
    }
    return sector;
  }

  /** Return list of sectors visible to player (explored + adjacent) */
  getVisibleSectors(playerData) {
    const explored = new Set(playerData.exploredSectors || ['15_10']);
    const visible = new Set(explored);
    // Reveal adjacent sectors to all explored
    for (const id of explored) {
      const [x, y] = id.split('_').map(Number);
      for (const [dx, dy] of [[-1,0],[1,0],[0,-1],[0,1]]) {
        const nid = `${x+dx}_${y+dy}`;
        if (this.getSector(nid)) visible.add(nid);
      }
    }
    const all = this.getSectors();
    return Array.from(visible).map(id => {
      const s = { ...all[id] };
      s.explored = explored.has(id);
      if (!s.explored) {
        // Fog: hide details of unexplored but adjacent sectors
        s.name = '???';
        s.richness = 0;
        s.owner = null;
      }
      return s;
    });
  }

  /** Player claims/sets base in a sector */
  claimSector(sectorId, playerData) {
    const sector = this.getSector(sectorId);
    if (!sector) throw new Error('Sector not found');
    if (sector.type === 'void_rift') throw new Error('Cannot claim Void Rift sectors');
    sector.owner = playerData.userId;
    this.exploreSector(sectorId, playerData);
    playerData.homeSector = sectorId;
    return sector;
  }
}

module.exports = GalaxySystem;
