<?php
require_once __DIR__ . '/../../core/config.php';
require_once __DIR__ . '/../../core/database.php';

class CrmCalendarService
{
    private $pdo;
    private $userId;
    private $accessToken;

    public function __construct($userId)
    {
        $this->pdo = db();
        $this->userId = $userId;
        $this->loadTokens();
    }

    private function loadTokens()
    {
        if (!$this->userId) return;
        
        $stmt = $this->pdo->prepare("SELECT google_access_token, google_refresh_token, google_token_expires FROM users WHERE id = ? LIMIT 1");
        $stmt->execute([$this->userId]);
        $user = $stmt->fetch();

        // 🚀 CORRECCIÓN: Si no hay token de acceso, abortamos. 
        // Ya no exigimos estrictamente el refresh_token si el token actual está vigente.
        if (!$user || empty($user['google_access_token'])) {
            error_log("CrmCalendarService: No hay access_token para el usuario ID {$this->userId}");
            return;
        }

        // Si el token expira en menos de 5 minutos, intentamos renovarlo
        if (strtotime($user['google_token_expires']) <= (time() + 300)) {
            
            // Solo podemos renovar si Google nos dio el refresh_token
            if (!empty($user['google_refresh_token'])) {
                $ch = curl_init('https://oauth2.googleapis.com/token');
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
                curl_setopt($ch, CURLOPT_TIMEOUT, 20);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
                    'client_id' => GOOGLE_CLIENT_ID,
                    'client_secret' => GOOGLE_CLIENT_SECRET,
                    'refresh_token' => $user['google_refresh_token'],
                    'grant_type' => 'refresh_token'
                ]));
                $rawResponse = curl_exec($ch);
                $curlError = curl_error($ch);
                $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);

                $response = $rawResponse !== false ? json_decode($rawResponse, true) : null;

                if ($httpCode >= 200 && $httpCode < 300 && is_array($response) && isset($response['access_token'])) {
                    $this->accessToken = $response['access_token'];
                    $expires_at = date('Y-m-d H:i:s', time() + max(60, (int)($response['expires_in'] ?? 3599)));
                    $updateStmt = $this->pdo->prepare("UPDATE users SET google_access_token = ?, google_token_expires = ? WHERE id = ?");
                    $updateStmt->execute([$this->accessToken, $expires_at, $this->userId]);
                } else {
                    error_log("CrmCalendarService: Error al renovar token. HTTP {$httpCode}; cURL={$curlError}");
                }
            } else {
                error_log("CrmCalendarService: El token expiró y el usuario ID {$this->userId} no tiene refresh_token en la base de datos.");
            }
            
        } else {
            // 🚀 El token de acceso actual aún es válido, ¡lo usamos!
            $this->accessToken = $user['google_access_token'];
        }
    }

    public function addManualEvent($title, $start, $end, $isAllDay, $type, $oppId = null)
    {
        $googleId = null;
        if ($this->accessToken) {
            $description = "Evento manual creado desde el Calendario de ICYLAB OS.";
            if ($oppId) $description .= "\nAsociado a la Oportunidad ID: " . $oppId;
            
            $res = $this->createGoogleEvent($summary = $title, $description, $start, $end, $isAllDay);
            if (isset($res['id'])) {
                $googleId = $res['id'];
            }
        }

        $insert = $this->pdo->prepare("
            INSERT INTO crm_events 
            (opportunity_id, owner_user_id, event_type, title, start_date, end_date, is_all_day, google_event_id) 
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        ");
        $insert->execute([$oppId ?: 0, $this->userId, $type, $title, $start, $end, (int)$isAllDay, $googleId]);
        
        return $this->pdo->lastInsertId();
    }

    public function syncOpportunity($oppId, $customerName, $title, $data)
    {
        if (!$this->userId) return;

        // 1. Próxima Acción (Tiempos dinámicos)
        if (!empty($data['next_action']) && !empty($data['next_action_date'])) {
            $action = mb_strtolower($data['next_action'], 'UTF-8');
            $start = $data['next_action_date'] . ' 10:00:00';
            
            if (strpos($action, 'llamar') !== false) {
                $end = $data['next_action_date'] . ' 10:15:00'; // 15 min
            } elseif (strpos($action, 'reunión') !== false) {
                $end = $data['next_action_date'] . ' 11:00:00'; // 1 hr
            } else {
                $end = $data['next_action_date'] . ' 10:30:00'; // 30 min por defecto
            }
            $this->processEvent($oppId, 'accion', "ICYLAB: {$data['next_action']} - $customerName", $start, $end, false);
        } else {
            $this->deleteEventIfExist($oppId, 'accion');
        }

        // 2. Cierre Estimado (Todo el día)
        if (!empty($data['expected_close_date'])) {
            $this->processEvent($oppId, 'cierre', "Cierre Esperado: $title", $data['expected_close_date'], $data['expected_close_date'], true);
        } else {
            $this->deleteEventIfExist($oppId, 'cierre');
        }

        // 3. Vencimiento Pago (Todo el día)
        if (!empty($data['payment_due_date'])) {
            $this->processEvent($oppId, 'vencimiento', "Vencimiento Pago: $customerName", $data['payment_due_date'], $data['payment_due_date'], true);
        } else {
            $this->deleteEventIfExist($oppId, 'vencimiento');
        }

        // 4. Pago Recibido (Todo el día)
        if (!empty($data['payment_paid_date'])) {
            $this->processEvent($oppId, 'pago', "Pago Recibido: $customerName", $data['payment_paid_date'], $data['payment_paid_date'], true);
        } else {
            $this->deleteEventIfExist($oppId, 'pago');
        }
    }

    private function processEvent($oppId, $type, $title, $start, $end, $isAllDay)
    {
        $stmt = $this->pdo->prepare("SELECT * FROM crm_events WHERE opportunity_id = ? AND event_type = ? LIMIT 1");
        $stmt->execute([$oppId, $type]);
        $existing = $stmt->fetch();

        if ($existing) {
            if ($existing['start_date'] !== $start || $existing['title'] !== $title) {
                $googleId = $existing['google_event_id'];
                if ($this->accessToken && $googleId) {
                    $this->updateGoogleEvent($googleId, $title, $start, $end, $isAllDay);
                }
                $update = $this->pdo->prepare("UPDATE crm_events SET title = ?, start_date = ?, end_date = ? WHERE id = ?");
                $update->execute([$title, $start, $end, $existing['id']]);
            }
        } else {
            $googleId = null;
            if ($this->accessToken) {
                $res = $this->createGoogleEvent($title, "Link: https://" . $_SERVER['HTTP_HOST'] . "/modules/crm/opportunity.php?id=$oppId", $start, $end, $isAllDay);
                if (isset($res['id'])) $googleId = $res['id'];
            }
            $insert = $this->pdo->prepare("INSERT INTO crm_events (opportunity_id, owner_user_id, event_type, title, start_date, end_date, is_all_day, google_event_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
            $insert->execute([$oppId, $this->userId, $type, $title, $start, $end, (int)$isAllDay, $googleId]);
        }
    }

    private function deleteEventIfExist($oppId, $type)
    {
        $stmt = $this->pdo->prepare("SELECT id, google_event_id FROM crm_events WHERE opportunity_id = ? AND event_type = ? LIMIT 1");
        $stmt->execute([$oppId, $type]);
        $existing = $stmt->fetch();

        if ($existing) {
            if ($this->accessToken && $existing['google_event_id']) {
                $this->makeApiCall('DELETE', "https://www.googleapis.com/calendar/v3/calendars/primary/events/{$existing['google_event_id']}");
            }
            $del = $this->pdo->prepare("DELETE FROM crm_events WHERE id = ?");
            $del->execute([$existing['id']]);
        }
    }

    private function createGoogleEvent($summary, $description, $start, $end, $isAllDay)
    {
        $event = ['summary' => $summary, 'description' => $description];
        if ($isAllDay) {
            $event['start'] = ['date' => substr($start, 0, 10)];
            $event['end'] = ['date' => date('Y-m-d', strtotime(substr($start, 0, 10) . ' +1 day'))];
        } else {
            $event['start'] = ['dateTime' => str_replace(' ', 'T', $start) . '-04:00', 'timeZone' => 'America/Santiago'];
            $event['end'] = ['dateTime' => str_replace(' ', 'T', $end) . '-04:00', 'timeZone' => 'America/Santiago'];
        }
        return $this->makeApiCall('POST', 'https://www.googleapis.com/calendar/v3/calendars/primary/events', $event);
    }

    private function updateGoogleEvent($eventId, $summary, $start, $end, $isAllDay)
    {
        $event = ['summary' => $summary];
        if ($isAllDay) {
            $event['start'] = ['date' => substr($start, 0, 10)];
            $event['end'] = ['date' => date('Y-m-d', strtotime(substr($start, 0, 10) . ' +1 day'))];
        } else {
            $event['start'] = ['dateTime' => str_replace(' ', 'T', $start) . '-04:00', 'timeZone' => 'America/Santiago'];
            $event['end'] = ['dateTime' => str_replace(' ', 'T', $end) . '-04:00', 'timeZone' => 'America/Santiago'];
        }
        return $this->makeApiCall('PUT', "https://www.googleapis.com/calendar/v3/calendars/primary/events/{$eventId}", $event);
    }

    private function makeApiCall($method, $url, $data = null)
    {
        if (strpos((string)$url, 'https://www.googleapis.com/calendar/') !== 0) {
            error_log('CrmCalendarService: URL de Calendar no permitida.');
            return [];
        }

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $this->accessToken, 'Content-Type: application/json']);
        if ($data) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        $response = curl_exec($ch);
        $curlError = curl_error($ch);
        $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($response === false || $httpCode < 200 || $httpCode >= 300) {
            error_log("CrmCalendarService: Google Calendar fallo. HTTP {$httpCode}; cURL={$curlError}");
            return [];
        }

        if ($response === '' || $httpCode === 204) {
            return [];
        }

        $decoded = json_decode($response, true);
        return is_array($decoded) ? $decoded : [];
    }
}
