<?php

namespace App\Controllers\Admin;

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

class StorageSettings extends BaseController
{
    protected $settingModel;

    public function __construct()
    {
        $this->settingModel = new SchoolSettingModel();
    }

    private function checkAccess()
    {
        if (!session()->get('logged_in')) {
            return redirect()->to('/login');
        }

        $role = session()->get('user_role');
        if (!in_array($role, ['superadmin', 'admin'])) {
            return redirect()->to('/dashboard')->with('error', 'Anda tidak memiliki hak akses.');
        }

        return null;
    }

    /**
     * Halaman Utama Pengaturan Penyimpanan
     */
    public function index()
    {
        if ($redirect = $this->checkAccess()) return $redirect;

        $data = [
            'title'   => 'Pengaturan Penyimpanan File',
            'setting' => $this->settingModel->getSettings(),
        ];

        return view('settings/storage', $data);
    }

    /**
     * Menyimpan Konfigurasi Client & Folder
     */
    public function save()
    {
        if ($redirect = $this->checkAccess()) return $redirect;

        $setting = $this->settingModel->getSettings();
        if (!$setting) {
            return redirect()->to('/settings/storage')->with('error', 'Konfigurasi lembaga belum diinisialisasi.');
        }

        $storageDriver = $this->request->getPost('storage_driver') ?: 'local';
        $clientId      = $this->request->getPost('google_client_id');
        $clientSecret  = $this->request->getPost('google_client_secret');
        $folderId      = $this->request->getPost('google_drive_folder_id');
        
        $action = $this->request->getPost('action'); // 'save' atau 'disconnect'

        if ($action === 'disconnect') {
            $updateData = [
                'storage_driver'       => 'local', // otomatis balik ke lokal
                'google_refresh_token' => null
            ];
            if ($this->settingModel->update($setting['id'], $updateData)) {
                return redirect()->to('/settings/storage')->with('success', 'Integrasi Google Drive berhasil diputuskan. Driver diatur kembali ke Lokal.');
            }
            return redirect()->to('/settings/storage')->with('error', 'Gagal memutuskan integrasi.');
        }

        // Validasi input jika memilih Google Drive
        if ($storageDriver === 'google') {
            if (empty(trim($clientId)) || empty(trim($clientSecret)) || empty(trim($folderId))) {
                return redirect()->to('/settings/storage')->with('error', 'Untuk driver Google Drive, Client ID, Client Secret, dan Folder ID wajib diisi.');
            }
        }

        $updateData = [
            'storage_driver'         => $storageDriver,
            'google_client_id'       => trim($clientId),
            'google_client_secret'   => trim($clientSecret),
            'google_drive_folder_id' => trim($folderId)
        ];

        if ($this->settingModel->update($setting['id'], $updateData)) {
            return redirect()->to('/settings/storage')->with('success', 'Konfigurasi Penyimpanan File berhasil disimpan.');
        }

        return redirect()->to('/settings/storage')->with('error', 'Gagal memperbarui pengaturan.');
    }

    /**
     * Inisiasi Proses Otentikasi Google OAuth 2.0 (Redirect ke Google)
     */
    public function oauthInit()
    {
        if ($redirect = $this->checkAccess()) return $redirect;

        $settings = $this->settingModel->getSettings();
        if (empty($settings['google_client_id']) || empty($settings['google_client_secret'])) {
            return redirect()->to('/settings/storage')->with('error', 'Harap isi dan simpan Client ID dan Client Secret terlebih dahulu.');
        }

        try {
            $client = new Client();
            $client->setClientId(trim($settings['google_client_id']));
            $client->setClientSecret(trim($settings['google_client_secret']));
            $client->setRedirectUri(base_url('settings/storage/oauth-callback'));
            $client->addScope(Drive::DRIVE);
            $client->setAccessType('offline');
            $client->setPrompt('consent'); // Memaksa Google mengirimkan Refresh Token kembali

            $authUrl = $client->createAuthUrl();
            return redirect()->to($authUrl);
        } catch (\Throwable $e) {
            return redirect()->to('/settings/storage')->with('error', 'Gagal menginisiasi OAuth Google: ' . $e->getMessage());
        }
    }

    /**
     * Callback Handler setelah Login/Otorisasi Sukses di Google
     */
    public function oauthCallback()
    {
        if ($redirect = $this->checkAccess()) return $redirect;

        $code = $this->request->getGet('code');
        $error = $this->request->getGet('error');

        if ($error) {
            return redirect()->to('/settings/storage')->with('error', 'Otorisasi dibatalkan pengguna atau error: ' . esc($error));
        }

        if (empty($code)) {
            return redirect()->to('/settings/storage')->with('error', 'Authorization Code tidak ditemukan.');
        }

        $settings = $this->settingModel->getSettings();
        
        try {
            $client = new Client();
            $client->setClientId(trim($settings['google_client_id']));
            $client->setClientSecret(trim($settings['google_client_secret']));
            $client->setRedirectUri(base_url('settings/storage/oauth-callback'));

            // Tukarkan authorization code dengan Access/Refresh Token
            $token = $client->fetchAccessTokenWithAuthCode($code);

            if (isset($token['error'])) {
                return redirect()->to('/settings/storage')->with('error', 'Gagal mendapatkan token: ' . esc($token['error_description'] ?? $token['error']));
            }

            $refreshToken = $token['refresh_token'] ?? null;

            if (empty($refreshToken)) {
                // Kadang Google tidak mengembalikan refresh token jika akun sudah pernah dihubungkan sebelumnya.
                // Jika demikian, kita periksa apakah kita sudah punya refresh token tersimpan.
                if (!empty($settings['google_refresh_token'])) {
                    return redirect()->to('/settings/storage')->with('success', 'Google Drive berhasil dihubungkan ulang (menggunakan kunci refresh token yang sudah ada).');
                }
                
                return redirect()->to('/settings/storage')->with('error', 'Gagal mendapatkan Refresh Token. Silakan hapus izin aplikasi SIMAK di pengaturan akun Google Anda, lalu coba hubungkan kembali.');
            }

            // Simpan refresh token ke database
            $this->settingModel->update($settings['id'], [
                'google_refresh_token' => $refreshToken
            ]);

            return redirect()->to('/settings/storage')->with('success', 'Google Drive Berhasil Dihubungkan! Aplikasi kini dapat menyimpan data ke cloud Google Drive Anda.');

        } catch (\Throwable $e) {
            return redirect()->to('/settings/storage')->with('error', 'Terjadi kesalahan sistem saat otentikasi: ' . $e->getMessage());
        }
    }
}
