<?php

namespace Core\App\Services;

/**
 * VideoMeetingService
 * Handles 3 providers: Jitsi (free), Daily.co (freemium), Whereby (freemium)
 */
class VideoMeetingService
{
    /* ─────────────────────────────────────────────
       ENSURE TABLE EXISTS (auto-migrate)
    ───────────────────────────────────────────── */
    private static function ensureTable(): void
    {
        try {
            \db()->exec("CREATE TABLE IF NOT EXISTS `video_meeting_settings` (
                `id`         int(11)     NOT NULL AUTO_INCREMENT,
                `provider`   varchar(50) NOT NULL,
                `api_key`    text        DEFAULT NULL,
                `extra`      longtext    DEFAULT NULL,
                `is_active`  tinyint(1)  NOT NULL DEFAULT 0,
                `created_at` timestamp   NOT NULL DEFAULT current_timestamp(),
                `updated_at` timestamp   NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
                PRIMARY KEY (`id`),
                UNIQUE KEY `uk_video_provider` (`provider`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        } catch (\Throwable $e) { /* ignore if already exists or no permission */ }
    }

    /* ─────────────────────────────────────────────
       LOAD ALL PROVIDERS FROM DB
    ───────────────────────────────────────────── */
    public static function loadAll(): array
    {
        self::ensureTable();
        $defaults = [
            'jitsi'  => ['provider' => 'jitsi',  'api_key' => '', 'is_active' => 0, 'extra' => ['domain' => 'meet.jit.si', 'room_prefix' => 'meeting']],
            'daily'  => ['provider' => 'daily',  'api_key' => '', 'is_active' => 0, 'extra' => ['subdomain' => '']],
            'whereby'=> ['provider' => 'whereby','api_key' => '', 'is_active' => 0, 'extra' => []],
        ];
        try {
            $rows = \db()->query("SELECT * FROM video_meeting_settings")->fetchAll(\PDO::FETCH_ASSOC);
            foreach ($rows as $row) {
                $key = $row['provider'];
                if (!isset($defaults[$key])) continue;
                $defaults[$key] = array_merge($defaults[$key], $row);
                $defaults[$key]['extra'] = !empty($row['extra']) ? (json_decode($row['extra'], true) ?: []) : $defaults[$key]['extra'];
            }
        } catch (\Throwable $e) { /* table may not exist yet */ }
        return $defaults;
    }

    /* ─────────────────────────────────────────────
       GET ACTIVE PROVIDER KEY
    ───────────────────────────────────────────── */
    public static function getActiveProviderKey(): string
    {
        try {
            $row = \db()->query("SELECT provider FROM video_meeting_settings WHERE is_active=1 LIMIT 1")->fetch(\PDO::FETCH_ASSOC);
            return $row['provider'] ?? 'jitsi';
        } catch (\Throwable $e) { return 'jitsi'; }
    }

    /* ─────────────────────────────────────────────
       IS VIDEO MEETING ENABLED?
    ───────────────────────────────────────────── */
    public static function isEnabled(): bool
    {
        self::ensureTable();
        try {
            $row = \db()->query("SELECT id FROM video_meeting_settings WHERE is_active=1 LIMIT 1")->fetch(\PDO::FETCH_ASSOC);
            return (bool)$row;
        } catch (\Throwable $e) { return false; }
    }

    /* ─────────────────────────────────────────────
       GET ACTIVE CONFIG
    ───────────────────────────────────────────── */
    public static function getActiveConfig(): ?array
    {
        try {
            $row = \db()->query("SELECT * FROM video_meeting_settings WHERE is_active=1 LIMIT 1")->fetch(\PDO::FETCH_ASSOC);
            if (!$row) return null;
            $row['extra'] = !empty($row['extra']) ? (json_decode($row['extra'], true) ?: []) : [];
            return $row;
        } catch (\Throwable $e) { return null; }
    }

    /* ─────────────────────────────────────────────
       GET ROOM URL FOR A MEETING
    ───────────────────────────────────────────── */
    public static function getRoomUrl(int $meetingId): ?string
    {
        $cfg = self::getActiveConfig();
        if (!$cfg) return null;

        $provider = $cfg['provider'];
        $apiKey   = $cfg['api_key'] ?? '';
        $extra    = $cfg['extra']   ?? [];

        switch ($provider) {
            case 'jitsi':
                return self::jitsiUrl($meetingId, $extra);

            case 'daily':
                if (empty($apiKey)) return null;
                return self::dailyUrl($meetingId, $apiKey, $extra);

            case 'whereby':
                if (empty($apiKey)) return null;
                return self::wherebyUrl($meetingId, $apiKey);
        }
        return null;
    }

    /* ─────────────────────────────────────────────
       PROVIDER: JITSI
    ───────────────────────────────────────────── */
    private static function jitsiUrl(int $meetingId, array $extra): string
    {
        $domain = trim($extra['domain'] ?? 'meet.jit.si');
        $prefix = trim($extra['room_prefix'] ?? 'meeting');
        if (!$domain) $domain = 'meet.jit.si';
        if (!$prefix) $prefix = 'meeting';
        // Clean domain (remove protocol if user typed it)
        $domain = preg_replace('#^https?://#', '', $domain);
        $domain = rtrim($domain, '/');
        return 'https://' . $domain . '/' . $prefix . '-' . $meetingId;
    }

    /* ─────────────────────────────────────────────
       PROVIDER: DAILY.CO
       Creates room deterministically (idempotent)
    ───────────────────────────────────────────── */
    private static function dailyUrl(int $meetingId, string $apiKey, array $extra): ?string
    {
        $roomName = 'mt-meeting-' . $meetingId;

        // Try to get existing room
        $ch = curl_init("https://api.daily.co/v1/rooms/{$roomName}");
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 8,
            CURLOPT_HTTPHEADER     => ["Authorization: Bearer {$apiKey}", "Content-Type: application/json"],
        ]);
        $body   = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $data = json_decode($body, true) ?: [];

        if ($status === 200 && !empty($data['url'])) {
            return $data['url'];
        }

        // Room doesn't exist → create it
        $ch = curl_init("https://api.daily.co/v1/rooms");
        $payload = json_encode([
            'name'       => $roomName,
            'privacy'    => 'public',
            'properties' => ['enable_chat' => true, 'enable_knocking' => false],
        ]);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => $payload,
            CURLOPT_TIMEOUT        => 10,
            CURLOPT_HTTPHEADER     => ["Authorization: Bearer {$apiKey}", "Content-Type: application/json"],
        ]);
        $body   = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $data = json_decode($body, true) ?: [];
        return $data['url'] ?? null;
    }

    /* ─────────────────────────────────────────────
       PROVIDER: WHEREBY
       Creates a meeting via API, returns hostRoomUrl
    ───────────────────────────────────────────── */
    private static function wherebyUrl(int $meetingId, string $apiKey): ?string
    {
        // Check if we have a cached URL in DB extra
        try {
            $row = \db()->prepare("SELECT extra FROM video_meeting_settings WHERE provider='whereby' LIMIT 1");
            $row->execute();
            $r = $row->fetch(\PDO::FETCH_ASSOC);
            if ($r) {
                $extra = json_decode($r['extra'] ?? '{}', true) ?: [];
                $rooms = $extra['rooms'] ?? [];
                if (!empty($rooms[$meetingId])) {
                    return $rooms[$meetingId];
                }
            }
        } catch (\Throwable $e) {}

        // Create new meeting via Whereby API
        $ch = curl_init("https://api.whereby.dev/v1/meetings");
        $payload = json_encode([
            'endDate'      => date('Y-m-d\TH:i:s\Z', strtotime('+30 days')),
            'fields'       => ['hostRoomUrl'],
        ]);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => $payload,
            CURLOPT_TIMEOUT        => 10,
            CURLOPT_HTTPHEADER     => ["Authorization: Bearer {$apiKey}", "Content-Type: application/json"],
        ]);
        $body   = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($status !== 201) return null;
        $data = json_decode($body, true) ?: [];
        $url  = $data['roomUrl'] ?? ($data['hostRoomUrl'] ?? null);
        if (!$url) return null;

        // Cache in DB
        try {
            $db   = \db();
            $stmt = $db->prepare("SELECT extra FROM video_meeting_settings WHERE provider='whereby' LIMIT 1");
            $stmt->execute();
            $row   = $stmt->fetch(\PDO::FETCH_ASSOC);
            $extra = json_decode($row['extra'] ?? '{}', true) ?: [];
            $extra['rooms'][$meetingId] = $url;
            $db->prepare("UPDATE video_meeting_settings SET extra=? WHERE provider='whereby'")
               ->execute([json_encode($extra, JSON_UNESCAPED_UNICODE)]);
        } catch (\Throwable $e) {}

        return $url;
    }

    /* ─────────────────────────────────────────────
       TEST CONNECTION
    ───────────────────────────────────────────── */
    public static function testConnection(string $provider, string $apiKey, array $extra = []): array
    {
        switch ($provider) {

            case 'jitsi':
                $domain = trim($extra['domain'] ?? 'meet.jit.si');
                $domain = preg_replace('#^https?://#', '', $domain);
                if (empty($domain)) return ['success' => false, 'error' => 'Domain is required'];
                return ['success' => true, 'message' => 'Jitsi is free — no API key needed. Domain: ' . $domain];

            case 'daily':
                if (empty($apiKey)) return ['success' => false, 'error' => 'API key is required'];
                $ch = curl_init("https://api.daily.co/v1");
                curl_setopt_array($ch, [
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_TIMEOUT        => 8,
                    CURLOPT_HTTPHEADER     => ["Authorization: Bearer {$apiKey}"],
                ]);
                $body   = curl_exec($ch);
                $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);
                if ($status === 200) return ['success' => true, 'message' => 'Daily.co connected successfully'];
                $err = json_decode($body, true)['error'] ?? "HTTP {$status}";
                return ['success' => false, 'error' => 'Daily.co: ' . $err];

            case 'whereby':
                if (empty($apiKey)) return ['success' => false, 'error' => 'API key is required'];
                $ch = curl_init("https://api.whereby.dev/v1/meetings?limit=1");
                curl_setopt_array($ch, [
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_TIMEOUT        => 8,
                    CURLOPT_HTTPHEADER     => ["Authorization: Bearer {$apiKey}"],
                ]);
                $body   = curl_exec($ch);
                $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);
                if ($status === 200) return ['success' => true, 'message' => 'Whereby connected successfully'];
                $err = json_decode($body, true)['message'] ?? "HTTP {$status}";
                return ['success' => false, 'error' => 'Whereby: ' . $err];
        }

        return ['success' => false, 'error' => 'Unknown provider'];
    }
}
