import { searchWorlds, calcParsecs } from './travellerMapApi.js';

const MODULE_ID = 'mgt2-compendium-amiral-denisov';
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;

function cleanSectorName(sector) {
  return sector?.replace(/\s*\([^)]*\)\s*$/, '').trim() || sector;
}

function worldCoord(sx, sy, hx, hy) {
  return { x: (sx - 0) * 32 + (hx - 1), y: (sy - 0) * 40 + (hy - 40) };
}

export class TravelDialog extends HandlebarsApplicationMixin(ApplicationV2) {
  static DEFAULT_OPTIONS = {
    id: 'mgt2-travel-dialog',
    classes: ['mgt2-travel-dialog'],
    position: { width: 600, height: 500 },
    window: { icon: 'fas fa-route', title: 'Planificateur de voyage', resizable: true, controls: [] },
  };

  static PARTS = {
    main: {
      template: `modules/${MODULE_ID}/templates/travel-dialog.hbs`,
    },
  };

  constructor() {
    super();
    this._fromWorld = null;
    this._toWorld = null;
    this._lastWorlds = null;
    this._lastSegments = null;
  }

  _onRender(context, options) {
    this._wireSearch('from');
    this._wireSearch('to');
    this.element?.querySelector('[data-action="calculate"]')?.addEventListener('click', () => {
      this._calculateRoute();
    });
    this.element?.querySelector('[data-action="create-journal"]')?.addEventListener('click', () => {
      this._createJournal();
    });
  }

  _wireSearch(prefix) {
    const input = this.element.querySelector(`[name="travel-${prefix}"]`);
    const results = this.element.querySelector(`.travel-${prefix}-results`);
    if (!input || !results) return;

    let timeout = null;
    input.addEventListener('input', () => {
      clearTimeout(timeout);
      const q = input.value.trim();
      if (q.length < 2) { results.innerHTML = ''; return; }
      timeout = setTimeout(async () => {
        const worlds = await searchWorlds(q);
        if (!worlds?.length) {
          results.innerHTML = '<li class="no-result">Aucun résultat</li>';
          return;
        }
        results.innerHTML = worlds.slice(0, 10).map(w =>
          `<li data-sector="${w.sector}" data-hex="${w.hex}" data-name="${w.name}">
            <span class="world-name">${w.name}</span>
            <span class="world-sector">${w.sector}</span>
            <span class="world-hex">${w.hex}</span>
          </li>`
        ).join('');
      }, 300);
    });

    results.addEventListener('click', (e) => {
      const li = e.target.closest('[data-sector]');
      if (!li) return;
      const data = { sector: li.dataset.sector, hex: li.dataset.hex, name: li.dataset.name };
      if (prefix === 'from') this._fromWorld = data;
      else this._toWorld = data;
      input.value = `${data.name} (${data.sector} ${data.hex})`;
      results.innerHTML = '';
    });

    input.addEventListener('blur', () => {
      setTimeout(() => { results.innerHTML = ''; }, 200);
    });
  }

  async _calculateRoute() {
    if (!this._fromWorld || !this._toWorld) {
      ui.notifications.warn('Veuillez sélectionner un monde de départ et un monde d\'arrivée');
      return;
    }

    const jumpEl = this.element.querySelector('[name="travel-jump"]');
    const jump = parseInt(jumpEl?.value, 10) || 2;

    const resultsEl = this.element.querySelector('.travel-results');
    if (!resultsEl) return;

    resultsEl.innerHTML = '<div class="travel-loading"><i class="fas fa-spinner fa-spin"></i> Calcul de l\'itinéraire…</div>';

    const startSector = cleanSectorName(this._fromWorld.sector);
    const endSector = cleanSectorName(this._toWorld.sector);
    const startLoc = `${startSector} ${this._fromWorld.hex}`;
    const endLoc = `${endSector} ${this._toWorld.hex}`;

    try {
      const resp = await fetch(
        `https://travellermap.com/api/route?start=${encodeURIComponent(startLoc)}&end=${encodeURIComponent(endLoc)}&jump=${jump}`
      );

      if (!resp.ok) {
        if (resp.status === 404) {
          const text = await resp.text().catch(() => 'Aucun itinéraire trouvé');
          resultsEl.innerHTML = `<div class="travel-error">${this._escapeHtml(text)}</div>`;
        } else {
          resultsEl.innerHTML = `<div class="travel-error">Erreur API (${resp.status})</div>`;
        }
        return;
      }

      const data = await resp.json();
      if (!Array.isArray(data) || data.length < 2) {
        resultsEl.innerHTML = '<div class="travel-error">Aucun itinéraire trouvé</div>';
        return;
      }
      this._displayRoute(data, resultsEl);
    } catch (err) {
      console.error('TravelDialog | Erreur:', err);
      resultsEl.innerHTML = `<div class="travel-error">Erreur : ${this._escapeHtml(err.message)}</div>`;
    }
  }

  _displayRoute(worlds, resultsEl) {
    this._lastWorlds = worlds;
    const segments = [];
    let totalParsecs = 0;
    for (let i = 0; i < worlds.length - 1; i++) {
      const a = worlds[i];
      const b = worlds[i + 1];
      const fromC = worldCoord(a.SectorX, a.SectorY, a.HexX, a.HexY);
      const toC = worldCoord(b.SectorX, b.SectorY, b.HexX, b.HexY);
      const dist = calcParsecs(fromC, toC);
      totalParsecs += dist;
      segments.push({ from: a, to: b, dist });
    }
    this._lastSegments = segments;

    let html = `<div class="travel-route-summary">
      <i class="fas fa-route"></i>
      <strong>${segments.length}</strong> saut${segments.length > 1 ? 's' : ''}
      · <strong>${totalParsecs}</strong> parsecs
    </div>`;

    html += `<div class="travel-route-duration">
      <i class="fas fa-clock"></i> Durée estimée : <strong>${segments.length}</strong> semaine${segments.length > 1 ? 's' : ''}
    </div>`;

    html += '<ol class="travel-jump-list">';
    segments.forEach((seg) => {
      const f = seg.from;
      const t = seg.to;
      html += `<li>
        <div class="jump-segment">
          <div class="jump-world jump-from">
            <span class="jump-world-name">${f.Name || '?'}</span>
            <span class="jump-world-detail">${f.Sector} ${f.Hex || ''}</span>
          </div>
          <div class="jump-arrow"><i class="fas fa-long-arrow-alt-right"></i></div>
          <div class="jump-world jump-to">
            <span class="jump-world-name">${t.Name || '?'}</span>
            <span class="jump-world-detail">${t.Sector} ${t.Hex || ''}</span>
          </div>
          <div class="jump-distance">Saut-${seg.dist}</div>
        </div>
      </li>`;
    });
    html += '</ol>';

    resultsEl.innerHTML = html;

    const journalBtn = this.element?.querySelector('.travel-journal-actions');
    if (journalBtn) journalBtn.style.display = 'block';
  }

  async _createJournal() {
    const worlds = this._lastWorlds;
    const segments = this._lastSegments;
    if (!worlds?.length || !segments?.length) {
      ui.notifications.warn('Calculez d\'abord un itinéraire');
      return;
    }

    const from = worlds[0];
    const to = worlds[worlds.length - 1];
    const totalParsecs = segments.reduce((s, seg) => s + seg.dist, 0);
    const totalJumps = segments.length;
    const jumpRating = this.element?.querySelector('[name="travel-jump"]')?.value || '?';

    const lines = [];
    lines.push(`<h2>Journal de voyage</h2>`);
    lines.push(`<p><strong>Départ :</strong> ${this._worldLink(from)}</p>`);
    lines.push(`<p><strong>Destination :</strong> ${this._worldLink(to)}</p>`);
    lines.push(`<p><strong>Moteur :</strong> J-${jumpRating}</p>`);
    lines.push(`<hr>`);

    lines.push(`<h3>Itinéraire (${totalJumps} saut${totalJumps > 1 ? 's' : ''}, ${totalParsecs} pc)</h3>`);
    lines.push(`<table><thead><tr><th>#</th><th>Départ</th><th>→</th><th>Arrivée</th><th>Distance</th></tr></thead><tbody>`);
    segments.forEach((seg, i) => {
      const f = seg.from;
      const t = seg.to;
      lines.push(`<tr>
        <td>${i + 1}</td>
        <td>${this._worldLink(f)}</td>
        <td>→</td>
        <td>${this._worldLink(t)}</td>
        <td>${seg.dist} pc</td>
      </tr>`);
    });
    lines.push(`</tbody></table>`);

    lines.push(`<hr>`);
    lines.push(`<h3>Mondes visités</h3>`);
    lines.push(`<ul>`);
    const seen = new Set();
    for (const w of worlds) {
      const key = `${w.Sector}|${w.Hex}`;
      if (seen.has(key)) continue;
      seen.add(key);
      lines.push(`<li>${this._worldLink(w)}${w.UWP ? ` — UWP: ${w.UWP}` : ''}</li>`);
    }
    lines.push(`</ul>`);

    const content = lines.join('\n');

    try {
      const journal = await JournalEntry.create({
        name: `Voyage : ${from.Name || '?'} → ${to.Name || '?'}`,
        pages: [{
          name: 'Itinéraire',
          type: 'text',
          text: { content, format: 2 },
        }],
      });

      if (journal) {
        ui.notifications.info(`Journal créé : ${journal.name}`);
        journal.sheet?.render(true);
      }
    } catch (err) {
      console.error('TravelDialog | Erreur création journal:', err);
      ui.notifications.error('Erreur lors de la création du journal');
    }
  }

  _worldLink(w) {
    const name = w.Name || '?';
    const sector = w.Sector || '';
    const hex = w.Hex || '';
    return `<a class="mgt2-world-link" data-sector="${this._escapeAttr(sector)}" data-hex="${this._escapeAttr(hex)}">${name}</a> <em>(${sector} ${hex})</em>`;
  }

  _escapeAttr(str) {
    if (!str) return '';
    return str.replace(/"/g, '&quot;').replace(/&/g, '&amp;');
  }

  _escapeHtml(str) {
    if (!str) return '';
    const d = document.createElement('div');
    d.textContent = str;
    return d.innerHTML;
  }
}
