/* FutureMedia — app.js
   Frontend logic: view routing, form handling, calls to /analyze and /download
   on the local Node server. Falls back to a local mock if the server isn't
   running, so the UI is fully explorable without a backend. */

(() => {
  const API_BASE = 'http://localhost:3000';

  // ---------- state ----------
  const state = {
    lastResult: null,
    history: JSON.parse(localStorage.getItem('fm_history') || '[]'),
  };

  // ---------- utilities ----------
  const $ = (sel) => document.querySelector(sel);
  const $$ = (sel) => document.querySelectorAll(sel);

  function showToast(msg) {
    const toast = $('#toast');
    toast.textContent = msg;
    toast.classList.add('is-visible');
    clearTimeout(showToast._t);
    showToast._t = setTimeout(() => toast.classList.remove('is-visible'), 2600);
  }

  function detectPlatform(url) {
    const patterns = [
      { name: 'TikTok', test: /tiktok\.com/i },
      { name: 'YouTube', test: /youtube\.com|youtu\.be/i },
      { name: 'Instagram', test: /instagram\.com/i },
      { name: 'Twitter / X', test: /twitter\.com|x\.com/i },
      { name: 'Facebook', test: /facebook\.com|fb\.watch/i },
    ];
    const match = patterns.find((p) => p.test.test(url));
    return match ? match.name : null;
  }

  function formatDuration(sec) {
    const m = Math.floor(sec / 60).toString().padStart(2, '0');
    const s = Math.floor(sec % 60).toString().padStart(2, '0');
    return `${m}:${s}`;
  }

  // ---------- view routing ----------
  function setView(name) {
    $$('.view').forEach((v) => v.classList.remove('is-active'));
    $(`#view-${name}`).classList.add('is-active');
    $$('.rail-btn[data-view]').forEach((b) => b.classList.toggle('is-active', b.dataset.view === name));
  }

  $$('.rail-btn[data-view]').forEach((btn) => {
    btn.addEventListener('click', () => setView(btn.dataset.view));
  });

  // ---------- segmented controls ----------
  function wireSegmented(container) {
    container.querySelectorAll('.seg-btn').forEach((btn) => {
      btn.addEventListener('click', () => {
        container.querySelectorAll('.seg-btn').forEach((b) => b.classList.remove('is-active'));
        btn.classList.add('is-active');
      });
    });
  }
  wireSegmented($('#typeSegmented'));
  wireSegmented($('#themeSegmented'));

  // ---------- theme ----------
  function applyTheme(theme) {
    document.body.classList.toggle('theme-light', theme === 'light');
    localStorage.setItem('fm_theme', theme);
    $('#themeToggle i').className = theme === 'light' ? 'fa-solid fa-sun' : 'fa-solid fa-moon';
    $('#themeSegmented').querySelectorAll('.seg-btn').forEach((b) => {
      b.classList.toggle('is-active', b.dataset.value === theme);
    });
  }

  $('#themeToggle').addEventListener('click', () => {
    const next = document.body.classList.contains('theme-light') ? 'dark' : 'light';
    applyTheme(next);
  });

  $('#themeSegmented').addEventListener('click', (e) => {
    const btn = e.target.closest('.seg-btn');
    if (btn) applyTheme(btn.dataset.value);
  });

  // ---------- language ----------
  $('#langSelect').addEventListener('change', (e) => I18N.load(e.target.value));

  // ---------- URL input -> platform chip ----------
  $('#urlInput').addEventListener('input', (e) => {
    const chip = $('#platformChip');
    const platform = detectPlatform(e.target.value.trim());
    if (platform) {
      chip.textContent = platform;
      chip.hidden = false;
    } else {
      chip.hidden = true;
    }
    // reset downstream cards if the link changes
    $('#resultCard').hidden = true;
    $('#progressCard').hidden = true;
  });

  // ---------- analyze ----------
  async function analyze(url) {
    try {
      const res = await fetch(`${API_BASE}/analyze`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url }),
      });
      if (!res.ok) throw new Error('bad response');
      return await res.json();
    } catch (e) {
      // No local server reachable — fall back to a mock so the UI stays usable.
      return mockAnalyze(url);
    }
  }

  function mockAnalyze(url) {
    const platform = detectPlatform(url) || 'Web';
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve({
          title: 'Video.mp4',
          platform,
          duration: 87,
          size: '23 MB',
          quality: '1080p',
          qualities: ['1080p', '720p', '480p'],
        });
      }, 1100);
    });
  }

  $('#analyzeBtn').addEventListener('click', async () => {
    const url = $('#urlInput').value.trim();
    if (!url) {
      showToast(I18N.t('error.invalidUrl'));
      return;
    }

    const btn = $('#analyzeBtn');
    btn.classList.add('is-loading');
    btn.disabled = true;
    $('#resultCard').hidden = true;
    $('#progressCard').hidden = true;

    try {
      const data = await analyze(url);
      state.lastResult = { ...data, url };

      $('#resultTitle').textContent = data.title;
      $('#resultPlatform').textContent = data.platform;
      $('#resultDuration').textContent = formatDuration(data.duration);
      $('#resultSize').textContent = data.size;
      $('#resultQuality').textContent = data.quality;
      $('#resultCard').hidden = false;
    } catch (e) {
      showToast(I18N.t('error.analyzeFailed'));
    } finally {
      btn.classList.remove('is-loading');
      btn.disabled = false;
    }
  });

  // ---------- download ----------
  const RING_CIRCUMFERENCE = 2 * Math.PI * 52; // r=52

  function setRingProgress(pct) {
    const offset = RING_CIRCUMFERENCE - (pct / 100) * RING_CIRCUMFERENCE;
    $('#progressRing').style.strokeDashoffset = offset;
    $('#progressPercent').textContent = `${Math.round(pct)}%`;
  }

  /** Trigger an actual browser "Save As" for a Blob. */
  function saveBlob(blob, filename) {
    const objectUrl = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = objectUrl;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    a.remove();
    setTimeout(() => URL.revokeObjectURL(objectUrl), 4000);
  }

  /** Trigger a browser download for a same-origin/server URL (streams straight to disk). */
  function saveFromUrl(url, filename) {
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    a.remove();
  }

  async function runDownload() {
    const type = $('#typeSegmented .is-active').dataset.value;
    const quality = $('#qualitySelect').value;
    const result = state.lastResult;
    if (!result) return;

    $('#progressCard').hidden = false;
    setRingProgress(0);

    let usedServer = false;
    let savedFilename = null;

    try {
      const res = await fetch(`${API_BASE}/download`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url: result.url, quality, type }),
      });

      if (res.ok && res.body) {
        usedServer = true;
        const reader = res.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';

        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          buffer += decoder.decode(value, { stream: true });
          const lines = buffer.split('\n');
          buffer = lines.pop();
          for (const line of lines) {
            if (!line.trim()) continue;
            const msg = JSON.parse(line);
            if (msg.status === 'progress') {
              setRingProgress(msg.percent || 0);
              $('#progressSpeed').textContent = msg.speed || '—';
              $('#progressRemaining').textContent = msg.eta || '—';
            } else if (msg.status === 'done') {
              setRingProgress(100);
              savedFilename = msg.filename;
              saveFromUrl(`${API_BASE}${msg.fileUrl}`, msg.filename);
            } else if (msg.status === 'error') {
              throw new Error(msg.message);
            }
          }
        }
      } else {
        usedServer = false;
      }
    } catch (e) {
      usedServer = false;
    }

    if (!usedServer) {
      // No backend reachable — still hand the user a real file (demo content)
      // so the download button always produces something on disk.
      await simulateProgress();
      const ext = type === 'audio' ? 'mp3' : 'mp4';
      const demoName = `${result.title.replace(/\.[a-z0-9]+$/i, '')}.${ext}`;
      const demoContent = `FutureMedia demo file\nURL: ${result.url}\nType: ${type}\nQuality: ${quality}\nGenerated: ${new Date().toISOString()}\n\n(Backend not running — this is a placeholder, not real media.)`;
      saveBlob(new Blob([demoContent], { type: 'text/plain' }), demoName);
      savedFilename = demoName;
    }

    const entry = {
      id: Date.now(),
      title: result.title,
      platform: result.platform,
      type,
      quality,
      date: new Date().toISOString(),
    };
    state.history.unshift(entry);
    localStorage.setItem('fm_history', JSON.stringify(state.history));
    renderHistory();

    showToast(usedServer ? `${savedFilename} — ${I18N.t('result.download')} ✓` : `${savedFilename} (demo) — ${I18N.t('result.download')} ✓`);
  }

  function simulateProgress() {
    return new Promise((resolve) => {
      let pct = 0;
      const speedEl = $('#progressSpeed');
      const remEl = $('#progressRemaining');
      const timer = setInterval(() => {
        pct += Math.random() * 14 + 4;
        if (pct >= 100) {
          pct = 100;
          setRingProgress(pct);
          speedEl.textContent = '0 MB/s';
          remEl.textContent = '00:00';
          clearInterval(timer);
          setTimeout(resolve, 350);
          return;
        }
        setRingProgress(pct);
        speedEl.textContent = `${(Math.random() * 10 + 6).toFixed(1)} MB/s`;
        remEl.textContent = formatDuration(Math.max(0, Math.round((100 - pct) / 8)));
      }, 260);
    });
  }

  $('#downloadBtn').addEventListener('click', runDownload);

  // ---------- history ----------
  function renderHistory() {
    const list = $('#historyList');
    if (!state.history.length) {
      list.innerHTML = `<li class="history-empty" data-i18n="history.empty">${I18N.t('history.empty')}</li>`;
      return;
    }
    list.innerHTML = state.history.map((item) => `
      <li class="history-item" data-id="${item.id}">
        <div class="history-thumb"><i class="fa-solid ${item.type === 'audio' ? 'fa-music' : 'fa-film'}"></i></div>
        <div class="history-info">
          <div class="history-title">${item.title}</div>
          <div class="history-sub">${item.platform} · ${item.quality} · ${new Date(item.date).toLocaleString()}</div>
        </div>
        <div class="history-actions">
          <button class="icon-btn" data-action="redownload" title="${I18N.t('history.redownload')}"><i class="fa-solid fa-rotate-right"></i></button>
          <button class="icon-btn" data-action="delete" title="${I18N.t('history.delete')}"><i class="fa-solid fa-trash"></i></button>
        </div>
      </li>
    `).join('');
  }

  $('#historyList').addEventListener('click', (e) => {
    const btn = e.target.closest('.icon-btn');
    if (!btn) return;
    const li = e.target.closest('.history-item');
    const id = Number(li.dataset.id);
    if (btn.dataset.action === 'delete') {
      state.history = state.history.filter((h) => h.id !== id);
      localStorage.setItem('fm_history', JSON.stringify(state.history));
      renderHistory();
    } else if (btn.dataset.action === 'redownload') {
      showToast(I18N.t('form.analyzing'));
    }
  });

  // ---------- init ----------
  async function init() {
    const savedLang = localStorage.getItem('fm_lang') || 'tr';
    $('#langSelect').value = savedLang;
    await I18N.load(savedLang);

    const savedTheme = localStorage.getItem('fm_theme') || 'dark';
    applyTheme(savedTheme);

    renderHistory();
  }

  init();
})();
