<?php
header('Content-Type: text/html; charset=UTF-8');

$jsonFile = __DIR__ . '/output_channels.json';
$accessPassword = '4545454599';

$columnOrder = [
    'samir' => 'SAMIR',
    'nizer' => 'NIZER',
    'good'  => 'GOOD',
    'cris'  => 'CRIS',
];

function normalizeChannelUrl(string $url): string {
    $url = trim($url);
    return preg_replace('/\.ts($|\?)/i', '$1', $url);
}

function normalizeSearchText(string $text): string {
    $text = trim(mb_strtolower($text, 'UTF-8'));

    $converted = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $text);
    if ($converted !== false) {
        $text = $converted;
    }

    $text = strtolower($text);
    $text = preg_replace('/[^a-z0-9]+/', '', $text);

    return $text ?? '';
}

function startsWithText(string $text, string $search): bool {
    if ($search === '') return false;
    return substr($text, 0, strlen($search)) === $search;
}

function isValidLogoUrl(string $url): bool {
    $url = trim($url);
    if ($url === '') {
        return false;
    }
    return preg_match('#^https?://#i', $url) === 1;
}

function hasValidAccess(string $accessPassword): bool {
    $key = isset($_REQUEST['key']) ? (string)$_REQUEST['key'] : '';
    return $key !== '' && hash_equals($accessPassword, $key);
}

function loadChannelsFromJson(string $jsonFile): array {
    if (!file_exists($jsonFile)) {
        return [];
    }

    $content = file_get_contents($jsonFile);
    if ($content === false || trim($content) === '') {
        return [];
    }

    $data = json_decode($content, true);
    if (!is_array($data)) {
        return [];
    }

    $items = [];

    foreach ($data as $rec) {
        if (!is_array($rec)) {
            continue;
        }

        $lista = isset($rec['lista_name']) ? trim((string)$rec['lista_name']) : '';
        $name  = isset($rec['name_chanel']) ? trim((string)$rec['name_chanel']) : '';
        $link  = isset($rec['link_chanel']) ? trim((string)$rec['link_chanel']) : '';
        $id    = isset($rec['id_chanel']) ? trim((string)$rec['id_chanel']) : '';
        $logo  = isset($rec['logo_chanel']) ? trim((string)$rec['logo_chanel']) : '';

        if ($lista === '' || $link === '') {
            continue;
        }

        $items[] = [
            'lista_name'  => $lista,
            'name_chanel' => $name !== '' ? $name : 'Sem nome',
            'link_chanel' => normalizeChannelUrl($link),
            'id_chanel'   => $id,
            'logo_chanel' => isValidLogoUrl($logo) ? $logo : '',
            'search_name' => normalizeSearchText($name),
            'search_id'   => normalizeSearchText($id),
        ];
    }

    return $items;
}

function groupChannelsByList(array $items, array $columnOrder): array {
    $grouped = [];

    foreach ($columnOrder as $key => $label) {
        $grouped[$label] = [];
    }

    foreach ($items as $item) {
        $listKey = mb_strtolower(trim((string)$item['lista_name']), 'UTF-8');

        if (!isset($columnOrder[$listKey])) {
            continue;
        }

        $label = $columnOrder[$listKey];

        $grouped[$label][] = [
            'name'       => $item['name_chanel'],
            'url'        => $item['link_chanel'],
            'id'         => $item['id_chanel'],
            'logo'       => $item['logo_chanel'],
            'lista_name' => $item['lista_name'],
        ];
    }

    return $grouped;
}

if (isset($_GET['logout']) && $_GET['logout'] == '1') {
    header('Location: ./');
    exit;
}

if (isset($_GET['api']) && $_GET['api'] === 'search') {
    header('Content-Type: application/json; charset=UTF-8');

    if (!hasValidAccess($accessPassword)) {
        http_response_code(401);
        echo json_encode([
            'success' => false,
            'message' => 'Não autorizado.'
        ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }

    $query = isset($_GET['q']) ? trim((string)$_GET['q']) : '';
    $queryNormalized = normalizeSearchText($query);

    $allChannels = loadChannelsFromJson($jsonFile);

    if ($queryNormalized !== '') {
        $scored = [];

        foreach ($allChannels as $item) {
            $name = $item['search_name'] ?? '';
            $id   = $item['search_id'] ?? '';

            $matched = false;
            $score = 999;

            if ($name !== '' && startsWithText($name, $queryNormalized)) {
                $score = 1;
                $matched = true;
            } elseif ($id !== '' && startsWithText($id, $queryNormalized)) {
                $score = 2;
                $matched = true;
            } elseif ($name !== '' && strpos($name, $queryNormalized) !== false) {
                $score = 3;
                $matched = true;
            } elseif ($id !== '' && strpos($id, $queryNormalized) !== false) {
                $score = 4;
                $matched = true;
            }

            if ($matched) {
                $item['_score'] = $score;
                $scored[] = $item;
            }
        }

        usort($scored, function ($a, $b) {
            $scoreCompare = ($a['_score'] ?? 999) <=> ($b['_score'] ?? 999);
            if ($scoreCompare !== 0) {
                return $scoreCompare;
            }

            $nameCompare = strcasecmp($a['name_chanel'] ?? '', $b['name_chanel'] ?? '');
            if ($nameCompare !== 0) {
                return $nameCompare;
            }

            return strcasecmp($a['id_chanel'] ?? '', $b['id_chanel'] ?? '');
        });

        $allChannels = $scored;
    }

    $result = groupChannelsByList($allChannels, $columnOrder);

    echo json_encode([
        'success' => true,
        'query'   => $query,
        'data'    => $result,
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    exit;
}

$loginError = '';
$hasAccess = hasValidAccess($accessPassword);

if (!$hasAccess && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['panel_password'])) {
    $postedPassword = (string)($_POST['panel_password'] ?? '');

    if (hash_equals($accessPassword, $postedPassword)) {
        header('Location: ./?key=' . urlencode($postedPassword));
        exit;
    } else {
        $loginError = 'Senha incorreta.';
    }
}

if (!$hasAccess):
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Acesso ao Painel</title>
  <style>
    :root {
      --bg1: #f8fafc;
      --bg2: #edf2f7;
      --card: #ffffff;
      --text: #263445;
      --muted: #6d7886;
      --border: #d9e1ea;
      --shadow: 0 18px 50px rgba(0,0,0,0.10);
      --accent: #3b82f6;
      --danger: #d9485f;
    }
    * { box-sizing: border-box; }
    body {
      margin: 0;
      min-height: 100vh;
      font-family: Arial, Helvetica, sans-serif;
      background: linear-gradient(180deg, var(--bg1) 0%, var(--bg2) 100%);
      display: flex;
      align-items: center;
      justify-content: center;
      color: var(--text);
      padding: 18px;
    }
    .login-card {
      width: 100%;
      max-width: 430px;
      background: var(--card);
      border: 1px solid var(--border);
      border-radius: 22px;
      box-shadow: var(--shadow);
      padding: 28px;
    }
    .login-title {
      font-size: 30px;
      font-weight: 700;
      margin-bottom: 8px;
      text-align: center;
    }
    .login-subtitle {
      text-align: center;
      color: var(--muted);
      font-size: 15px;
      margin-bottom: 24px;
    }
    .login-input {
      width: 100%;
      border: 1px solid var(--border);
      border-radius: 14px;
      padding: 16px 18px;
      font-size: 22px;
      outline: none;
      margin-bottom: 14px;
    }
    .login-input:focus {
      border-color: var(--accent);
      box-shadow: 0 0 0 4px rgba(59,130,246,0.12);
    }
    .login-button {
      width: 100%;
      border: 0;
      border-radius: 14px;
      padding: 16px 18px;
      font-size: 18px;
      font-weight: 700;
      cursor: pointer;
      color: #fff;
      background: var(--accent);
    }
    .login-error {
      margin-bottom: 14px;
      padding: 12px 14px;
      border-radius: 12px;
      background: rgba(217,72,95,0.10);
      color: var(--danger);
      font-weight: 700;
      text-align: center;
    }
  </style>
</head>
<body>
  <form class="login-card" method="post" action="">
    <div class="login-title">Painel protegido</div>
    <div class="login-subtitle">Digite a senha para acessar</div>

    <?php if ($loginError !== ''): ?>
      <div class="login-error"><?php echo htmlspecialchars($loginError, ENT_QUOTES, 'UTF-8'); ?></div>
    <?php endif; ?>

    <input
      class="login-input"
      type="password"
      name="panel_password"
      placeholder="Senha"
      autocomplete="current-password"
      autofocus
      required
    />

    <button class="login-button" type="submit">Entrar</button>
  </form>
</body>
</html>
<?php
exit;
endif;
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Painel JSON Canais</title>
  <style>
    :root {
      --bg: #f3f5f7;
      --card: #ffffff;
      --text: #2f3a4a;
      --muted: #6e7785;
      --border: #dfe5ec;
      --row: #f7f8fa;
      --shadow: 0 12px 35px rgba(0, 0, 0, 0.08);
      --radius: 18px;
      --samir: #64c782;
      --nizer: #6297e6;
      --good: #59bfd1;
      --cris: #e9ac6d;
      --dialog: #162033;
      --dialog-text: #eef4ff;
      --dialog-border: #2b426a;
      --success: #89f0b0;
      --selected-bg: #1ea94f;
      --selected-text: #ffffff;
      --selected-sub: rgba(255,255,255,0.88);
      --logo-bg: linear-gradient(180deg, #ffffff 0%, #eef2f7 100%);
      --logo-border: #d7dee8;
    }

    * { box-sizing: border-box; }

    body {
      margin: 0;
      font-family: Arial, Helvetica, sans-serif;
      background: linear-gradient(180deg, #f8fafc 0%, var(--bg) 100%);
      color: var(--text);
    }

    .container {
      max-width: 1520px;
      margin: 0 auto;
      padding: 24px 28px 48px;
    }

    .panel-actions {
      display: flex;
      justify-content: flex-end;
      margin-bottom: 12px;
    }

    .logout-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      text-decoration: none;
      border: 1px solid #d3dbe5;
      background: #fff;
      color: #314055;
      border-radius: 12px;
      padding: 10px 14px;
      font-weight: 700;
      box-shadow: 0 6px 18px rgba(0,0,0,0.05);
    }

    .topbar {
      display: flex;
      justify-content: center;
      margin-bottom: 24px;
    }

    .search-box {
      width: min(840px, 100%);
      display: flex;
      align-items: center;
      background: var(--card);
      border: 1px solid #cfd8e3;
      border-radius: 16px;
      padding: 0 18px;
      box-shadow: 0 8px 22px rgba(0, 0, 0, 0.05);
    }

    .search-box input {
      flex: 1;
      border: 0;
      outline: none;
      background: transparent;
      font-size: 28px;
      color: var(--text);
      padding: 20px 8px;
    }

    .search-box input::placeholder { color: #8d95a3; }

    .search-icon {
      width: 28px;
      height: 28px;
      opacity: 0.75;
      flex-shrink: 0;
    }

    .status-bar {
      text-align: center;
      color: var(--muted);
      font-size: 15px;
      margin-bottom: 20px;
      min-height: 18px;
    }

    .grid {
      display: grid;
      grid-template-columns: repeat(4, minmax(260px, 1fr));
      gap: 26px;
      align-items: start;
    }

    .column {
      background: var(--card);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
      box-shadow: var(--shadow);
      min-height: 520px;
    }

    .column-header {
      color: #fff;
      text-align: center;
      font-weight: 700;
      letter-spacing: 1px;
      font-size: 28px;
      padding: 22px 16px;
    }

    .samir .column-header { background: var(--samir); }
    .nizer .column-header { background: var(--nizer); }
    .good .column-header { background: var(--good); }
    .cris .column-header { background: var(--cris); }

    .list {
      display: flex;
      flex-direction: column;
      max-height: 620px;
      overflow-y: auto;
    }

    .item {
      width: 100%;
      border: 0;
      text-align: left;
      cursor: pointer;
      padding: 14px 16px;
      font-size: 20px;
      border-bottom: 1px solid #edf1f5;
      background: #ffffff;
      transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
      color: var(--text);
    }

    .item:nth-child(odd) { background: var(--row); }
    .item:hover { background: #eef5ff; transform: translateX(4px); }
    .item:active { transform: translateX(2px); }

    .item.selected {
      background: var(--selected-bg) !important;
      color: var(--selected-text);
      box-shadow: inset 0 0 0 2px rgba(255,255,255,0.18);
    }

    .item.selected .item-name,
    .item.selected .item-id {
      color: var(--selected-text);
    }

    .item.selected .item-url {
      color: var(--selected-sub);
    }

    .item.selected .item-logo-box {
      background: rgba(255,255,255,0.95);
      border-color: rgba(255,255,255,0.5);
    }

    .item-inner {
      display: flex;
      align-items: flex-start;
      gap: 12px;
      min-width: 0;
    }

    .item-logo-wrap {
      flex: 0 0 auto;
      width: 56px;
      display: flex;
      justify-content: center;
      align-items: flex-start;
      padding-top: 2px;
    }

    .item-logo-box {
      width: 52px;
      height: 36px;
      border-radius: 10px;
      background: var(--logo-bg);
      border: 1px solid var(--logo-border);
      box-shadow: inset 0 1px 0 rgba(255,255,255,0.8);
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
      padding: 4px;
    }

    .item-logo {
      max-width: 100%;
      max-height: 100%;
      object-fit: contain;
      display: block;
    }

    .item-logo-placeholder {
      font-size: 10px;
      font-weight: 700;
      color: #7b8797;
      text-align: center;
      line-height: 1.1;
      letter-spacing: 0.4px;
    }

    .item-content {
      flex: 1;
      min-width: 0;
    }

    .item-name {
      display: block;
      font-weight: 700;
      margin-bottom: 6px;
      line-height: 1.15;
      word-break: break-word;
    }

    .item-id {
      display: block;
      color: #526072;
      font-size: 13px;
      margin-bottom: 6px;
      word-break: break-word;
    }

    .item-url {
      display: block;
      color: var(--muted);
      font-size: 13px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .empty {
      padding: 28px 22px;
      font-size: 18px;
      color: var(--muted);
    }

    .dialog-box {
      margin-top: 28px;
      background: var(--dialog);
      color: var(--dialog-text);
      border: 1px solid var(--dialog-border);
      border-radius: 18px;
      box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18);
      padding: 22px;
    }

    .dialog-box.hidden { display: none; }

    .dialog-title {
      font-size: 22px;
      font-weight: 700;
      margin-bottom: 14px;
      color: var(--success);
    }

    .dialog-line {
      margin-bottom: 10px;
      word-break: break-word;
      line-height: 1.5;
    }

    .dialog-label {
      font-weight: 700;
      color: #b8ccf5;
    }

    .footer-note {
      text-align: center;
      color: var(--muted);
      margin-top: 18px;
      font-size: 14px;
    }

    @media (max-width: 1200px) {
      .grid { grid-template-columns: repeat(2, minmax(260px, 1fr)); }
    }

    @media (max-width: 700px) {
      .container { padding: 18px 14px 30px; }
      .search-box input { font-size: 20px; padding: 16px 6px; }
      .grid { grid-template-columns: 1fr; gap: 18px; }
      .column-header { font-size: 22px; padding: 18px 14px; }
      .item { font-size: 17px; padding: 14px 12px; }
      .item-logo-wrap { width: 50px; }
      .item-logo-box { width: 46px; height: 32px; }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="panel-actions">
      <a class="logout-btn" href="?logout=1">Sair</a>
    </div>

    <div class="topbar">
      <div class="search-box">
        <input type="text" id="searchInput" placeholder="Buscar canais por nome ou ID..." autocomplete="off" />
        <svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
          <circle cx="11" cy="11" r="7"></circle>
          <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
        </svg>
      </div>
    </div>

    <div class="status-bar" id="statusBar">Digite para pesquisar no JSON por nome ou ID.</div>

    <div class="grid" id="grid"></div>

    <div class="dialog-box hidden" id="copiedDialog">
      <div class="dialog-title">URL copiada com sucesso</div>
      <div class="dialog-line"><span class="dialog-label">Canal:</span> <span id="dialogName"></span></div>
      <div class="dialog-line"><span class="dialog-label">ID:</span> <span id="dialogId"></span></div>
      <div class="dialog-line"><span class="dialog-label">URL copiada:</span> <span id="dialogUrl"></span></div>
    </div>

    <div class="footer-note">
      Busca por nome e ID. A pesquisa prioriza itens que começam com o texto digitado.
    </div>
  </div>

  <script>
    const ACCESS_KEY = <?php echo json_encode($accessPassword, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>;

    const grid = document.getElementById('grid');
    const searchInput = document.getElementById('searchInput');
    const statusBar = document.getElementById('statusBar');
    const copiedDialog = document.getElementById('copiedDialog');
    const dialogName = document.getElementById('dialogName');
    const dialogId = document.getElementById('dialogId');
    const dialogUrl = document.getElementById('dialogUrl');

    const columnClassMap = {
      SAMIR: 'samir',
      NIZER: 'nizer',
      GOOD: 'good',
      CRIS: 'cris'
    };

    let debounceTimer = null;

    function escapeHtml(str) {
      return String(str ?? '')
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#039;');
    }

    function clearSelectionInColumn(listElement) {
      const selected = listElement.querySelectorAll('.item.selected');
      selected.forEach(el => el.classList.remove('selected'));
    }

    function createLogoHtml(channel) {
      const logo = channel.logo || '';

      if (logo) {
        return `
          <div class="item-logo-box">
            <img
              class="item-logo"
              src="${escapeHtml(logo)}"
              alt="Logo do canal"
              loading="lazy"
              referrerpolicy="no-referrer"
              onerror="this.style.display='none'; this.parentNode.innerHTML='<div class=&quot;item-logo-placeholder&quot;>LOGO</div>';"
            />
          </div>
        `;
      }

      return `
        <div class="item-logo-box">
          <div class="item-logo-placeholder">LOGO</div>
        </div>
      `;
    }

    function renderColumns(data) {
      grid.innerHTML = '';

      Object.keys(columnClassMap).forEach((name) => {
        const channels = Array.isArray(data[name]) ? data[name] : [];

        const column = document.createElement('div');
        column.className = `column ${columnClassMap[name]}`;

        const header = document.createElement('div');
        header.className = 'column-header';
        header.textContent = name;
        column.appendChild(header);

        const list = document.createElement('div');
        list.className = 'list';
        list.dataset.column = name;

        if (!channels.length) {
          const empty = document.createElement('div');
          empty.className = 'empty';
          empty.textContent = 'Nenhum canal encontrado';
          list.appendChild(empty);
        } else {
          channels.forEach((channel) => {
            const button = document.createElement('button');
            button.type = 'button';
            button.className = 'item';
            button.dataset.name = channel.name || '';
            button.dataset.url = channel.url || '';
            button.dataset.id = channel.id || '';
            button.dataset.logo = channel.logo || '';
            button.dataset.lista = channel.lista_name || '';

            button.innerHTML = `
              <div class="item-inner">
                <div class="item-logo-wrap">
                  ${createLogoHtml(channel)}
                </div>
                <div class="item-content">
                  <span class="item-name">${escapeHtml(channel.name || '')}</span>
                  <span class="item-id">ID: ${escapeHtml(channel.id || '')}</span>
                  <span class="item-url">${escapeHtml(channel.url || '')}</span>
                </div>
              </div>
            `;

            button.addEventListener('click', async () => {
              clearSelectionInColumn(list);
              button.classList.add('selected');

              const name = button.dataset.name || '';
              const url = button.dataset.url || '';
              const id  = button.dataset.id || '';

              await copyChannelUrl(name, id, url);
            });

            list.appendChild(button);
          });
        }

        column.appendChild(list);
        grid.appendChild(column);
      });
    }

    async function copyChannelUrl(name, id, url) {
      try {
        await navigator.clipboard.writeText(url);
        dialogName.textContent = name;
        dialogId.textContent = id || '-';
        dialogUrl.textContent = url;
        copiedDialog.classList.remove('hidden');
        statusBar.textContent = 'Link copiado para a área de transferência.';
      } catch (error) {
        dialogName.textContent = name;
        dialogId.textContent = id || '-';
        dialogUrl.textContent = url;
        copiedDialog.classList.remove('hidden');
        statusBar.textContent = 'Não foi possível copiar automaticamente. Copie manualmente abaixo.';
      }
    }

    async function searchChannels(query = '') {
      statusBar.textContent = 'Lendo JSON de canais...';

      try {
        const response = await fetch(`?api=search&key=${encodeURIComponent(ACCESS_KEY)}&q=${encodeURIComponent(query)}`);
        const json = await response.json();

        if (!json.success) {
          throw new Error(json.message || 'Resposta inválida');
        }

        renderColumns(json.data);

        const total = Object.values(json.data).reduce((acc, list) => acc + list.length, 0);
        statusBar.textContent = query
          ? `Pesquisa por "${query}" retornou ${total} canal(is).`
          : `Mostrando ${total} canal(is) carregados do JSON.`;
      } catch (error) {
        statusBar.textContent = 'Erro ao ler output_channels.json.';
        renderColumns({ SAMIR: [], NIZER: [], GOOD: [], CRIS: [] });
      }
    }

    searchInput.addEventListener('input', (e) => {
      const value = e.target.value;
      clearTimeout(debounceTimer);
      debounceTimer = setTimeout(() => {
        searchChannels(value);
      }, 120);
    });

    searchChannels('');
  </script>
</body>
</html>