<?php
/**
 * progress_sync.php
 * Sincronização de progresso em tempo real entre TV e Celular.
 * Ações: push | pull | remove
 * Chave principal: MAC do dispositivo (resolvido para user_key via tabela usuarios)
 */

declare(strict_types=1);

require_once dirname(__DIR__) . '/_app_guard.php';
app_guard_validate();
require_once dirname(__DIR__) . '/_device_access.php';

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

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

function ps_out(array $payload): void {
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

// ── banco ──────────────────────────────────────────────────────────────────
try {
    $db = new PDO('sqlite:' . dirname(__DIR__) . '/db.db');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    $db->exec('PRAGMA journal_mode=WAL');
    $db->exec('PRAGMA synchronous=NORMAL');
} catch (Throwable $e) {
    ps_out(['status' => 'erro', 'message' => 'db_error']);
}

da_ensure_schema($db);
ps_ensure_schema($db);

// ── parâmetros comuns ──────────────────────────────────────────────────────
$action     = strtolower(trim((string)($_POST['action'] ?? 'pull')));
$mac        = trim((string)($_POST['mac'] ?? ''));
$deviceType = da_normalize_device_type((string)($_POST['device_type'] ?? 'tv'));
$userKey    = da_resolve_user_key_from_mac($db, $mac);

if ($userKey === '') {
    // MAC não cadastrado: retorna vazio (não bloqueia)
    ps_out(['status' => 'ok', 'items' => [], 'server_ts' => time()]);
}

// ── PUSH ───────────────────────────────────────────────────────────────────
if ($action === 'push') {
    $tipo     = ps_normalize_tipo((string)($_POST['tipo'] ?? 'movie'));
    $url      = trim((string)($_POST['url'] ?? ''));
    if ($url === '') ps_out(['status' => 'erro', 'message' => 'url_required']);

    $nome         = trim((string)($_POST['nome'] ?? ''));
    $logo         = trim((string)($_POST['logo'] ?? ''));
    $category     = trim((string)($_POST['category'] ?? ''));
    $position     = max(0, (int)($_POST['position'] ?? 0));
    $duration     = max(0, (int)($_POST['duration'] ?? 0));
    // Campos extras para séries
    $serieId      = trim((string)($_POST['serie_id'] ?? ''));
    $episodeId    = trim((string)($_POST['episode_id'] ?? ''));
    $episodeTitle = trim((string)($_POST['episode_title'] ?? ''));
    $season       = max(0, (int)($_POST['season'] ?? 0));
    $episode      = max(0, (int)($_POST['episode'] ?? 0));

    $ts = time();

    $st = $db->prepare("
        INSERT INTO progress_sync
            (user_key, tipo, nome, logo, url, category, position, duration,
             serie_id, episode_id, episode_title, season, episode,
             last_device_type, last_watched, updated_at)
        VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
        ON CONFLICT(user_key, tipo, url) DO UPDATE SET
            nome          = excluded.nome,
            logo          = excluded.logo,
            category      = excluded.category,
            position      = excluded.position,
            duration      = excluded.duration,
            serie_id      = excluded.serie_id,
            episode_id    = excluded.episode_id,
            episode_title = excluded.episode_title,
            season        = excluded.season,
            episode       = excluded.episode,
            last_device_type = excluded.last_device_type,
            last_watched  = excluded.last_watched,
            updated_at    = excluded.updated_at
    ");
    $ok = $st->execute([
        $userKey, $tipo, $nome, $logo, $url, $category,
        $position, $duration,
        $serieId, $episodeId, $episodeTitle, $season, $episode,
        $deviceType, $ts, $ts
    ]);

    // Espelhar também na tabela legada continue_watching_sync para retrocompatibilidade
    try {
        $stLeg = $db->prepare("
            INSERT INTO continue_watching_sync
                (user_key, tipo, nome, logo, url, category, position, duration,
                 last_watched, last_device_type, updated_at)
            VALUES (?,?,?,?,?,?,?,?,?,?,?)
            ON CONFLICT(user_key, tipo, url) DO UPDATE SET
                nome=excluded.nome, logo=excluded.logo,
                category=excluded.category, position=excluded.position,
                duration=excluded.duration, last_watched=excluded.last_watched,
                last_device_type=excluded.last_device_type,
                updated_at=excluded.updated_at
        ");
        $stLeg->execute([
            $userKey, $tipo, $nome, $logo, $url, $category,
            $position, $duration, $ts, $deviceType, $ts
        ]);
    } catch (Throwable $_) {}

    ps_out(['status' => $ok ? 'ok' : 'erro', 'server_ts' => $ts]);
}

// ── REMOVE ─────────────────────────────────────────────────────────────────
if ($action === 'remove') {
    $tipo = ps_normalize_tipo((string)($_POST['tipo'] ?? 'movie'));
    $url  = trim((string)($_POST['url'] ?? ''));
    if ($url === '') ps_out(['status' => 'erro', 'message' => 'url_required']);

    $st = $db->prepare('DELETE FROM progress_sync WHERE user_key=? AND tipo=? AND url=?');
    $ok = $st->execute([$userKey, $tipo, $url]);

    // espelha remoção na tabela legada
    try {
        $stL = $db->prepare('DELETE FROM continue_watching_sync WHERE user_key=? AND tipo=? AND url=?');
        $stL->execute([$userKey, $tipo, $url]);
    } catch (Throwable $_) {}

    ps_out(['status' => $ok ? 'ok' : 'erro', 'server_ts' => time()]);
}

// ── PULL (default) ─────────────────────────────────────────────────────────
$limit    = max(1, min(200, (int)($_POST['limit'] ?? 80)));
$since    = max(0, (int)($_POST['since'] ?? 0)); // timestamp Unix; 0 = tudo

if ($since > 0) {
    $st = $db->prepare('
        SELECT * FROM progress_sync
        WHERE user_key=? AND updated_at>=?
        ORDER BY last_watched DESC LIMIT ?
    ');
    $st->bindValue(1, $userKey, PDO::PARAM_STR);
    $st->bindValue(2, $since,   PDO::PARAM_INT);
    $st->bindValue(3, $limit,   PDO::PARAM_INT);
} else {
    $st = $db->prepare('
        SELECT * FROM progress_sync
        WHERE user_key=?
        ORDER BY last_watched DESC LIMIT ?
    ');
    $st->bindValue(1, $userKey, PDO::PARAM_STR);
    $st->bindValue(2, $limit,   PDO::PARAM_INT);
}
$st->execute();

$items = [];
while ($row = $st->fetch()) {
    $pos = (int)($row['position'] ?? 0);
    $dur = (int)($row['duration'] ?? 0);
    $pct = ($dur > 0) ? (int)round(($pos / $dur) * 100) : 0;
    $pct = max(0, min(100, $pct));

    $items[] = [
        'tipo'          => (string)($row['tipo']          ?? 'movie'),
        'nome'          => (string)($row['nome']          ?? ''),
        'logo'          => (string)($row['logo']          ?? ''),
        'url'           => (string)($row['url']           ?? ''),
        'category'      => (string)($row['category']      ?? ''),
        'position'      => $pos,
        'duration'      => $dur,
        'progress_pct'  => $pct,
        'serie_id'      => (string)($row['serie_id']      ?? ''),
        'episode_id'    => (string)($row['episode_id']    ?? ''),
        'episode_title' => (string)($row['episode_title'] ?? ''),
        'season'        => (int)($row['season']           ?? 0),
        'episode'       => (int)($row['episode']          ?? 0),
        'last_watched'  => (int)($row['last_watched']     ?? 0),
        'device_type'   => (string)($row['last_device_type'] ?? ''),
        'updated_at'    => (int)($row['updated_at']       ?? 0),
    ];
}

ps_out(['status' => 'ok', 'items' => $items, 'server_ts' => time()]);

// ── helpers ────────────────────────────────────────────────────────────────
function ps_normalize_tipo(string $raw): string {
    $v = strtolower(trim($raw));
    return in_array($v, ['movie', 'series', 'live'], true) ? $v : 'movie';
}

function ps_ensure_schema(PDO $db): void {
    $db->exec("CREATE TABLE IF NOT EXISTS progress_sync (
        id              INTEGER PRIMARY KEY AUTOINCREMENT,
        user_key        TEXT    NOT NULL,
        tipo            TEXT    NOT NULL DEFAULT 'movie',
        nome            TEXT    DEFAULT '',
        logo            TEXT    DEFAULT '',
        url             TEXT    NOT NULL,
        category        TEXT    DEFAULT '',
        position        INTEGER NOT NULL DEFAULT 0,
        duration        INTEGER NOT NULL DEFAULT 0,
        progress_pct    INTEGER NOT NULL DEFAULT 0,
        serie_id        TEXT    DEFAULT '',
        episode_id      TEXT    DEFAULT '',
        episode_title   TEXT    DEFAULT '',
        season          INTEGER DEFAULT 0,
        episode         INTEGER DEFAULT 0,
        last_device_type TEXT   DEFAULT 'tv',
        last_watched    INTEGER NOT NULL DEFAULT (strftime('%s','now')),
        updated_at      INTEGER NOT NULL DEFAULT (strftime('%s','now')),
        UNIQUE(user_key, tipo, url)
    )");
    $db->exec("CREATE INDEX IF NOT EXISTS idx_ps_user_watched  ON progress_sync(user_key, last_watched DESC)");
    $db->exec("CREATE INDEX IF NOT EXISTS idx_ps_user_updated  ON progress_sync(user_key, updated_at DESC)");
}
