<?php
declare(strict_types=1);

require_once __DIR__ . '/database.php';

const GPC_CHARSET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

function gpc_no_cache_headers(): void
{
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    header('Cache-Control: post-check=0, pre-check=0', false);
    header('Pragma: no-cache');
    header('Expires: 0');
}

function gpc_new_device_key(): string
{
    $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
    $part1 = '';
    $part2 = '';
    for ($i = 0; $i < 4; $i++) { $part1 .= $chars[random_int(0, strlen($chars) - 1)]; }
    for ($i = 0; $i < 4; $i++) { $part2 .= $chars[random_int(0, strlen($chars) - 1)]; }
    return 'SYN-' . $part1 . '-' . $part2;
}

function gpc_mac_decode(string $encoded): ?string
{
    $len = strlen($encoded);
    if ($len < 2) {
        return null;
    }
    $pos1 = strpos(GPC_CHARSET, $encoded[$len - 2]);
    $pos2 = strpos(GPC_CHARSET, $encoded[$len - 1]);
    if ($pos1 === false || $pos2 === false) {
        return null;
    }
    $decoded = substr($encoded, 0, $len - 2);
    $decoded = substr($decoded, 0, $pos1) . substr($decoded, $pos1 + $pos2);
    $json = base64_decode($decoded, true);
    return $json === false ? null : $json;
}

function gpc_mac_encode(string $json): string
{
    $b64 = base64_encode($json);
    $maxSplit = min(41, strlen($b64) + 1);
    $splitPos = $maxSplit > 0 ? random_int(0, $maxSplit - 1) : 0;
    $noiseLen = random_int(5, 20);
    $noise = '';
    for ($i = 0; $i < $noiseLen; $i++) {
        $noise .= GPC_CHARSET[random_int(0, 61)];
    }
    $payload = substr($b64, 0, $splitPos) . $noise . substr($b64, $splitPos);
    return $payload . GPC_CHARSET[$splitPos] . GPC_CHARSET[$noiseLen];
}

function gpc_json_out(array $payload): void
{
    gpc_no_cache_headers();
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode([
        'data' => gpc_mac_encode(json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)),
    ], JSON_UNESCAPED_UNICODE);
}

function gpc_parse_body(): ?array
{
    $raw = file_get_contents('php://input');
    if ($raw === false || $raw === '') {
        return null;
    }
    $outer = json_decode($raw, true);
    if (!is_array($outer) || !isset($outer['data'])) {
        return null;
    }
    if (is_array($outer['data'])) {
        return $outer['data'];
    }
    $decoded = gpc_mac_decode((string) $outer['data']);
    if ($decoded === null) {
        return null;
    }
    $inner = json_decode($decoded, true);
    return is_array($inner) ? $inner : null;
}

function gpc_mac_from_device_id(?string $id): ?string
{
    if ($id === null || $id === '') {
        return null;
    }
    $raw = base64_decode($id, true);
    if ($raw === false) {
        $raw = $id;
    }
    $raw = strtoupper(preg_replace('/[^A-Fa-f0-9]/', '', $raw));
    if (strlen($raw) < 12) {
        return null;
    }
    $raw = substr($raw, 0, 12);
    return strtoupper(implode(':', str_split($raw, 2)));
}

function gpc_device_key(string $mac): string
{
    return gpc_new_device_key();
}

function gpc_base_url(string $url): string
{
    $trim = trim($url);
    if ($trim !== '' && !preg_match('#^https?://#i', $trim)) {
        $trim = 'http://' . $trim;
    }
    $p = parse_url($trim);
    if (!$p || empty($p['host'])) {
        return $trim;
    }
    $port = isset($p['port']) ? ':' . $p['port'] : '';
    return ($p['scheme'] ?? 'http') . '://' . $p['host'] . $port;
}

function gpc_expired(?string $date): bool
{
    if ($date === null || trim($date) === '') {
        return false;
    }
    $d = preg_split('/[T\s]/', trim($date))[0];
    $ts = strtotime($d . ' 23:59:59');
    return $ts !== false && $ts < time();
}

function gpc_validate_key(?string $key): bool
{
    $expected = gpc_setting('app_key_dev', '69865c6619886');
    if ($expected === '') {
        return true;
    }
    return $key !== null && hash_equals($expected, $key);
}

function gpc_has_device_header(): bool
{
    foreach ($_SERVER as $k => $v) {
        if (strcasecmp($k, 'HTTP_DEVICE_ID') === 0 && $v !== '') {
            return true;
        }
    }
    return false;
}


function gpc_dns_row_effectively_active(array $dnsRow): bool
{
    if ((int)($dnsRow['status'] ?? 0) !== 1) {
        return false;
    }
    if (!empty($dnsRow['validity']) && gpc_expired((string)$dnsRow['validity'])) {
        return false;
    }
    if (!empty($dnsRow['reseller_id'])) {
        if ((int)($dnsRow['reseller_active'] ?? 0) !== 1) {
            return false;
        }
        if (!empty($dnsRow['reseller_validity']) && gpc_expired((string)$dnsRow['reseller_validity'])) {
            return false;
        }
    }
    return true;
}

function gpc_device_partner_code_active(array $deviceRow): bool
{
    if (($deviceRow['access_type'] ?? 'app_license') !== 'partner_code') {
        return true;
    }

    $dnsUrl = gpc_base_url((string)($deviceRow['dns'] ?? ''));
    if ($dnsUrl === '') {
        return false;
    }

    $db = gpc_db();
    $stmt = $db->query('SELECT ds.*, r.active AS reseller_active, r.validity AS reseller_validity FROM dns_servers ds LEFT JOIN resellers r ON r.id = ds.reseller_id');
    while ($dns = $stmt->fetch()) {
        if (gpc_base_url((string)$dns['url']) === $dnsUrl && gpc_dns_row_effectively_active($dns)) {
            return true;
        }
    }
    return false;
}

function gpc_playlist_url(array $row): string
{
    if (!empty($row['playlist_url'])) {
        return (string) $row['playlist_url'];
    }
    if (!empty($row['username']) && !empty($row['password']) && !empty($row['dns'])) {
        $base = rtrim((string) $row['dns'], '/');
        return $base . '/get.php?username=' . rawurlencode((string) $row['username'])
            . '&password=' . rawurlencode((string) $row['password'])
            . '&type=m3u_plus&output=mpegts';
    }
    return '';
}

function gpc_build_guim(string $mac, string $deviceKey): array
{
    $db = gpc_db();
    $stmt = $db->prepare('SELECT * FROM devices WHERE mac_address = :m ORDER BY id DESC LIMIT 1');
    $stmt->execute([':m' => $mac]);
    $client = $stmt->fetch();

    $stmtAll = $db->prepare('SELECT * FROM devices WHERE mac_address = :m ORDER BY id ASC');
    $stmtAll->execute([':m' => $mac]);

    $urls = [];
    $hasActivePlayable = false;
    while ($row = $stmtAll->fetch()) {
        if (!gpc_device_partner_code_active($row)) {
            continue;
        }
        $pl = gpc_playlist_url($row);
        $rowExpire = $row['expire_date'] ?? '';
        if ($pl === '' || ($rowExpire !== '' && gpc_expired((string)$rowExpire))) {
            continue;
        }
        $hasActivePlayable = true;
        $urls[] = [
            'id'           => (string) $row['id'],
            'name'         => (string) ($row['title'] ?: 'Lista'),
            'url'          => $pl,
            'is_protected' => '1',
        ];
    }

    $expire = $client['expire_date'] ?? '';
    $registered = $client !== false;
    $paid = $registered && $expire !== '' && !gpc_expired($expire) && (($client['access_type'] ?? 'app_license') !== 'partner_code' || gpc_device_partner_code_active($client));
    if (!$paid && $hasActivePlayable) { $paid = true; }

    return [
        'is_google_paid' => $paid,
        'is_paid'        => $paid,
        'status'         => $paid ? 'active' : 'inactive',
        'mac_registered' => $registered,
        'mac_address'    => $mac,
        'expire_date'    => $expire !== '' ? $expire : null,
        'device_key'     => (string)($client['device_key'] ?? $deviceKey),
        'notification'   => gpc_setting('notification', ''),
        'urls'           => $urls,
    ];
}

function gpc_auto_register_mac(string $mac, string $deviceKey): void
{
    // Controle global do Auto MAC.
    if (gpc_setting('auto_mac_enabled', '1') !== '1') {
        return;
    }

    $db = gpc_db();
    $stmt = $db->prepare("SELECT id FROM devices WHERE mac_address = :m AND COALESCE(access_type,'app_license') = 'app_license' LIMIT 1");
    $stmt->execute([':m' => $mac]);
    if ($stmt->fetch()) {
        return;
    }

    $days = max(1, (int) gpc_setting('auto_register_days', '365'));
    $expire = date('Y-m-d', strtotime('+' . $days . ' days'));

    $deviceKey = $deviceKey ?: gpc_new_device_key();
    $ins = $db->prepare('INSERT INTO devices (mac_address, title, expire_date, device_key, license_type, key_created_at, key_expire_at)
        VALUES (:m, :t, :e, :k, :lt, :kc, :ke)');
    $ins->execute([
        ':m' => $mac,
        ':t' => 'Teste grátis SYNTRA',
        ':e' => $expire,
        ':k' => $deviceKey,
        ':lt' => 'trial',
        ':kc' => date('Y-m-d H:i:s'),
        ':ke' => $expire,
    ]);
}

function gpc_log_register(array $data): void
{
    $stmt = gpc_db()->prepare('INSERT INTO registration_logs
        (mac_address, username, password, cod_revenda, dns_id, dns_url)
        VALUES (:mac, :u, :p, :c, :did, :url)');
    $stmt->execute([
        ':mac' => $data['mac'] ?? '',
        ':u'   => $data['user'] ?? '',
        ':p'   => $data['pass'] ?? '',
        ':c'   => $data['cod'] ?? '',
        ':did' => (int) ($data['dns_id'] ?? 0),
        ':url' => $data['dns_url'] ?? '',
    ]);
}


function syntra_dns_final_active(array $dnsRow): bool
{
    if ((int)($dnsRow['status'] ?? 0) !== 1) return false;
    if (!empty($dnsRow['validity']) && gpc_expired((string)$dnsRow['validity'])) return false;
    if (!empty($dnsRow['reseller_id'])) {
        if ((int)($dnsRow['reseller_active'] ?? 0) !== 1) return false;
        if (!empty($dnsRow['reseller_validity']) && gpc_expired((string)$dnsRow['reseller_validity'])) return false;
    }
    return true;
}



function syntra_reseller_plan_label(string $plan): string
{
    $plan = strtolower(trim($plan));
    if ($plan === 'plus') return 'PLUS';
    if ($plan === 'business') return 'BUSINESS';
    return 'BASIC';
}

function syntra_reseller_can_mac(array $reseller): bool
{
    return (int)($reseller['can_mac'] ?? 1) === 1;
}

function syntra_reseller_can_dns(array $reseller): bool
{
    return (int)($reseller['can_dns'] ?? 1) === 1 && (int)($reseller['dns_limit'] ?? 0) > 0;
}

function syntra_reseller_is_valid(array $reseller): bool
{
    return (int)($reseller['active'] ?? 0) === 1 && (empty($reseller['validity']) || !gpc_expired((string)$reseller['validity']));
}

function syntra_status_badge(bool $ok): string
{
    return $ok ? '<span class="badge badge-ok">Online</span>' : '<span class="badge badge-bad">Atenção</span>';
}
