<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Calendly extends CI_Controller
{
    private $authUrl  = "https://auth.calendly.com/oauth/authorize";
    private $tokenUrl = "https://auth.calendly.com/oauth/token";

    public function __construct()
    {
        parent::__construct();
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");

        $this->load->helper('url');
        $this->load->library('FirebaseLib');
    }

    public function index()
    {
        $this->load->view('calendly_connect');
    }

    // Step 1: Start OAuth flow
    public function connect_start()
    {
        $clientId     = $this->input->post('client_id');
        $clientSecret = $this->input->post('client_secret');
        $lawId        = $this->input->post('lawId') ?? null;

        if (!$lawId || trim($lawId) === '') {
            $this->showError('Invalid law Id: Cannot be empty.');
            return;
        }
        // $redirectUri = base_url('mycase_apis/calendly/access');
        // $redirectUri = "https://buzzwaretechserver.site/mycase_apis/calendly/access";
        $redirectUri = "http://localhost:8000/calendly/access";


        if (!$clientId || !$clientSecret) {
            $this->showError('Missing required fields!');
            return;
        }

        $state = bin2hex(random_bytes(16));

        // Store everything in one document with lawId
        $db = $this->firebaselib->getFirestore();
        $db->collection('calendly_tokens')->document($lawId)->set([
            'lawId'         => $lawId,
            'client_id'     => $clientId,
            'client_secret' => $clientSecret,
            'redirect_uri'  => $redirectUri,
            'state'         => $state,
            'created_at'    => round(microtime(true) * 1000)
        ]);

        $url = $this->authUrl . "?" . http_build_query([
            'response_type' => 'code',
            'client_id'     => $clientId,
            'redirect_uri'  => $redirectUri,
            'state'         => $state
        ]);

        redirect($url);
    }

    // Step 2: Callback after login → exchange code for tokens
    public function access()
    {
        $code  = $this->input->get('code');
        $state = $this->input->get('state');

        if (!$code || !$state) {
            $this->showError('Authorization failed!');
            return;
        }

        $db = $this->firebaselib->getFirestore();
        $query = $db->collection('calendly_tokens')->where('state', '==', $state)->documents();

        $lawId = null;
        $credentials = null;

        foreach ($query as $doc) {
            if ($doc->exists()) {
                $lawId = $doc->id();
                $credentials = $doc->data();
                break;
            }
        }

        if (!$lawId) {
            $this->showError('Invalid state!');
            return;
        }

        $clientId     = $credentials['client_id'];
        $clientSecret = $credentials['client_secret'];
        $redirectUri  = $credentials['redirect_uri'];

        // Step 1: Generate access token
        $tokens = $this->requestToken([
            'grant_type'    => 'authorization_code',
            'code'          => $code,
            'redirect_uri'  => $redirectUri,
            'client_id'     => $clientId,
            'client_secret' => $clientSecret
        ]);

        if (!isset($tokens['access_token'])) {
            $this->showError('Failed to get access tokens.');
            return;
        }

        $accessToken  = $tokens['access_token'];
        $refreshToken = $tokens['refresh_token'];
        $expiresIn    = $tokens['expires_in'];
        $tokenType    = $tokens['token_type'];
        $scopes       = $tokens['scope'] ?? null;

        $currentMs = round(microtime(true) * 1000);

        // Step 2: Fetch Calendly user details (VERY IMPORTANT)
        $userInfo = $this->fetchCalendlyUser($accessToken);

        if (!$userInfo['success']) {
            $this->showError('Token OK but failed fetching user: ' . $userInfo['message']);
            return;
        }

        $userResource = $userInfo['data']['resource'];

        $userUri       = $userResource['uri'];
        $userTimezone  = $userResource['timezone'];
        $orgUri = $userResource['organization']
            ?? $userResource['current_organization']
            ?? null;


        // Save everything
        $db->collection('calendly_tokens')->document($lawId)->set([
            'lawId'          => $lawId,
            'client_id'      => $clientId,
            'client_secret'  => $clientSecret,
            'redirect_uri'   => $redirectUri,

            // Tokens
            'access_token'   => $accessToken,
            'refresh_token'  => $refreshToken,
            'token_type'     => $tokenType,
            'scopes'         => $scopes,
            'expires_in'     => $expiresIn,
            'expires_at'     => $currentMs + ($expiresIn * 1000),

            // User info
            'user_uri'       => $userUri,
            'user_timezone'  => $userTimezone,
            'organization_uri' => $orgUri,


            // Timestamps
            'created_at'     => $credentials['created_at'] ?? $currentMs,
            'updated_at'     => $currentMs

        ], ['merge' => true]);
        //update LawFirm collection
        $this->load->library('SyncService');
        $this->syncservice->updateSyncStatus($lawId, 'isCalendlySync', true);


        redirect(base_url('calendly/success'));
    }
    private function fetchCalendlyUser($accessToken)
    {
        $url = "https://api.calendly.com/users/me";

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "Authorization: Bearer {$accessToken}",
                "Content-Type: application/json"
            ]
        ]);

        $res = curl_exec($ch);
        $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $json = json_decode($res, true);

        if ($http >= 400) {
            return ['success' => false, 'message' => $json['title'] ?? 'User fetch failed'];
        }

        return ['success' => true, 'data' => $json];
    }


    private function requestToken($data)
    {
        $ch = curl_init($this->tokenUrl);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query($data),
            CURLOPT_HTTPHEADER => ["Content-Type: application/x-www-form-urlencoded"]
        ]);

        $res = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $json = json_decode($res, true);

        if ($httpCode >= 400 || isset($json['error'])) {
            $errorDesc = $json['error_description'] ?? $json['error'] ?? 'Unknown error';
            $this->showError("Failed to get token: {$errorDesc}");
            return;
        }

        return $json;
    }

    private function fetchAccessToken($lawId)
    {
        $db = $this->firebaselib->getFirestore();
        $doc = $db->collection('calendly_tokens')->document($lawId)->snapshot();

        if (!$doc->exists()) {
            return ['success' => false, 'message' => 'No token found for lawId: ' . $lawId];
        }

        $tokenData = $doc->data();
        $currentMs = round(microtime(true) * 1000);

        $accessToken = $tokenData['access_token'] ?? null;
        $expiresAt = $tokenData['expires_at'] ?? 0;

        // Token valid
        if ($accessToken && $currentMs < $expiresAt) {
            return ['success' => true, 'access_token' => $accessToken];
        }

        // Refresh token
        $refreshToken = $tokenData['refresh_token'] ?? null;
        if (!$refreshToken) {
            return ['success' => false, 'message' => 'No refresh token available'];
        }

        $tokens = $this->requestToken([
            'grant_type' => 'refresh_token',
            'refresh_token' => $refreshToken,
            'client_id' => $tokenData['client_id'],
            'client_secret' => $tokenData['client_secret']
        ]);

        if (!isset($tokens['access_token'])) {
            return ['success' => false, 'message' => 'Failed to refresh token'];
        }

        // Update Firestore
        $db->collection('calendly_tokens')->document($lawId)->set([
            'access_token' => $tokens['access_token'],
            'refresh_token' => $tokens['refresh_token'],
            'expires_at' => $currentMs + ($tokens['expires_in'] * 1000),
            'updated_at' => $currentMs
        ], ['merge' => true]);

        return ['success' => true, 'access_token' => $tokens['access_token']];
    }

    // API endpoint
    public function getAccessToken($lawId = null)
    {
        if (!$lawId) {
            $lawId = $this->input->get('lawId');
        }

        if (!$lawId) {
            echo json_encode(['success' => false, 'message' => 'lawId parameter is required']);
            return;
        }

        $tokenResult = $this->fetchAccessToken($lawId);
        echo json_encode($tokenResult);
    }

    public function success()
    {
        $this->load->view('calendly_success');
    }

    private function showError($message)
    {
        $data = ['message' => $message];
        $this->load->view('calendly_error', $data);
    }
}
