/**
 * Sdílené funkce pro skill-image-vojtacode.
 * Žádné napevno zadané cesty — všechno se odvozuje od domovské složky uživatele,
 * takže to funguje na Windows i macOS bez editace.
 */
import { createRequire } from 'node:module';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const require = createRequire(import.meta.url);

/** Kořen skillu (o dvě úrovně výš než scripts/lib/). */
export const KOREN_SKILLU = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');

/** Data skillu mimo skill samotný — přežijí přeinstalaci i update. */
export const DATOVA_SLOZKA = path.join(os.homedir(), '.vojtacode-image');

/**
 * Profil prohlížeče s uloženým přihlášením.
 * Výchozí je vlastní profil v domovské složce — funguje na každém počítači.
 * Kdo už má jiný přihlášený Playwright profil, může na něj ukázat proměnnou
 * prostředí VOJTACODE_IMAGE_PROFIL a přihlašování přeskočit.
 */
export const PROFIL_PROHLIZECE = (process.env.VOJTACODE_IMAGE_PROFIL || '').trim()
  || path.join(DATOVA_SLOZKA, 'profil-prohlizece');

/** Kam se ukládají obrázky, když uživatel neřekne jinak. */
export function vychoziVystup() {
  const obrazky = path.join(os.homedir(), 'Pictures');
  const zaklad = fs.existsSync(obrazky) ? obrazky : os.homedir();
  return path.join(zaklad, 'VojtaCode-obrazky');
}

export const GEMINI = 'https://gemini.google.com/app';

/* ── volba prohlížeče ──────────────────────────────────────────────────────
   Uživatel si prohlížeč vybere jednou při instalaci; volba se uloží sem a
   generování ji pak už jen načte. */

export const SOUBOR_NASTAVENI = path.join(DATOVA_SLOZKA, 'nastaveni.json');

/** Prohlížeče, ze kterých se vybírá. `channel` = jak to chce Playwright. */
export const PROHLIZECE = {
  chrome:   { nazev: 'Google Chrome',  channel: 'chrome',  engine: 'chromium', stahovat: false },
  edge:     { nazev: 'Microsoft Edge', channel: 'msedge',  engine: 'chromium', stahovat: false },
  chromium: { nazev: 'Chromium',       channel: undefined, engine: 'chromium', stahovat: true  },
  firefox:  { nazev: 'Firefox',        channel: undefined, engine: 'firefox',  stahovat: true  }
};

/** Kde na disku hledáme systémové prohlížeče. */
function cestyProhlizece(klic) {
  const je_win = process.platform === 'win32';
  const domov = os.homedir();
  if (klic === 'chrome') {
    return je_win
      ? ['C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
         'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
         path.join(domov, 'AppData\\Local\\Google\\Chrome\\Application\\chrome.exe')]
      : ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'];
  }
  if (klic === 'edge') {
    return je_win
      ? ['C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',
         'C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe']
      : ['/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'];
  }
  return [];
}

/** Je ten prohlížeč v systému nainstalovaný? (Jen pro chrome/edge.) */
export function jeNainstalovan(klic) {
  return cestyProhlizece(klic).some((c) => { try { return fs.existsSync(c); } catch (e) { return false; } });
}

/** Přečte uložené nastavení; když není, vrátí prázdný objekt. */
export function nactiNastaveni() {
  try { return JSON.parse(fs.readFileSync(SOUBOR_NASTAVENI, 'utf8')); }
  catch (e) { return {}; }
}

/** Uloží volbu prohlížeče. */
export function ulozProhlizec(klic) {
  if (!PROHLIZECE[klic]) throw new Error(`Neznámý prohlížeč: ${klic}. Vyber z: ${Object.keys(PROHLIZECE).join(', ')}`);
  fs.mkdirSync(DATOVA_SLOZKA, { recursive: true });
  const nastaveni = { ...nactiNastaveni(), prohlizec: klic };
  fs.writeFileSync(SOUBOR_NASTAVENI, JSON.stringify(nastaveni, null, 2), 'utf8');
  return klic;
}

/**
 * Který prohlížeč použít. Pořadí: parametr → uložené nastavení →
 * co je v systému (Chrome, pak Edge) → vestavěné Chromium.
 */
export function vyberProhlizec(vynuceny) {
  if (vynuceny) {
    if (!PROHLIZECE[vynuceny]) throw new Error(`Neznámý prohlížeč: ${vynuceny}. Vyber z: ${Object.keys(PROHLIZECE).join(', ')}`);
    return vynuceny;
  }
  const ulozeny = nactiNastaveni().prohlizec;
  if (ulozeny && PROHLIZECE[ulozeny]) return ulozeny;
  if (jeNainstalovan('chrome')) return 'chrome';
  if (jeNainstalovan('edge')) return 'edge';
  return 'chromium';
}

/**
 * Najde Playwright. Pořadí: lokální node_modules ve skillu (tam ho dá nastaveni.mjs)
 * → globální npm složka → běžné require. Windows i macOS.
 */
export function najdiPlaywright() {
  const kandidati = [
    path.join(KOREN_SKILLU, 'node_modules', 'playwright'),
    path.join(KOREN_SKILLU, 'node_modules', 'playwright-core'),
    path.join(process.env.APPDATA ?? '', 'npm', 'node_modules', 'playwright'),
    '/usr/local/lib/node_modules/playwright',
    '/opt/homebrew/lib/node_modules/playwright',
    'playwright',
    'playwright-core'
  ];
  for (const k of kandidati) {
    try { return require(k); } catch (e) { /* zkus další */ }
  }
  throw new Error(
    'CHYBI_PLAYWRIGHT: Playwright nenalezen. Spusť nejdřív:\n' +
    `  node "${path.join(KOREN_SKILLU, 'scripts', 'nastaveni.mjs')}"`
  );
}

/** Vrátí motor prohlížeče (chromium / firefox) z Playwrightu. */
export function najdiMotor(engine) {
  const pw = najdiPlaywright();
  const motor = pw[engine];
  if (!motor) throw new Error(`Playwright nezná motor „${engine}".`);
  return motor;
}

/**
 * Otevře vybraný prohlížeč s trvalým profilem.
 * Volba prohlížeče: parametr → uložené nastavení → co je v systému.
 */
export async function otevriProhlizec({ viditelny = true, prohlizec } = {}) {
  const klic = vyberProhlizec(prohlizec);
  const volba = PROHLIZECE[klic];
  const motor = najdiMotor(volba.engine);
  fs.mkdirSync(PROFIL_PROHLIZECE, { recursive: true });

  const nastaveni = {
    headless: !viditelny,
    channel: volba.channel,
    // Viditelné okno obsluhuje ČLOVĚK (přihlašuje se v něm). Proto viewport
    // nevynucujeme — stránka se řídí skutečnou velikostí okna.
    // Pevný viewport 1280×920 tu působil škodu: Playwright ho bere v CSS
    // pixelech, takže při škálování Windows 125 % / 150 % vyrostlo okno na
    // 1600×1150 / 1920×1380 fyzických bodů. Na 1080p obrazovku se nevešlo
    // a přihlašovací stránka Googlu byla oříznutá (tlačítko Další mimo obraz).
    viewport: viditelny ? null : { width: 1280, height: 920 }
  };
  if (volba.engine === 'chromium') {
    // Playwright má sandbox vypnutý jako výchozí → přidal by --no-sandbox
    // a Chrome pak zobrazí žlutou lištu „nepodporované označení příkazového
    // řádku". Zapínáme ho zpět: lišta zmizí a je to bezpečnější.
    nastaveni.chromiumSandbox = true;
    nastaveni.args = ['--disable-blink-features=AutomationControlled'];
    // Okno na celou obrazovku, ať se vejde přihlašování i celý Gemini.
    // POZOR: nekombinovat s --window-position, Chrome pak maximalizaci ignoruje
    // a otevře úzké okno (změřeno: 945 px místo 1920).
    if (viditelny) nastaveni.args.push('--start-maximized');
  }

  try {
    const ctx = await motor.launchPersistentContext(PROFIL_PROHLIZECE, nastaveni);
    ctx.__prohlizec = klic;
    return ctx;
  } catch (err) {
    throw new Error(
      `Nepodařilo se otevřít ${volba.nazev}.\n` +
      (volba.stahovat
        ? `Chybí nejspíš stažený prohlížeč — spusť: npx playwright install ${volba.engine}\n`
        : `Zkontroluj, že je ${volba.nazev} nainstalovaný, nebo vyber jiný přes --prohlizec.\n`) +
      'Původní chyba: ' + (err?.message || err)
    );
  }
}

export const SELEKTOR_VSTUPU = 'div[contenteditable="true"]';

/**
 * Je uživatel přihlášený? Pozitivní signál (avatar účtu) má přednost;
 * jako záloha se kouká, jestli NENÍ vidět tlačítko na přihlášení.
 */
export async function jePrihlasen(page) {
  if (!page.url().startsWith('https://gemini.google.com')) return false;
  if ((await page.locator(SELEKTOR_VSTUPU).count().catch(() => 0)) === 0) return false;
  const ucet = await page
    .locator('a[href*="SignOutOptions" i], a[aria-label*="Google Account" i], [aria-label*="Google Account" i]')
    .count().catch(() => 0);
  if (ucet > 0) return true;
  const prihlasitViditelne = await page
    .locator('a:visible:has-text("Sign in"), button:visible:has-text("Sign in"), ' +
             'a:visible:has-text("Přihlásit"), button:visible:has-text("Přihlásit")')
    .count().catch(() => 0);
  return prihlasitViditelne === 0;
}

/** Šířka obrázku z hlavičky PNG/JPEG — na odlišení skutečného renderu od miniatury. */
export function sirkaObrazku(soubor) {
  try {
    const b = fs.readFileSync(soubor);
    if (b.length > 24 && b[0] === 0x89 && b[1] === 0x50) return b.readUInt32BE(16);
    if (b.length > 4 && b[0] === 0xff && b[1] === 0xd8) {
      let o = 2;
      while (o < b.length) {
        if (b[o] !== 0xff) { o++; continue; }
        const m = b[o + 1];
        if (m >= 0xc0 && m <= 0xcf && m !== 0xc4 && m !== 0xc8 && m !== 0xcc) return b.readUInt16BE(o + 7);
        o += 2 + b.readUInt16BE(o + 2);
      }
    }
  } catch (e) { /* nevadí */ }
  return 0;
}

/** Název souboru z promptu — bez diakritiky, bez mezer. */
export function nazevZPromptu(text) {
  return (
    text.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '')
      .replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 60) || 'obrazek'
  );
}
