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

class Mycase extends CI_Controller
{
    private $authUrl  = "https://auth.mycase.com/login_sessions/new";
    private $tokenUrl = "https://auth.mycase.com/tokens";

    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('mycase_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 = "https://sugarfest.online/mycase/access.php";

        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('mycase_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('mycase_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  = 'https://sugarfest.online/mycase/access.php';

        $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;
        }
        $currentMs = round(microtime(true) * 1000);

        // Update the same document with tokens (unchanged)
        $db->collection('mycase_tokens')->document($lawId)->set([
            'lawId'         => $lawId,
            'client_id'     => $clientId,
            'client_secret' => $clientSecret,
            'redirect_uri'  => $redirectUri,
            'access_token'  => $tokens['access_token'],
            'refresh_token' => $tokens['refresh_token'],
            'expires_at'    => $currentMs + ($tokens['expires_in'] * 1000),
            'created_at'    => $currentMs,
            'updated_at'    => $currentMs
        ], ['merge' => true]);
        //update LawFirm collection
        $this->load->library('SyncService');
        $this->syncservice->updateSyncStatus($lawId, 'isMycaseSync', true);


        redirect(base_url('mycase/success'));
    }



    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('mycase_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('mycase_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('mycase_success');
    }

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

    // ------------------------
    // MyCase Document Methods
    // -------------------------

    /**
     * Fetch a firm document from MyCase
     * 
     * @param string $accessToken MyCase access token
     * @param string $mycaseDocId Firm document ID in MyCase
     * @return array ['success' => bool, 'fileName' => string, 'content' => binary, 'message' => string]
     */

    private function fetchFirmDocument($accessToken, $mycaseDocId)
    {
        // STEP 1 — Fetch document metadata
        $ch = curl_init("https://external-integrations.mycase.com/v1/documents/{$mycaseDocId}");
        curl_setopt_array($ch, [
            CURLOPT_HTTPHEADER => ["Authorization: Bearer $accessToken"],
            CURLOPT_RETURNTRANSFER => true
        ]);
        $res = curl_exec($ch);

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

        if ($httpCode != 200) {
            return ['success' => false, 'message' => 'Failed to fetch document metadata'];
        }

        $docData = json_decode($res, true);
        $fileName = $docData['filename'] ?? "document_{$mycaseDocId}.pdf";

        // STEP 2 — Download document content
        $downloadUrl = "https://external-integrations.mycase.com/v1/documents/{$mycaseDocId}/data";

        $ch = curl_init($downloadUrl);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,  // FOLLOW the 302 redirect
            CURLOPT_HTTPHEADER     => ["Authorization: Bearer $accessToken"],
            CURLOPT_BINARYTRANSFER => true
        ]);

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

        if ($httpCode != 200 || !$pdfContent) {
            return ['success' => false, 'message' => 'Failed to download document content'];
        }

        return [
            'success' => true,
            'fileName' => $fileName,
            'content' => $pdfContent
        ];
    }

    /**
     * Upload a document to a specific case in MyCase, optionally assign to client/user
     * 
     * @param string $accessToken MyCase access token
     * @param string $caseId Target case ID
     * @param string $fileName Name of the file to upload
     * @param string $pdfContent Binary content of the PDF
     * @param array|null $assignedTo Optional. Format: ['type' => 'client'|'user', 'id' => 12345]
     * @return array ['success' => bool, 'mycase_doc_id' => string, 'upload_code' => int, 'message' => string]
     */
    private function uploadDocumentToCase($accessToken, $caseId, $fileName, $pdfContent, $assignedTo = null)
    {
        // Create document payload
        $payload = [
            "path"        => "Cases/{$caseId}/" . $fileName,
            "filename"    => $fileName,
            "description" => "Uploaded from firm template"
        ];

        // Add assigned_to if provided
        if ($assignedTo && isset($assignedTo['type'], $assignedTo['id'])) {
            $payload['assigned_to'] = [
                'type' => $assignedTo['type'], // 'client' or 'user'
                'id'   => $assignedTo['id']
            ];
        }

        // Create document in MyCase
        $ch = curl_init("https://external-integrations.mycase.com/v1/cases/{$caseId}/documents");
        curl_setopt_array($ch, [
            CURLOPT_HTTPHEADER => [
                "Authorization: Bearer $accessToken",
                "Content-Type: application/json"
            ],
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_RETURNTRANSFER => true
        ]);
        $res = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode != 201) {
            return ['success' => false, 'message' => 'Failed to create document in MyCase', 'upload_code' => $httpCode];
        }

        $doc = json_decode($res, true);
        $putUrl = $doc['put_url'] ?? null;
        $putHeaders = $doc['put_headers'] ?? [];

        if (!$putUrl) {
            return ['success' => false, 'message' => 'Failed to get PUT URL for upload', 'upload_code' => $httpCode];
        }

        // Upload PDF content to S3
        $headers = [];
        foreach ($putHeaders as $key => $value) $headers[] = "$key: $value";
        $headers[] = "Content-Length: " . strlen($pdfContent);
        if (!isset($putHeaders['Content-Type'])) $headers[] = "Content-Type: application/octet-stream";

        $ch = curl_init($putUrl);
        curl_setopt_array($ch, [
            CURLOPT_CUSTOMREQUEST => "PUT",
            CURLOPT_POSTFIELDS => $pdfContent,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false
        ]);
        curl_exec($ch);
        $uploadCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        return [
            'success' => ($uploadCode == 200 || $uploadCode == 204),
            'mycase_doc_id' => $doc['id'] ?? null,
            'upload_code' => $uploadCode,
            'message' => ($uploadCode == 200 || $uploadCode == 204) ? 'Uploaded successfully' : 'Upload failed'
        ];
    }



    /**
     * Controller endpoint to fetch firm doc and upload to a case
     */
    public function fetchAndUploadFirmDoc()
    {
        $caseId      = $this->input->post('case_id');
        $envelopeId  = $this->input->post('mycase_doc_id'); // same as DocuSign envelopeId
        $client_id   = $this->input->post('client_id');
        $lawId       = $this->input->post('lawId') ?? null;

        // Read JSON body if POST is empty
        if (!$caseId || !$envelopeId) {
            $json = json_decode(file_get_contents('php://input'), true);
            if ($json) {
                $caseId     = $caseId ?? ($json['case_id'] ?? null);
                $envelopeId = $envelopeId ?? ($json['mycase_doc_id'] ?? null);
                $client_id  = $client_id ?? ($json['client_id'] ?? null);
                $lawId      = $lawId ?? ($json['lawId'] ?? null);
            }
        }

        if (!$caseId || !$envelopeId || !$lawId) {
            echo json_encode(['success' => false, 'message' => 'case_id, client_id and mycase_doc_id are required']);
            return;
        }

        // $base_url = "https://buzzwaretechserver.site/duepro_docusign_apis/index.php";
        $base_url = "https://buzzwaretechserver.site/test_docusign_apis/index.php";

        $fetchApiUrl = "{$base_url}/docusign/fetchDocusignDocument?envelopeId={$envelopeId}";

        $ch = curl_init($fetchApiUrl);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Accept: application/json'
            ]
        ]);

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

        if ($httpCode !== 200) {
            echo json_encode([
                'success' => false,
                'message' => "Failed to call fetchDocusignDocument API. HTTP {$httpCode}"
            ]);
            return;
        }

        $fetch = json_decode($fetchResponse, true);
        if (!$fetch || !$fetch['success']) {
            echo json_encode($fetch ?? ['success' => false, 'message' => 'Invalid response from DocuSign API']);
            return;
        }

        // --- Step 2: Fetch MyCase access token ---
        if (!$lawId) {
            echo json_encode(['success' => false, 'message' => 'lawId is required for MyCase token']);
            return;
        }

        $tokenResult = $this->fetchAccessToken($lawId);
        if (!$tokenResult['success']) {
            echo json_encode($tokenResult);
            return;
        }

        $accessToken = $tokenResult['access_token'];

        // --- Step 3: Upload the PDF to MyCase ---
        $assignedTo = [
            'type' => 'client',
            'id'   => $client_id
        ];

        // DocuSign API returned base64 PDF → decode it
        $pdfContent = base64_decode($fetch['content']);

        $upload = $this->uploadDocumentToCase($accessToken, $caseId, $fetch['fileName'], $pdfContent, $assignedTo);

        echo json_encode($upload);
    }


    public function createClient()
    {
        // Read input JSON
        $input = json_decode(file_get_contents('php://input'), true);

        $lawId = $input['lawId'] ?? null;
        $userData = $input['userData'] ?? null;

        if (!$lawId || !$userData) {
            echo json_encode([
                'success' => false,
                'message' => 'lawId and userData are required'
            ]);
            return;
        }

        // Fetch access token internally using the helper
        $tokenResult = $this->fetchAccessToken($lawId);
        if (!$tokenResult['success']) {
            echo json_encode($tokenResult);
            return;
        }

        $accessToken = $tokenResult['access_token'];

        // Call MyCase API to create client
        $ch = curl_init("https://external-integrations.mycase.com/v1/clients");
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "Authorization: Bearer $accessToken",
                "Content-Type: application/json",
                "Accept: application/json"
            ],
            CURLOPT_POSTFIELDS => json_encode($userData)
        ]);

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

        // Forward MyCase response exactly as JSON
        header('Content-Type: application/json');
        http_response_code($httpCode); // optional: forward HTTP code from MyCase
        echo $res;
    }

    public function createCase()
    {
        // Read input JSON
        $input = json_decode(file_get_contents('php://input'), true);

        $lawId = $input['lawId'] ?? null;
        $caseData = $input['caseData'] ?? null;

        if (!$lawId || !$caseData) {
            echo json_encode([
                'success' => false,
                'message' => 'lawId and caseData are required'
            ]);
            return;
        }

        // Fetch access token internally using the helper
        $tokenResult = $this->fetchAccessToken($lawId);
        if (!$tokenResult['success']) {
            echo json_encode($tokenResult);
            return;
        }

        $accessToken = $tokenResult['access_token'];

        // Call MyCase API to create case
        $ch = curl_init("https://external-integrations.mycase.com/v1/cases");
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "Authorization: Bearer $accessToken",
                "Content-Type: application/json",
                "Accept: application/json"
            ],
            CURLOPT_POSTFIELDS => json_encode($caseData)
        ]);

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

        // Forward MyCase response exactly as JSON
        header('Content-Type: application/json');
        http_response_code($httpCode); // optional: forward HTTP code from MyCase
        echo $res;
    }
}
