<?php
declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

function drak_json(array $payload, int $status = 200): void
{
    http_response_code($status);
    echo json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    exit;
}

function drak_load_env(string $path): void
{
    if (!is_file($path)) {
        return;
    }

    $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    if ($lines === false) {
        return;
    }

    foreach ($lines as $line) {
        $line = trim($line);
        if ($line === '' || $line[0] === '#' || strpos($line, '=') === false) {
            continue;
        }

        [$key, $value] = explode('=', $line, 2);
        $key = trim($key);
        $value = trim(trim($value), "\"'");
        if ($key !== '' && getenv($key) === false) {
            putenv($key . '=' . $value);
            $_ENV[$key] = $value;
            $_SERVER[$key] = $value;
        }
    }
}

function drak_env(string $key, string $default = ''): string
{
    $value = getenv($key);
    return $value === false || $value === '' ? $default : $value;
}

function drak_env_first(array $keys, string $default = ''): string
{
    foreach ($keys as $key) {
        $value = drak_env((string)$key);
        if ($value !== '') {
            return $value;
        }
    }
    return $default;
}

function drak_normalize_mac(string $value): string
{
    $clean = drak_clean_mac($value);
    if (strlen($clean) < 12) {
        return '';
    }
    $clean = substr($clean, 0, 12);
    return implode(':', str_split($clean, 2));
}

function drak_clean_mac(string $value): string
{
    return strtoupper(preg_replace('/[^0-9A-Fa-f]/', '', $value) ?? '');
}

function drak_body(): array
{
    $raw = file_get_contents('php://input');
    if ($raw === false || trim($raw) === '') {
        return $_POST;
    }

    $json = json_decode($raw, true);
    return is_array($json) ? $json : $_POST;
}


function drak_server_path(string $path): string
{
    return str_replace('/', DIRECTORY_SEPARATOR, $path);
}

function drak_connect_shared_db(array $paths): ?PDO
{
    foreach ($paths as $path) {
        $path = trim((string)$path);
        if ($path === '' || !is_file($path)) {
            continue;
        }

        require_once $path;
        if (function_exists('db')) {
            $candidate = db();
            if ($candidate instanceof PDO) {
                $candidate->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                $candidate->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
                return $candidate;
            }
        }
        if (isset($GLOBALS['pdo']) && $GLOBALS['pdo'] instanceof PDO) {
            $GLOBALS['pdo']->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $GLOBALS['pdo']->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
            return $GLOBALS['pdo'];
        }
    }

    return null;
}
function drak_pdo(): PDO
{
    static $pdo = null;
    if ($pdo instanceof PDO) {
        return $pdo;
    }

    foreach ([
        drak_server_path('/var/www/smat-dev/.draktv-db.env'),
        drak_server_path('/var/www/smat-dev/.env'),
        drak_server_path('/var/www/smart-dev/.draktv-db.env'),
        drak_server_path('/var/www/smart-dev/.env'),
        dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . '.draktv-db.env',
        dirname(__DIR__) . DIRECTORY_SEPARATOR . '.draktv-db.env',
        dirname(__DIR__) . DIRECTORY_SEPARATOR . '.env',
        __DIR__ . DIRECTORY_SEPARATOR . '.env',
    ] as $envPath) {
        drak_load_env($envPath);
    }

    $shared = drak_connect_shared_db([
        drak_env('DRAK_API_SHARED_DB_FILE'),
        drak_server_path('/var/www/smat-dev/includes/db.php'),
        drak_server_path('/var/www/smart-dev/includes/db.php'),
        dirname(__DIR__) . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'db.php',
    ]);
    if ($shared instanceof PDO) {
        $pdo = $shared;
        return $pdo;
    }

    $pgName = drak_env('PGDATABASE');
    $pgUser = drak_env('PGUSER');
    if ($pgName !== '' && $pgUser !== '') {
        $host = drak_env('PGHOST', '127.0.0.1');
        $port = drak_env('PGPORT', '5432');
        $pass = drak_env('PGPASSWORD', '');
        $dsn = "pgsql:host={$host};port={$port};dbname={$pgName}";

        $pdo = new PDO($dsn, $pgUser, $pass, [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ]);
        return $pdo;
    }
$dbName = drak_env_first(['DB_NAME', 'MYSQL_DATABASE', 'MYSQL_DB']);
    $dbUser = drak_env_first(['DB_USER', 'MYSQL_USER']);
    if ($dbName !== '' && $dbUser !== '') {
        $host = drak_env_first(['DB_HOST', 'MYSQL_HOST'], 'localhost');
        $port = drak_env_first(['DB_PORT', 'MYSQL_PORT'], '3306');
        $pass = drak_env_first(['DB_PASS', 'DB_PASSWORD', 'MYSQL_PASSWORD'], '');
        $dsn = "mysql:host={$host};port={$port};dbname={$dbName};charset=utf8mb4";

        $pdo = new PDO($dsn, $dbUser, $pass, [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ]);
        return $pdo;
    }

    $shared = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'db.php';
    if (is_file($shared)) {
        require_once $shared;
        if (function_exists('db')) {
            $pdo = db();
            return $pdo;
        }
    }

    $pgName = drak_env('PGDATABASE');
    $pgUser = drak_env('PGUSER');
    if ($pgName !== '' && $pgUser !== '') {
        $host = drak_env('PGHOST', '127.0.0.1');
        $port = drak_env('PGPORT', '5432');
        $pass = drak_env('PGPASSWORD', '');
        $dsn = "pgsql:host={$host};port={$port};dbname={$pgName}";

        $pdo = new PDO($dsn, $pgUser, $pass, [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ]);
        return $pdo;
    }

    throw new RuntimeException('Database configuration missing');
}


function drak_pdo_driver(PDO $pdo): string
{
    try {
        return strtolower((string)$pdo->getAttribute(PDO::ATTR_DRIVER_NAME));
    } catch (Throwable $error) {
        return '';
    }
}

function drak_now_sql(PDO $pdo): string
{
    return drak_pdo_driver($pdo) === 'mysql' ? 'NOW(6)' : 'CURRENT_TIMESTAMP';
}

function drak_db_bool(PDO $pdo, bool $value)
{
    return drak_pdo_driver($pdo) === 'pgsql' ? $value : ($value ? 1 : 0);
}
function drak_uuid(): string
{
    $bytes = random_bytes(16);
    $bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x40);
    $bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80);
    $hex = bin2hex($bytes);
    return substr($hex, 0, 8) . '-' .
        substr($hex, 8, 4) . '-' .
        substr($hex, 12, 4) . '-' .
        substr($hex, 16, 4) . '-' .
        substr($hex, 20, 12);
}

function drak_random_key(): string
{
    return (string)random_int(100000, 999999);
}

function drak_random_device_id(): string
{
    $hex = strtoupper(bin2hex(random_bytes(6)));
    return 'NF-' . substr($hex, 0, 4) . '-' . substr($hex, 4, 4) . '-' . substr($hex, 8, 4);
}

function drak_try_exec(PDO $pdo, string $sql): void
{
    try {
        $pdo->exec($sql);
    } catch (PDOException $error) {
        // Indexes may already exist or imported text columns may reject optional indexes.
    }
}

function drak_mac_sql(PDO $pdo, string $column): string
{
    if (drak_pdo_driver($pdo) === 'pgsql') {
        return "UPPER(REGEXP_REPLACE(COALESCE({$column}, ''), '[^0-9A-Fa-f]', '', 'g'))";
    }
    return "REPLACE(REPLACE(REPLACE(REPLACE(UPPER(COALESCE({$column}, '')), ':', ''), '-', ''), '.', ''), ' ', '')";
}

function drak_mysql_datetime(?string $value): ?string
{
    if ($value === null || trim($value) === '') {
        return null;
    }

    $timestamp = strtotime($value);
    if ($timestamp === false) {
        return $value;
    }
    return date('Y-m-d H:i:s', $timestamp);
}

function drak_ensure_schema(PDO $pdo): void
{
    static $done = false;
    if ($done) {
        return;
    }

    
    if (drak_pdo_driver($pdo) === 'pgsql') {
        drak_try_exec($pdo, 'CREATE EXTENSION IF NOT EXISTS pgcrypto');
        drak_try_exec($pdo, "
            CREATE TABLE IF NOT EXISTS device_activations (
                id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
                reseller_id uuid NULL,
                mac_address text NOT NULL,
                duration_type text NOT NULL DEFAULT 'year',
                credits_used numeric NOT NULL DEFAULT 0,
                activated_at timestamptz NOT NULL DEFAULT now(),
                expires_at timestamptz NULL,
                status text NOT NULL DEFAULT 'active',
                notes text NULL,
                created_at timestamptz NOT NULL DEFAULT now(),
                device_id text NULL,
                activation_code text NULL,
                playlist_url text NULL,
                epg_url text NULL,
                customer_email text NULL,
                customer_name text NULL,
                bound_at timestamptz NULL
            )
        ");
        drak_try_exec($pdo, "
            CREATE TABLE IF NOT EXISTS niceflix_devices (
                id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
                mac_address text NOT NULL,
                device_id text NOT NULL,
                device_key text NOT NULL,
                customer_email text NULL,
                customer_name text NULL,
                status text NOT NULL DEFAULT 'trial',
                trial_started_at timestamptz NOT NULL DEFAULT now(),
                expires_at timestamptz NULL,
                activation_code text NULL,
                reseller_id uuid NULL,
                last_seen_at timestamptz NOT NULL DEFAULT now(),
                last_ip text NULL,
                user_agent text NULL,
                created_at timestamptz NOT NULL DEFAULT now(),
                updated_at timestamptz NOT NULL DEFAULT now()
            )
        ");
        drak_try_exec($pdo, "
            CREATE TABLE IF NOT EXISTS niceflix_playlists (
                id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
                device_id uuid NOT NULL REFERENCES niceflix_devices(id) ON DELETE CASCADE,
                name text NOT NULL,
                playlist_url text NOT NULL,
                epg_url text NULL,
                is_protected boolean NOT NULL DEFAULT false,
                source text NOT NULL DEFAULT 'client',
                display_order integer NOT NULL DEFAULT 0,
                created_at timestamptz NOT NULL DEFAULT now(),
                updated_at timestamptz NOT NULL DEFAULT now()
            )
        ");
        drak_try_exec($pdo, "CREATE UNIQUE INDEX IF NOT EXISTS ux_niceflix_devices_mac_clean ON niceflix_devices (UPPER(REGEXP_REPLACE(mac_address, '[^0-9A-Fa-f]', '', 'g')))");
        drak_try_exec($pdo, "CREATE INDEX IF NOT EXISTS ix_device_activations_mac_clean ON device_activations (UPPER(REGEXP_REPLACE(mac_address, '[^0-9A-Fa-f]', '', 'g')))");
        drak_try_exec($pdo, 'CREATE INDEX IF NOT EXISTS ix_niceflix_playlists_device ON niceflix_playlists (device_id, display_order, created_at)');
        $done = true;
        return;
    }$pdo->exec("
        CREATE TABLE IF NOT EXISTS device_activations (
            id CHAR(36) NOT NULL PRIMARY KEY,
            reseller_id CHAR(36) NULL,
            mac_address VARCHAR(64) NOT NULL,
            duration_type VARCHAR(32) NOT NULL DEFAULT 'year',
            credits_used DECIMAL(10,2) NOT NULL DEFAULT 0,
            activated_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
            expires_at DATETIME NULL,
            status VARCHAR(32) NOT NULL DEFAULT 'active',
            notes TEXT NULL,
            created_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
            device_id VARCHAR(64) NULL,
            activation_code VARCHAR(120) NULL,
            playlist_url TEXT NULL,
            epg_url TEXT NULL,
            customer_email VARCHAR(255) NULL,
            customer_name VARCHAR(255) NULL,
            bound_at DATETIME NULL
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS niceflix_devices (
            id CHAR(36) NOT NULL PRIMARY KEY,
            mac_address VARCHAR(64) NOT NULL,
            device_id VARCHAR(64) NOT NULL,
            device_key VARCHAR(32) NOT NULL,
            customer_email VARCHAR(255) NULL,
            customer_name VARCHAR(255) NULL,
            status VARCHAR(32) NOT NULL DEFAULT 'trial',
            trial_started_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
            expires_at DATETIME NULL,
            activation_code VARCHAR(120) NULL,
            reseller_id CHAR(36) NULL,
            last_seen_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
            last_ip VARCHAR(64) NULL,
            user_agent TEXT NULL,
            created_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS niceflix_playlists (
            id CHAR(36) NOT NULL PRIMARY KEY,
            device_id CHAR(36) NOT NULL,
            name VARCHAR(255) NOT NULL,
            playlist_url TEXT NOT NULL,
            epg_url TEXT NULL,
            is_protected TINYINT(1) NOT NULL DEFAULT 0,
            source VARCHAR(32) NOT NULL DEFAULT 'client',
            display_order INT NOT NULL DEFAULT 0,
            created_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
            INDEX ix_niceflix_playlists_device (device_id, display_order, created_at)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");

    drak_try_exec($pdo, "CREATE INDEX ix_device_activations_mac ON device_activations (mac_address(64))");
    drak_try_exec($pdo, "CREATE INDEX ix_niceflix_devices_mac ON niceflix_devices (mac_address(64))");
    drak_try_exec($pdo, "CREATE INDEX ix_niceflix_devices_device_id ON niceflix_devices (device_id(64))");

    $done = true;
}

function drak_find_activation(PDO $pdo, string $mac): ?array
{
    $stmt = $pdo->prepare("
        SELECT *
        FROM device_activations
        WHERE " . drak_mac_sql($pdo, 'mac_address') . " = :mac_clean
          AND LOWER(COALESCE(status, '')) = 'active'
          AND (expires_at IS NULL OR expires_at >= " . drak_now_sql($pdo) . ")
        ORDER BY activated_at DESC, created_at DESC
        LIMIT 1
    ");
    $stmt->execute(['mac_clean' => drak_clean_mac($mac)]);
    $row = $stmt->fetch();
    return $row === false ? null : $row;
}

function drak_find_device(PDO $pdo, string $mac): ?array
{
    $stmt = $pdo->prepare("
        SELECT *
        FROM niceflix_devices
        WHERE " . drak_mac_sql($pdo, 'mac_address') . " = :mac_clean
        LIMIT 1
    ");
    $stmt->execute(['mac_clean' => drak_clean_mac($mac)]);
    $row = $stmt->fetch();
    return $row === false ? null : $row;
}

function drak_find_device_by_id(PDO $pdo, string $id): ?array
{
    $stmt = $pdo->prepare("SELECT * FROM niceflix_devices WHERE id = :id LIMIT 1");
    $stmt->execute(['id' => $id]);
    $row = $stmt->fetch();
    return $row === false ? null : $row;
}

function drak_sync_device(PDO $pdo, string $mac, ?string $deviceId = null, ?string $userAgent = null): array
{
    drak_ensure_schema($pdo);

    $activation = drak_find_activation($pdo, $mac);
    $device = drak_find_device($pdo, $mac);
    $nextDeviceId = $deviceId ?: ($activation['device_id'] ?? null) ?: ($device['device_id'] ?? null) ?: drak_random_device_id();
    $nextDeviceKey = $device['device_key'] ?? drak_random_key();
    $status = $activation ? 'active' : ($device['status'] ?? 'trial');
    $expires = $activation ? ($activation['expires_at'] ?? null) : ($device['expires_at'] ?? null);

    $expires = drak_mysql_datetime($expires);
    if ($expires === null) {
        $expires = $activation
            ? (new DateTimeImmutable('+100 years'))->format('Y-m-d H:i:s')
            : (new DateTimeImmutable('+7 days'))->format('Y-m-d H:i:s');
    }
    $now = drak_now_sql($pdo);

    if (!$device) {
        $id = drak_uuid();
        $stmt = $pdo->prepare("
            INSERT INTO niceflix_devices
                (id, mac_address, device_id, device_key, status, expires_at, reseller_id, activation_code, customer_email, customer_name, last_ip, user_agent, trial_started_at, last_seen_at, created_at, updated_at)
            VALUES
                (:id, :mac, :device_id, :device_key, :status, :expires_at, :reseller_id, :activation_code, :customer_email, :customer_name, :last_ip, :user_agent, {$now}, {$now}, {$now}, {$now})
        ");
        $stmt->execute([
            'id' => $id,
            'mac' => $mac,
            'device_id' => $nextDeviceId,
            'device_key' => $nextDeviceKey,
            'status' => $status,
            'expires_at' => $expires,
            'reseller_id' => $activation['reseller_id'] ?? null,
            'activation_code' => $activation['activation_code'] ?? null,
            'customer_email' => $activation['customer_email'] ?? null,
            'customer_name' => $activation['customer_name'] ?? null,
            'last_ip' => $_SERVER['REMOTE_ADDR'] ?? null,
            'user_agent' => $userAgent,
        ]);
        $created = drak_find_device_by_id($pdo, $id);
        if ($created !== null) {
            return $created;
        }
    }

    $stmt = $pdo->prepare("
        UPDATE niceflix_devices
        SET device_id = COALESCE(NULLIF(:device_id, ''), device_id),
            status = :status,
            expires_at = :expires_at,
            reseller_id = COALESCE(:reseller_id, reseller_id),
            activation_code = COALESCE(:activation_code, activation_code),
            customer_email = COALESCE(:customer_email, customer_email),
            customer_name = COALESCE(:customer_name, customer_name),
            last_ip = :last_ip,
            user_agent = COALESCE(:user_agent, user_agent),
            last_seen_at = {$now},
            updated_at = {$now}
        WHERE id = :id
    ");
    $stmt->execute([
        'id' => $device['id'],
        'device_id' => $nextDeviceId,
        'status' => $status,
        'expires_at' => $expires,
        'reseller_id' => $activation['reseller_id'] ?? null,
        'activation_code' => $activation['activation_code'] ?? null,
        'customer_email' => $activation['customer_email'] ?? null,
        'customer_name' => $activation['customer_name'] ?? null,
        'last_ip' => $_SERVER['REMOTE_ADDR'] ?? null,
        'user_agent' => $userAgent,
    ]);
    return drak_find_device_by_id($pdo, (string)$device['id']) ?: $device;
}

function drak_device_active(array $device): bool
{
    $status = strtolower((string)($device['status'] ?? ''));
    if ($status !== 'active' && $status !== 'trial') {
        return false;
    }
    if (empty($device['expires_at'])) {
        return true;
    }
    return strtotime((string)$device['expires_at']) >= time();
}

function drak_load_playlists(PDO $pdo, string $deviceUuid): array
{
    $cleanup = $pdo->prepare("
        DELETE FROM niceflix_playlists
        WHERE device_id = :device_id
          AND (
            LOWER(COALESCE(source, '')) <> 'client'
            OR LOWER(COALESCE(name, '')) LIKE '%demo%'
            OR LOWER(COALESCE(name, '')) LIKE '%sample%'
          )
    ");
    $cleanup->execute(['device_id' => $deviceUuid]);

    $stmt = $pdo->prepare("
        SELECT id, name, playlist_url, epg_url, is_protected, updated_at
        FROM niceflix_playlists
        WHERE device_id = :device_id
        ORDER BY display_order ASC, created_at ASC
    ");
    $stmt->execute(['device_id' => $deviceUuid]);
    return $stmt->fetchAll();
}

function drak_auth_payload(PDO $pdo, string $mac, ?string $deviceId = null, ?string $userAgent = null): array
{
    $device = drak_sync_device($pdo, $mac, $deviceId, $userAgent);
    return [
        'ok' => true,
        'device' => $device,
        'playlists' => drak_load_playlists($pdo, (string)$device['id']),
    ];
}
