'use strict';

const https = require('node:https');
const path = require('node:path');
const { existsSync, readJsonSync, writeJsonSync, ensureDirSync } = require('fs-extra');
const kleur = require('kleur');
const pkg = require('../../package.json');
const ui = require('./ui');
const { CONFIG_PATH } = require('./license');

const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 horas

// ── Helpers de config ────────────────────────────────────────────────────────

function readConfig() {
  if (!existsSync(CONFIG_PATH)) return {};
  try { return readJsonSync(CONFIG_PATH); } catch { return {}; }
}

function writeConfig(config) {
  ensureDirSync(path.dirname(CONFIG_PATH));
  writeJsonSync(CONFIG_PATH, config, { spaces: 2 });
}

// ── Comparação semver mínima (sem deps externas) ─────────────────────────────

function isNewer(remote, local) {
  const parse = (v) => String(v).replace(/^v/, '').split('.').map(Number);
  const [rMaj, rMin, rPat] = parse(remote);
  const [lMaj, lMin, lPat] = parse(local);
  if (rMaj !== lMaj) return rMaj > lMaj;
  if (rMin !== lMin) return rMin > lMin;
  return rPat > lPat;
}

// ── Fetch assíncrono (dispara em background) ─────────────────────────────────

function fetchLatestVersion() {
  return new Promise((resolve) => {
    const req = https.get(
      'https://registry.npmjs.org/kasy-cli/latest',
      { timeout: 3000 },
      (res) => {
        let data = '';
        res.on('data', (chunk) => { data += chunk; });
        res.on('end', () => {
          try { resolve(JSON.parse(data).version ?? null); }
          catch { resolve(null); }
        });
      }
    );
    req.on('error', () => resolve(null));
    req.on('timeout', () => { req.destroy(); resolve(null); });
  });
}

// ── Função principal ─────────────────────────────────────────────────────────

/**
 * Mostra aviso de atualização (baseado no cache da última verificação — zero latência).
 * Dispara refresh do cache em background se já passaram 24h.
 * Nunca lança erro — falha silenciosa em qualquer cenário.
 */
async function checkForUpdates() {
  try {
    const config = readConfig();
    const cache = config.updateCheck || {};

    // Exibe aviso baseado no cache — não espera rede
    if (cache.latestVersion && isNewer(cache.latestVersion, pkg.version)) {
      console.log(
        '\n' +
        kleur.bgYellow().black(' UPDATE ') + '  ' +
        kleur.bold(`v${cache.latestVersion} disponível`) +
        kleur.dim(`  (você tem v${pkg.version})`) +
        '\n' +
        kleur.dim('         ') + kleur.cyan('kasy upgrade') +
        '\n'
      );
    }

    // Atualiza cache em background a cada 24h — não bloqueia o CLI
    const now = Date.now();
    if (!cache.checkedAt || now - cache.checkedAt > CHECK_INTERVAL_MS) {
      fetchLatestVersion()
        .then((version) => {
          if (!version) return;
          const fresh = readConfig();
          writeConfig({ ...fresh, updateCheck: { latestVersion: version, checkedAt: now } });
        })
        .catch(() => {});
    }
  } catch {
    // Nunca travar o CLI por causa de verificação de update
  }
}

/**
 * Chamado antes de kasy new. Se houver versão mais nova no cache,
 * mostra aviso e pergunta se quer continuar ou sair para atualizar.
 * Nunca bloqueia — se o usuário ignorar, o fluxo segue normalmente.
 */
async function warnIfOutdatedBeforeNew(t) {
  try {
    const cache = (readConfig().updateCheck) || {};
    if (!cache.latestVersion || !isNewer(cache.latestVersion, pkg.version)) return;

    const hint = t ? t('new.outdated.hint') : 'projetos criados agora não terão as últimas melhorias.';
    console.log(
      '\n' +
      kleur.bgYellow().black(' UPDATE ') + '  ' +
      kleur.bold(`v${cache.latestVersion} disponível`) +
      kleur.dim(`  — ${hint}`) +
      '\n'
    );

    // Called BEFORE any ui.intro fires in kasy new, so this prompt runs as a
    // standalone Clack confirm (no rail to break). On cancel we exit cleanly.
    const upgrade = await ui.confirm({
      message: t ? t('new.outdated.upgradeNow') : 'Atualizar antes de criar? (requer assinatura ativa)',
      initialValue: false,
      onCancel: () => process.exit(0),
    });

    if (upgrade) {
      const { spawnSync } = require('node:child_process');
      const result = spawnSync('kasy', ['upgrade'], { stdio: 'inherit', shell: true });
      process.exit(result.status ?? 0);
    }
  } catch {
    // Nunca travar o kasy new por causa do aviso de versão
  }
}

module.exports = { checkForUpdates, warnIfOutdatedBeforeNew };
