<?php

namespace App\Services;

use App\Models\GoogleMeetConfiguration;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * GoogleMeetConfigurationService
 *
 * Manages CRUD operations for Google Meet OAuth2 credentials.
 */
class GoogleMeetConfigurationService
{
    public function getConfiguration(): ?GoogleMeetConfiguration
    {
        return GoogleMeetConfiguration::getActive();
    }

    public function getConfigurationOrFail(): GoogleMeetConfiguration
    {
        $config = $this->getConfiguration();

        if (!$config) {
            // Redirect gracefully instead of throwing — callers should check isConfigured() first
            throw new \RuntimeException('Google Meet configuration not found. Please configure the integration first.');
        }

        return $config;
    }

    /**
     * Get configuration or redirect to create page.
     * Returns null if not configured (callers should redirect).
     */
    public function getConfigurationOrNull(): ?GoogleMeetConfiguration
    {
        return $this->getConfiguration();
    }

    public function saveConfiguration(array $data): GoogleMeetConfiguration
    {
        return DB::transaction(function () use ($data) {
            GoogleMeetConfiguration::query()->update(['is_active' => false]);

            $config = GoogleMeetConfiguration::create([
                'client_id'     => $data['client_id'],
                'client_secret' => $data['client_secret'],
                'redirect_uri'  => $data['redirect_uri'],
                'is_active'     => true,
            ]);

            Log::info('Google Meet configuration saved', [
                'config_id'    => $config->id,
                'redirect_uri' => $config->redirect_uri,
            ]);

            return $config;
        });
    }

    public function updateConfiguration(GoogleMeetConfiguration $config, array $data): GoogleMeetConfiguration
    {
        $config->update([
            'client_id'     => $data['client_id']     ?? $config->client_id,
            'client_secret' => $data['client_secret'] ?? $config->client_secret,
            'redirect_uri'  => $data['redirect_uri']  ?? $config->redirect_uri,
        ]);

        if (isset($data['client_id']) || isset($data['client_secret'])) {
            $this->clearTokens($config);
        }

        Log::info('Google Meet configuration updated', ['config_id' => $config->id]);

        return $config;
    }

    public function deleteConfiguration(): bool
    {
        $config = $this->getConfiguration();

        if (!$config) {
            return false;
        }

        $config->delete();

        Log::info('Google Meet configuration deleted', ['config_id' => $config->id]);

        return true;
    }

    public function isConfigured(): bool
    {
        return GoogleMeetConfiguration::isConfigured();
    }

    public function isAuthenticated(): bool
    {
        return GoogleMeetConfiguration::isAuthenticated();
    }

    public function storeTokens(GoogleMeetConfiguration $config, array $tokenData): GoogleMeetConfiguration
    {
        $config->update([
            'access_token'     => $tokenData['access_token'],
            'refresh_token'    => $tokenData['refresh_token'] ?? $config->refresh_token,
            'token_expires_at' => now()->addSeconds($tokenData['expires_in']),
        ]);

        Log::info('Google Meet OAuth tokens stored', [
            'config_id'  => $config->id,
            'expires_in' => $tokenData['expires_in'] ?? 'unknown',
        ]);

        return $config;
    }

    public function clearTokens(GoogleMeetConfiguration $config): void
    {
        $config->update([
            'access_token'     => null,
            'refresh_token'    => null,
            'token_expires_at' => null,
        ]);

        Log::info('Google Meet OAuth tokens cleared', ['config_id' => $config->id]);
    }

    public function updateAccessToken(GoogleMeetConfiguration $config, string $accessToken, int $expiresIn): void
    {
        $config->update([
            'access_token'     => $accessToken,
            'token_expires_at' => now()->addSeconds($expiresIn),
        ]);

        Log::info('Google Meet access token updated', [
            'config_id'  => $config->id,
            'expires_in' => $expiresIn,
        ]);
    }

    public function getStatusSummary(): array
    {
        $config = $this->getConfiguration();

        if (!$config) {
            return [
                'configured'              => false,
                'authenticated'           => false,
                'has_valid_token'         => false,
                'minutes_until_expiration' => null,
                'config_id'               => null,
            ];
        }

        return [
            'configured'              => true,
            'authenticated'           => $config->hasTokens(),
            'has_valid_token'         => $config->hasValidToken(),
            'minutes_until_expiration' => $config->getMinutesUntilExpiration(),
            'config_id'               => $config->id,
            'created_at'              => $config->created_at,
            'updated_at'              => $config->updated_at,
        ];
    }

    public function getCredentials(): ?array
    {
        $config = $this->getConfiguration();

        if (!$config) {
            return null;
        }

        return [
            'client_id'     => $config->client_id,
            'client_secret' => $config->client_secret,
            'redirect_uri'  => $config->redirect_uri,
            'access_token'  => $config->access_token,
            'refresh_token' => $config->refresh_token,
        ];
    }
}
