<?php
require_once __DIR__ . '/_device_access.php';

function auth_json_out(array $arr): void {
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($arr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function auth_normalize_mac(?string $mac): string {
    $clean = strtoupper(substr(preg_replace('/[^A-Fa-f0-9]/', '', trim((string)$mac)), 0, 12));
    if (strlen($clean) !== 12) {
        return $clean;
    }
    return implode(':', str_split($clean, 2));
}

function auth_column_exists(PDO $db, string $table, string $column): bool {
    try {
        $st = $db->query("PRAGMA table_info($table)");
        while ($row = $st->fetch(PDO::FETCH_ASSOC)) {
            if (($row['name'] ?? '') === $column) {
                return true;
            }
        }
    } catch (Throwable $e) {
    }
    return false;
}

function auth_table_exists(PDO $db, string $table): bool {
    try {
        $st = $db->prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=? LIMIT 1");
        $st->execute([$table]);
        return (bool)$st->fetch(PDO::FETCH_ASSOC);
    } catch (Throwable $e) {
        return false;
    }
}

function auth_ensure_schema(PDO $db): void {
    da_ensure_schema($db);
}


function auth_get_dns_list(PDO $db): array {
    $dns = [];
    try {
        $st = $db->query("SELECT url FROM dns ORDER BY nome ASC");
        while ($row = $st->fetch(PDO::FETCH_ASSOC)) {
            $url = auth_normalize_dns((string)($row['url'] ?? ''));
            if ($url !== '' && !in_array($url, $dns, true)) {
                $dns[] = $url;
            }
        }
    } catch (Throwable $e) {
    }
    return $dns;
}

function auth_normalize_dns(?string $dns): string {
    $dns = trim((string)$dns);
    if ($dns === '') return '';
    if (!preg_match('~^https?://~i', $dns)) {
        $dns = 'http://' . $dns;
    }
    return rtrim($dns, '/');
}

function auth_xtream_blocked_status(?string $status): bool {
    $s = strtolower(trim((string)$status));
    if ($s === '') return false;
    foreach (['disabled', 'disable', 'banned', 'ban', 'expired', 'expirado', 'blocked', 'bloqueado'] as $bad) {
        if (strpos($s, $bad) !== false) return true;
    }
    return false;
}

function auth_fetch_json_url(string $url, int $timeout = 12): ?array {
    $response = false;
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CONNECTTIMEOUT => 6,
            CURLOPT_TIMEOUT => $timeout,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_USERAGENT => 'TheFull-Auth/1.0',
        ]);
        $response = curl_exec($ch);
        curl_close($ch);
    } else {
        $ctx = stream_context_create([
            'http' => ['timeout' => $timeout, 'header' => "User-Agent: TheFull-Auth/1.0\r\n"],
            'ssl' => ['verify_peer' => false, 'verify_peer_name' => false],
        ]);
        $response = @file_get_contents($url, false, $ctx);
    }
    if (!is_string($response) || trim($response) === '') return null;
    $json = json_decode($response, true);
    return is_array($json) ? $json : null;
}

function auth_validate_xtream_credentials(string $dns, string $username, string $password): array {
    $dns = auth_normalize_dns($dns);
    $username = trim($username);
    $password = trim($password);
    $base = [
        'ok' => false,
        'expired' => false,
        'dns' => $dns,
        'exp' => 0,
        'message' => 'Usuário, senha ou DNS inválidos.',
        'user_info' => [],
    ];
    if ($dns === '' || $username === '' || $password === '') {
        $base['message'] = 'missing_credentials';
        return $base;
    }
    $url = $dns . '/player_api.php?username=' . urlencode($username) . '&password=' . urlencode($password);
    $json = auth_fetch_json_url($url, 12);
    if (!is_array($json) || !isset($json['user_info']) || !is_array($json['user_info'])) {
        $base['message'] = 'invalid_json';
        return $base;
    }
    $info = $json['user_info'];
    $base['user_info'] = $info;
    $auth = (int)($info['auth'] ?? 0);
    if ($auth !== 1) {
        $base['message'] = 'auth_failed';
        return $base;
    }
    $status = (string)($info['status'] ?? '');
    if (auth_xtream_blocked_status($status)) {
        $base['expired'] = stripos($status, 'expired') !== false || stripos($status, 'expirado') !== false;
        $base['message'] = $base['expired'] ? 'expired' : 'account_blocked';
        return $base;
    }
    $exp = (int)($info['exp_date'] ?? 0);
    if ($exp > 0 && $exp < time()) {
        $base['expired'] = true;
        $base['exp'] = $exp;
        $base['message'] = 'expired';
        return $base;
    }
    $base['ok'] = true;
    $base['expired'] = false;
    $base['exp'] = max(0, $exp);
    $base['message'] = 'ok';
    return $base;
}

function auth_validate_dns_credentials(array $dnsList, string $username, string $password, string $dnsSelected = ''): array {
    $ordered = [];
    $selected = auth_normalize_dns($dnsSelected);
    if ($selected !== '') $ordered[] = $selected;
    foreach ($dnsList as $dns) {
        $d = auth_normalize_dns((string)$dns);
        if ($d !== '' && !in_array($d, $ordered, true)) $ordered[] = $d;
    }
    $last = [
        'ok' => false,
        'expired' => false,
        'dns' => $selected,
        'exp' => 0,
        'message' => 'dns_empty',
        'user_info' => [],
    ];
    foreach ($ordered as $dns) {
        $res = auth_validate_xtream_credentials($dns, $username, $password);
        if (!empty($res['ok']) || !empty($res['expired'])) return $res;
        $last = $res;
    }
    return $last;
}

function auth_get_active_login_mode(PDO $db): string {
    try {
        $st = $db->query("SELECT active_login_mode FROM app_config WHERE id = 1 LIMIT 1");
        $mode = strtolower(trim((string)$st->fetchColumn()));
    } catch (Throwable $e) {
        $mode = 'normal';
    }
    if (!in_array($mode, ['normal', 'mac', 'activation_code'], true)) {
        $mode = 'normal';
    }
    return $mode;
}

function auth_get_test_config(PDO $db): array {
    try {
        $row = $db->query("SELECT enabled, api_url, dns_nome, provider, api_token, api_secret, api_bouquet, fastplay_adultos, auto_mac_enabled FROM config_test WHERE id = 1 LIMIT 1")
            ->fetch(PDO::FETCH_ASSOC);
        return is_array($row) ? $row : [];
    } catch (Throwable $e) {
        return [];
    }
}

function auth_get_app_flags(PDO $db): array {
    try {
        $row = $db->query("SELECT qrcode_app_enabled, renew_button_enabled, test_button_enabled, vencimento_modal_enabled FROM app_config WHERE id = 1 LIMIT 1")->fetch(PDO::FETCH_ASSOC);
        if (!is_array($row)) return ['qrcode_app_enabled' => 1, 'renew_button_enabled' => 1, 'test_button_enabled' => 1, 'vencimento_modal_enabled' => 1];
        return [
            'qrcode_app_enabled' => (int)($row['qrcode_app_enabled'] ?? 1),
            'renew_button_enabled' => (int)($row['renew_button_enabled'] ?? 1),
            'test_button_enabled' => (int)($row['test_button_enabled'] ?? 1),
            'vencimento_modal_enabled' => (int)($row['vencimento_modal_enabled'] ?? 1),
        ];
    } catch (Throwable $e) {
        return ['qrcode_app_enabled' => 1, 'renew_button_enabled' => 1, 'test_button_enabled' => 1, 'vencimento_modal_enabled' => 1];
    }
}

function auth_ensure_user_activation_code(PDO $db, array &$userRow): string {
    $code = trim((string)($userRow['activation_code'] ?? ''));
    $mac = auth_normalize_mac((string)($userRow['mac'] ?? ''));
    if ($code !== '' || $mac === '') return $code;
    $code = auth_generate_activation_code($db);
    try {
        $st = $db->prepare("UPDATE usuarios SET activation_code = ? WHERE mac = ?");
        $st->execute([$code, $mac]);
        $userRow['activation_code'] = $code;
    } catch (Throwable $e) {}
    return $code;
}

function auth_generate_activation_code(PDO $db): string {
    do {
        $code = str_pad((string)random_int(0, 9999), 4, '0', STR_PAD_LEFT);
        $st = $db->prepare("SELECT COUNT(*) FROM usuarios WHERE activation_code = ?");
        $st->execute([$code]);
        $exists = (int)$st->fetchColumn() > 0;
        $st->closeCursor();
    } while ($exists);
    return $code;
}

function auth_user_has_credentials(array $userRow): bool {
    return trim((string)($userRow['dns'] ?? '')) !== ''
        && trim((string)($userRow['username'] ?? '')) !== ''
        && trim((string)($userRow['password'] ?? '')) !== '';
}

function auth_format_exp($exp): string {
    $exp = (int)$exp;
    return $exp > 0 ? date('Y-m-d H:i:s', $exp) : '';
}

function auth_parse_vencimento_to_timestamp($value): int {
    if (is_numeric($value)) return (int)$value;
    $raw = trim((string)$value);
    if ($raw === '') return 0;
    $ts = strtotime($raw);
    return $ts ? (int)$ts : 0;
}

function auth_ensure_pending_mac(PDO $db, string $mac, string $deviceType = 'tv'): ?array {
    $mac = auth_normalize_mac($mac);
    if ($mac === '' || strlen(str_replace(':', '', $mac)) !== 12) return null;
    $deviceType = da_normalize_device_type($deviceType);
    $st = $db->prepare('SELECT * FROM usuarios WHERE mac = ? LIMIT 1');
    $st->execute([$mac]);
    $row = $st->fetch(PDO::FETCH_ASSOC);
    $st->closeCursor();
    if ($row) return $row;

    $cols = [];
    $q = $db->query('PRAGMA table_info(usuarios)');
    while ($r = $q->fetch(PDO::FETCH_ASSOC)) $cols[] = (string)$r['name'];
    if (!in_array('mac', $cols, true)) return null;
    $fields = ['mac'];
    $values = [$mac];
    $add = function(string $col, $val) use (&$fields, &$values, $cols): void {
        if (in_array($col, $cols, true)) { $fields[] = $col; $values[] = $val; }
    };
    $add('dns', '');
    $add('username', '');
    $add('password', '');
    $add('vencimento', '');
    $add('status', 'aguardando');
    $add('nome_cliente', 'Cliente ' . strtoupper(substr(str_replace(':', '', $mac), -4)));
    $add('whatsapp', '');
    $add('teste', 0);
    $add('teste_criado_at', 0);
    $add('login_mode', 'mac');
    $add('device_type', $deviceType);
    $add('last_device_type', $deviceType);
    $add('usuario_id', 0);
    $add('activation_code', auth_generate_activation_code($db));
    $placeholders = implode(',', array_fill(0, count($fields), '?'));
    $sql = 'INSERT OR IGNORE INTO usuarios (' . implode(',', $fields) . ') VALUES (' . $placeholders . ')';
    $execPending = function() use ($db, $sql, $values) {
        $stmt = $db->prepare($sql);
        $ok = $stmt->execute($values);
        $stmt->closeCursor();
        return $ok;
    };
    if (function_exists('trial_db_exec_retry')) {
        trial_db_exec_retry($execPending, 8, 200);
    } else {
        $execPending();
    }
    $st = $db->prepare('SELECT * FROM usuarios WHERE mac = ? LIMIT 1');
    $st->execute([$mac]);
    $saved = $st->fetch(PDO::FETCH_ASSOC) ?: null;
    $st->closeCursor();
    return $saved;
}

function auth_waiting_payload(string $message = 'Aguardando DNS, usuário e senha.'): array {
    return [
        'status' => 'waiting',
        'mac_registered' => true,
        'mac_pending' => true,
        'mac_has_credentials' => false,
        'logout' => false,
        'message' => $message,
    ];
}

function auth_refresh_user_after_validation(PDO $db, array $userRow, array $validation, string $deviceType = 'tv'): array {
    $mac = auth_normalize_mac((string)($userRow['mac'] ?? ''));
    $dns = auth_normalize_dns((string)($validation['dns'] ?? ($userRow['dns'] ?? '')));
    $exp = (int)($validation['exp'] ?? 0);
    $vencimento = $exp > 0 ? $exp : auth_parse_vencimento_to_timestamp($userRow['vencimento'] ?? 0);
    $deviceType = da_normalize_device_type($deviceType);
    try {
        $st = $db->prepare("UPDATE usuarios SET dns = ?, vencimento = ?, status = 'ativo', device_type = ?, last_device_type = ? WHERE mac = ?");
        $st->execute([$dns, $vencimento > 0 ? (string)$vencimento : '', $deviceType, $deviceType, $mac]);
    } catch (Throwable $e) {}
    $userRow['dns'] = $dns;
    $userRow['vencimento'] = $vencimento > 0 ? (string)$vencimento : '';
    $userRow['status'] = 'ativo';
    $userRow['device_type'] = $deviceType;
    $userRow['last_device_type'] = $deviceType;
    return $userRow;
}

function auth_build_success_payload(PDO $db, array $userRow, array $dnsList, ?string $forcedDns = null, array $extra = []): array {
    auth_ensure_user_activation_code($db, $userRow);
    $username = trim((string)($userRow['username'] ?? ''));
    $password = trim((string)($userRow['password'] ?? ''));
    $dnsSaved = auth_normalize_dns((string)($forcedDns ?: ($userRow['dns'] ?? '')));
    if ($dnsSaved !== '' && !in_array($dnsSaved, $dnsList, true)) {
        array_unshift($dnsList, $dnsSaved);
    }
    $vencimentoRaw = $userRow['vencimento'] ?? '';
    $vencimento = '';
    $ts = auth_parse_vencimento_to_timestamp($vencimentoRaw);
    if ($ts > 0) {
        $vencimento = date('Y-m-d H:i:s', $ts);
    }
    $deviceType = da_normalize_device_type((string)($userRow['device_type'] ?? $userRow['last_device_type'] ?? 'tv'));
    $accessProfile = da_get_profile_by_key($db, da_user_key($username, $password));
    $dnsClean = array_values(array_unique(array_filter(array_map('auth_normalize_dns', $dnsList))));
    return array_merge([
        'status' => 'ok',
        'mac_registered' => true,
        'mac_pending' => false,
        'mac_has_credentials' => true,
        'logout' => false,
        'dns' => $dnsClean,
        'dns_list' => $dnsClean,
        'dns_selected' => $dnsSaved,
        'username' => $username,
        'password' => $password,
        'vencimento' => $vencimento,
        'nome_cliente' => trim((string)($userRow['nome_cliente'] ?? $userRow['nome'] ?? '')),
        'whatsapp' => trim((string)($userRow['whatsapp'] ?? '')),
        'login_mode' => trim((string)($userRow['login_mode'] ?? 'normal')),
        'activation_code' => trim((string)($userRow['activation_code'] ?? '')),
        'device_type' => $deviceType,
        'allow_tv' => $accessProfile['allow_tv'],
        'allow_mobile' => $accessProfile['allow_mobile'],
        'allow_movies' => $accessProfile['allow_movies'],
        'allow_series' => $accessProfile['allow_series'],
        'allow_live' => $accessProfile['allow_live'],
        'server_ts' => time(),
    ], $extra);
}
