<?php
declare(strict_types=1);
ini_set('display_errors', '1');
error_reporting(E_ALL);

/**
 * build_m3u_clean.php
 * - Lee JSON items {tvg_id,name,logo}
 * - Descarga logos a /logos como PNG
 * - Genera JSON final limpio:
 *   { meta, categories, channels:[{id,name,category,logo}] }
 * - Sin tvg_id, sin source_logo
 * - Sin URLs rotas (¥) -> siempre con "/"
 * - Por tandas (evita timeout) + reanudable
 */

// ===================== CONFIG =====================
$INPUT_JSON = __DIR__ . '/m3u_logos.json'; // o URL: 'https://api.codextelecom.com/m3u_logos.json'
$BASE_URL   = 'https://api.codextelecom.com/logos';
$LOGO_DIR   = __DIR__ . '/logos';

$PER_RUN     = 12; // logos por ejecución (sube/baja según hosting)
$MAX_SECONDS = 20; // segundos máx por ejecución
$TIMEOUT     = 60; // timeout curl

$PROGRESS_FILE = __DIR__ . '/progress_m3u.json';
$ERRORS_FILE   = __DIR__ . '/errores_m3u.json';
$OUT_JSON      = __DIR__ . '/logos_movistar_from_m3u.json';

// ===================== CATEGORÍAS (orden fijo) =====================
$CATEGORIES_ORDER = [
  "LOCALES Y EXCLUSIVOS",
  "NOVELAS",
  "OTROS LOCALES",
  "SERIES Y PELICULAS",
  "CIENCIA Y CULTURA",
  "ENTRETENIMIENTO Y ESTILO DE VIDA",
  "PACK HBO",
  "INFANTILES",
  "DEPORTE",
  "NOTICIAS",
  "ESPECIALIZADOS Y REGIONALES",
  "RELIGIOSO",
  "MUSICA",
  "INTERNACIONAL Y VARIADO"
];

// ===================== HELPERS =====================
function ensure_dir(string $dir): void {
  if (!is_dir($dir)) {
    if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
      throw new RuntimeException("No pude crear carpeta: $dir");
    }
  }
}

function slugify(string $text): string {
  $text = trim(mb_strtolower($text, 'UTF-8'));
  $text = preg_replace('/[^\p{L}\p{N}\s-]+/u', '', $text) ?? '';
  $text = preg_replace('/[\s_-]+/u', '-', $text) ?? '';
  $text = trim($text, '-');
  return $text !== '' ? $text : 'logo';
}

function short_hash(string $s): string { return substr(md5($s), 0, 6); }

function normalize_name(string $s): string {
  $s = mb_strtolower(trim($s), 'UTF-8');
  $s = str_replace(['á','é','í','ó','ú','ü','ñ'], ['a','e','i','o','u','u','n'], $s);
  $s = preg_replace('/\s+/u',' ', $s) ?? $s;
  $s = preg_replace('/\bhd\b/u','', $s) ?? $s;
  return trim($s);
}

function category_for_name(string $name): string {
  $n = normalize_name($name);

  $locales = [
    'latina','america television','panamericana television','tv peru','canal n','atv','rpp','global tv','trivu','willax','pbo',
    'latina noticias','alacocina tv','movistar eventos','movistar eventos 2'
  ];
  foreach ($locales as $k) if (str_contains($n, $k)) return "LOCALES Y EXCLUSIVOS";

  $novelas = ['tl novelas','las estrellas','tnt novelas','k-drama','ve plus','pasiones'];
  foreach ($novelas as $k) if (str_contains($n, $k)) return "NOVELAS";

  $otrosLocales = ['juntos tv','la tele','tv peru 7.3','atv+','exitosa tv','nativa','viva tv','usmp tv','ipe','plus life'];
  foreach ($otrosLocales as $k) if (str_contains($n, $k)) return "OTROS LOCALES";

  $series = ['tnt', 'tnt series','warner','star channel','fx','investigation discovery','clover','star tve','adult swim','tcm','space','cinecanal','comedy central','cinemax','atres series'];
  foreach ($series as $k) if (str_contains($n, $k)) return "SERIES Y PELICULAS";

  $ciencia = ['discovery', 'animal planet','nat geo','love nature','discovery turbo','discovery home & garden'];
  foreach ($ciencia as $k) if (str_contains($n, $k)) return "CIENCIA Y CULTURA";

  $lifestyle = ['tlc','home & health','food network','ucl'];
  foreach ($lifestyle as $k) if (str_contains($n, $k)) return "ENTRETENIMIENTO Y ESTILO DE VIDA";

  $kids = ['cartoon network','discovery kids','cartoonito','nick','disney channel','disney junior','tooncast','baby tv','clan','kids stars','plim plim'];
  foreach ($kids as $k) if (str_contains($n, $k)) return "INFANTILES";

  $sports = ['movistar deportes','m deportes','liga 1','liga 1 max','px sports','via x','jcp-jne','jcp jne','espn'];
  foreach ($sports as $k) if (str_contains($n, $k)) return "DEPORTE";

  $news = ['cnn','bbc world news','france24','tvlibertad'];
  foreach ($news as $k) if (str_contains($n, $k)) return "NOTICIAS";

  $esp = ['congreso','justicia tv','sol tv'];
  foreach ($esp as $k) if (str_contains($n, $k)) return "ESPECIALIZADOS Y REGIONALES";

  $rel = ['ewtn','nuevo tiempo','enlace','telejuan','paxtv','daystar'];
  foreach ($rel as $k) if (str_contains($n, $k)) return "RELIGIOSO";

  $music = ['mtv'];
  foreach ($music as $k) if (str_contains($n, $k)) return "MUSICA";

  return "OTROS LOCALES";
}

function http_get(string $url, int $timeout): array {
  $ch = curl_init($url);
  if ($ch === false) throw new RuntimeException("curl_init falló");

  curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS      => 5,
    CURLOPT_CONNECTTIMEOUT => $timeout,
    CURLOPT_TIMEOUT        => $timeout,
    CURLOPT_SSL_VERIFYPEER => false, // si tu server lo soporta, pon true
    CURLOPT_SSL_VERIFYHOST => 0,
    CURLOPT_USERAGENT      => 'Mozilla/5.0 (CodexLogoBuilder/M3U-CLEAN)',
    CURLOPT_HEADER         => true,
  ]);

  $resp = curl_exec($ch);
  if ($resp === false) {
    $err = curl_error($ch);
    curl_close($ch);
    throw new RuntimeException("cURL: $err");
  }

  $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  $hsize  = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  $header = substr($resp, 0, $hsize);
  $body   = substr($resp, $hsize);

  $ctype = '';
  foreach (explode("\r\n", $header) as $line) {
    if (stripos($line, 'content-type:') === 0) {
      $ctype = trim(substr($line, 13));
      break;
    }
  }

  curl_close($ch);
  if ($status >= 400) throw new RuntimeException("HTTP $status: $url");
  return [$body, $ctype, $status];
}

function load_json_any(string $pathOrUrl, int $timeout): array {
  if (preg_match('~^https?://~i', $pathOrUrl)) {
    [$bytes] = http_get($pathOrUrl, $timeout);
    return json_decode($bytes, true, flags: JSON_THROW_ON_ERROR);
  }
  $bytes = @file_get_contents($pathOrUrl);
  if ($bytes === false) throw new RuntimeException("No pude leer archivo: $pathOrUrl");
  return json_decode($bytes, true, flags: JSON_THROW_ON_ERROR);
}

function save_png_bytes(string $bytes, string $outPath): void {
  if (!extension_loaded('gd')) throw new RuntimeException("GD no disponible.");

  $img = @imagecreatefromstring($bytes);
  if ($img === false) throw new RuntimeException("No pude leer imagen (bytes).");

  imagesavealpha($img, true);

  // Guardar tal cual (sin resize) para máxima calidad
  if (!imagepng($img, $outPath, 9)) {
    imagedestroy($img);
    throw new RuntimeException("No pude guardar PNG: $outPath");
  }
  imagedestroy($img);
}

// ===================== RUN =====================
ensure_dir($LOGO_DIR);
$start = microtime(true);

// progreso
$progress = ['index'=>0,'done'=>0,'errors'=>0];
if (file_exists($PROGRESS_FILE)) {
  $p = json_decode((string)file_get_contents($PROGRESS_FILE), true);
  if (is_array($p)) $progress = array_merge($progress, $p);
}

// errores
$errors = [];
if (file_exists($ERRORS_FILE)) {
  $e = json_decode((string)file_get_contents($ERRORS_FILE), true);
  if (is_array($e)) $errors = $e;
}

try {
  $input = load_json_any($INPUT_JSON, $TIMEOUT);
} catch (Throwable $e) {
  http_response_code(500);
  echo "ERROR leyendo JSON input: ".$e->getMessage()."\n";
  exit;
}

$items = $input['items'] ?? [];
$total = count($items);
if ($total === 0) { echo "No hay items en JSON.\n"; exit; }

echo "=== M3U CLEAN BUILDER ===\n";
echo "Total items: $total\n";
echo "Por ejecución: $PER_RUN | Max seg: $MAX_SECONDS\n\n";

// ---------- Construir lista channels LIMPIA ----------
$channels = [];
foreach ($items as $it) {
  $name = (string)($it['name'] ?? '');
  $tvg  = (string)($it['tvg_id'] ?? '');
  $src  = (string)($it['logo'] ?? '');

  $id = slugify($tvg !== '' ? $tvg : $name); // lch6289 etc (minúscula)
  $cat = category_for_name($name);

  $base = slugify($name !== '' ? $name : $id);
  $h = short_hash($tvg.'|'.$name.'|'.$src);
  $file = "{$base}-{$h}.png";

  $channels[] = [
    "id" => $id,
    "name" => $name,
    "category" => $cat,
    "logo" => rtrim($BASE_URL,'/')."/".$file, // ✅ URL limpia
    "_src" => $src, // interno SOLO para descargar (luego se quita)
    "_file" => $file // interno
  ];
}

// ordenar por categorías y nombre
$catIndex = array_flip($CATEGORIES_ORDER);
usort($channels, function($a,$b) use ($catIndex) {
  $ca = $catIndex[$a['category']] ?? 999;
  $cb = $catIndex[$b['category']] ?? 999;
  if ($ca !== $cb) return $ca <=> $cb;
  return strcasecmp((string)$a['name'], (string)$b['name']);
});

// ---------- Descargar por tandas ----------
$processed = 0;
for ($i=(int)$progress['index']; $i<count($channels); $i++) {
  if ($processed >= $PER_RUN) break;
  if ((microtime(true)-$start) > $MAX_SECONDS) break;

  $ch = $channels[$i];
  $name = $ch['name'];
  $src  = $ch['_src'];
  $file = $ch['_file'];
  $path = $LOGO_DIR . '/' . $file;

  if (file_exists($path)) {
    echo "SKIP: $name\n";
    $progress['done']++;
    $progress['index'] = $i+1;
    $processed++;
    continue;
  }

  try {
    [$bytes, $ctype] = http_get($src, $TIMEOUT);
    save_png_bytes($bytes, $path);
    echo "OK: $name -> $file\n";
    $progress['done']++;
  } catch (Throwable $e) {
    echo "ERROR: $name -> {$e->getMessage()}\n";
    $progress['errors']++;
    $errors[] = ['idx'=>$i,'name'=>$name,'logo'=>$src,'error'=>$e->getMessage()];
  }

  $progress['index'] = $i+1;
  $processed++;

  file_put_contents($PROGRESS_FILE, json_encode($progress, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT));
  file_put_contents($ERRORS_FILE, json_encode($errors, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT));
}

// ---------- Generar JSON final SIN campos extra ----------
$finalChannels = [];
foreach ($channels as $c) {
  $finalChannels[] = [
    "id" => $c['id'],
    "name" => $c['name'],
    "category" => $c['category'],
    "logo" => $c['logo'],
  ];
}

$out = [
  "meta" => [
    "version" => "1.0.0",
    "by" => "Codex Digital (builder)",
    "generated_at" => gmdate('c'),
    "total_channels" => count($finalChannels),
    "notes" => [
      "Source=m3u items; logos descargados y servidos localmente.",
      "Proceso por pasos para evitar timeouts del hosting."
    ]
  ],
  "categories" => $CATEGORIES_ORDER,
  "channels" => $finalChannels
];

file_put_contents($OUT_JSON, json_encode($out, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT));

// resumen
$remaining = max(0, count($channels) - (int)$progress['index']);
echo "\n=== PROGRESO ===\n";
echo "Total: ".count($channels)."\n";
echo "Hechos: {$progress['done']}\n";
echo "Errores: {$progress['errors']}\n";
echo "Siguiente index: {$progress['index']}\n";
echo "Restantes: $remaining\n";
echo "Salida JSON: $OUT_JSON\n";
echo "================\n";

if ($progress['index'] < count($channels)) {
  echo "➡️ Recarga esta misma URL para continuar.\n";
} else {
  echo "✅ TERMINADO (logos y JSON limpio listos)\n";
}