<?php

namespace App\Services;

use App\Models\SchoolSettingModel;
use Google\Client;
use Google\Service\Drive;

class StorageService
{
    private static $settings = null;

    /**
     * Ambil pengaturan lembaga yang aktif
     */
    private static function getSettings()
    {
        if (self::$settings === null) {
            $model = new SchoolSettingModel();
            self::$settings = $model->getSettings();
        }
        return self::$settings;
    }

    /**
     * Inisialisasi Google Drive Service menggunakan OAuth 2.0
     */
    private static function getGoogleDriveService()
    {
        $settings = self::getSettings();
        if (!$settings || ($settings['storage_driver'] ?? 'local') !== 'google') {
            return null;
        }

        $clientId     = $settings['google_client_id'] ?? '';
        $clientSecret = $settings['google_client_secret'] ?? '';
        $refreshToken = $settings['google_refresh_token'] ?? '';

        if (empty(trim($clientId)) || empty(trim($clientSecret)) || empty(trim($refreshToken))) {
            log_message('error', 'Google Drive Service gagal diinisialisasi: Kredensial OAuth tidak lengkap.');
            return null;
        }

        try {
            $client = new Client();
            $client->setClientId(trim($clientId));
            $client->setClientSecret(trim($clientSecret));
            $client->addScope(Drive::DRIVE);
            
            // Konfigurasikan token menggunakan refresh token permanen
            $client->refreshToken(trim($refreshToken));
            
            return new Drive($client);
        } catch (\Throwable $e) {
            log_message('error', 'Inisialisasi Google Drive Service (OAuth) Gagal: ' . $e->getMessage());
            return null;
        }
    }

    /**
     * Mengunggah file (Mendukung Lokal & Google Drive secara dinamis)
     * 
     * @param \CodeIgniter\HTTP\Files\UploadedFile $file Objek file unggahan CI4
     * @param string $folder Sub-folder di dalam uploads/ (contoh: 'students', 'cards')
     * @return string|false Nama file jika Lokal, File ID jika Google Drive, false jika gagal
     */
    public static function upload($file, $folder = 'students')
    {
        if ($file === null || !$file->isValid()) {
            return false;
        }

        $settings = self::getSettings();
        $driver = $settings['storage_driver'] ?? 'local';

        if ($driver === 'google') {
            $service = self::getGoogleDriveService();
            if ($service === null) {
                log_message('error', 'Layanan Google Drive tidak aktif, beralih otomatis ke penyimpanan Lokal.');
                return self::uploadLocal($file, $folder);
            }

            try {
                $folderId = $settings['google_drive_folder_id'] ?? '';
                
                // Siapkan Metadata file Google Drive
                $driveFile = new Drive\DriveFile();
                $driveFile->setName($file->getRandomName());
                if (!empty($folderId)) {
                    $driveFile->setParents([$folderId]);
                }

                // Unggah isi konten file
                $content = file_get_contents($file->getTempName());
                $result = $service->files->create($driveFile, [
                    'data'       => $content,
                    'mimeType'   => $file->getClientMimeType(),
                    'uploadType' => 'multipart',
                    'fields'     => 'id'
                ]);

                $fileId = $result->id;

                // Ubah permission file agar "Siapa saja dengan link dapat melihat" (Read-only)
                try {
                    $permission = new Drive\Permission();
                    $permission->setType('anyone');
                    $permission->setRole('reader');
                    $service->permissions->create($fileId, $permission);
                } catch (\Throwable $pe) {
                    log_message('error', 'Gagal mengatur hak akses Google Drive File ID ' . $fileId . ': ' . $pe->getMessage());
                }

                return $fileId;
            } catch (\Throwable $e) {
                log_message('error', 'Gagal unggah file ke Google Drive: ' . $e->getMessage());
                // Fallback otomatis ke penyimpanan lokal agar aplikasi tidak berhenti
                return self::uploadLocal($file, $folder);
            }
        }

        return self::uploadLocal($file, $folder);
    }

    /**
     * Mengunggah file dari path lokal (Berguna untuk ekstrasi ZIP massal)
     * 
     * @param string $sourcePath Path file di lokal server
     * @param string $originalName Nama file target
     * @param string $mimeType Tipe MIME berkas
     * @param string $folder Subfolder
     * @return string|false
     */
    public static function uploadFromPath($sourcePath, $originalName, $mimeType, $folder = 'students')
    {
        if (!file_exists($sourcePath)) {
            return false;
        }

        $settings = self::getSettings();
        $driver = $settings['storage_driver'] ?? 'local';

        if ($driver === 'google') {
            $service = self::getGoogleDriveService();
            if ($service === null) {
                log_message('error', 'Layanan Google Drive tidak aktif, beralih otomatis ke penyimpanan Lokal.');
                return self::uploadLocalFromPath($sourcePath, $originalName, $folder);
            }

            try {
                $folderId = $settings['google_drive_folder_id'] ?? '';
                
                // Siapkan Metadata file Google Drive
                $driveFile = new Drive\DriveFile();
                $driveFile->setName($originalName);
                if (!empty($folderId)) {
                    $driveFile->setParents([$folderId]);
                }

                // Unggah isi konten file
                $content = file_get_contents($sourcePath);
                $result = $service->files->create($driveFile, [
                    'data'       => $content,
                    'mimeType'   => $mimeType,
                    'uploadType' => 'multipart',
                    'fields'     => 'id'
                ]);

                $fileId = $result->id;

                // Ubah permission file agar "Siapa saja dengan link dapat melihat" (Read-only)
                try {
                    $permission = new Drive\Permission();
                    $permission->setType('anyone');
                    $permission->setRole('reader');
                    $service->permissions->create($fileId, $permission);
                } catch (\Throwable $pe) {
                    log_message('error', 'Gagal mengatur hak akses Google Drive File ID ' . $fileId . ': ' . $pe->getMessage());
                }

                return $fileId;
            } catch (\Throwable $e) {
                log_message('error', 'Gagal unggah file ke Google Drive dari path: ' . $e->getMessage());
                return self::uploadLocalFromPath($sourcePath, $originalName, $folder);
            }
        }

        return self::uploadLocalFromPath($sourcePath, $originalName, $folder);
    }

    /**
     * Helper: Unggah file lokal dari path
     */
    private static function uploadLocalFromPath($sourcePath, $originalName, $folder)
    {
        $targetDir = FCPATH . 'uploads/' . $folder;
        if (!is_dir($targetDir)) {
            mkdir($targetDir, 0777, true);
        }
        
        $destPath = $targetDir . '/' . $originalName;
        if (copy($sourcePath, $destPath)) {
            return $originalName;
        }
        return false;
    }

    /**
     * Helper: Unggah file ke server lokal
     */
    private static function uploadLocal($file, $folder)
    {
        $newName = $file->getRandomName();
        $targetDir = FCPATH . 'uploads/' . $folder;
        if (!is_dir($targetDir)) {
            mkdir($targetDir, 0777, true);
        }
        
        if ($file->move($targetDir, $newName)) {
            return $newName;
        }
        return false;
    }

    /**
     * Mengambil URL File untuk Gambar (Mendukung Lokal & Google Drive)
     * 
     * @param string $photoValue Nama file lokal ATAU Google File ID
     * @param string $folder Nama subfolder
     * @param string $default Fallback gambar jika file kosong di assets/images/
     * @return string URL gambar lengkap
     */
    public static function getUrl($photoValue, $folder = 'students', $default = 'avatar.png')
    {
        if (empty($photoValue)) {
            return base_url('assets/images/' . $default);
        }

        $settings = self::getSettings();
        $driver = $settings['storage_driver'] ?? 'local';

        // Deteksi apakah photoValue merupakan nama file lokal (memiliki ekstensi berkas .jpg, .png, dll)
        $hasExtension = preg_match('/\.[a-zA-Z0-9]+$/', $photoValue);

        if ($driver === 'google' && !$hasExtension) {
            // Kembalikan thumbnail resmi Google Drive yang cepat dan terkompresi otomatis (lebar 400px)
            return 'https://drive.google.com/thumbnail?id=' . $photoValue . '&sz=w400';
        }

        // Pengecekan file lokal
        $localPath = FCPATH . 'uploads/' . $folder . '/' . $photoValue;
        if (file_exists($localPath)) {
            return base_url('uploads/' . $folder . '/' . $photoValue);
        }

        // Default avatar jika file tidak ditemukan
        return base_url('assets/images/' . $default);
    }

    /**
     * Menghapus file (Mendukung Lokal & Google Drive)
     * 
     * @param string $photoValue Nama file lokal ATAU Google File ID
     * @param string $folder Nama subfolder
     * @return bool
     */
    public static function delete($photoValue, $folder = 'students')
    {
        if (empty($photoValue)) {
            return true;
        }

        $settings = self::getSettings();
        $driver = $settings['storage_driver'] ?? 'local';
        $hasExtension = preg_match('/\.[a-zA-Z0-9]+$/', $photoValue);

        if ($driver === 'google' && !$hasExtension) {
            $service = self::getGoogleDriveService();
            if ($service !== null) {
                try {
                    $service->files->delete($photoValue);
                    return true;
                } catch (\Throwable $e) {
                    log_message('error', 'Gagal menghapus file di Google Drive: ' . $e->getMessage());
                    return false;
                }
            }
            return false;
        }

        // Hapus dari folder server lokal
        $localPath = FCPATH . 'uploads/' . $folder . '/' . $photoValue;
        if (file_exists($localPath)) {
            return unlink($localPath);
        }

        return true;
    }
}
