<?php

namespace App\Services;

use App\Models\Interview;
use App\Models\SiteSetting;
use App\Models\User;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class GoogleCalendarService
{
    protected string $baseUrl  = 'https://www.googleapis.com/calendar/v3';
    protected string $authUrl  = 'https://accounts.google.com/o/oauth2/v2/auth';
    protected string $tokenUrl = 'https://oauth2.googleapis.com/token';

    // ─── OAuth URL ────────────────────────────────────────────────────────────

    public function getAuthUrlForUser(User $user, ?string $state = null): string
    {
        $clientId    = SiteSetting::get('google_calendar_client_id');
        $redirectUri = $this->redirectUri();

        $params = http_build_query([
            'client_id'     => $clientId,
            'redirect_uri'  => $redirectUri,
            'response_type' => 'code',
            'scope'         => 'https://www.googleapis.com/auth/calendar',
            'access_type'   => 'offline',
            'prompt'        => 'consent',
            // state: dışarıdan verilen güvenli random string, yoksa user id kullan
            'state'         => $state ?? (string) $user->id,
        ]);

        return $this->authUrl . '?' . $params;
    }

    // ─── Callback: code → token, user'a kaydet ───────────────────────────────

    public function handleCallbackForUser(string $code, User $user): bool
    {
        $clientId     = SiteSetting::get('google_calendar_client_id');
        $clientSecret = SiteSetting::get('google_calendar_client_secret');
        $redirectUri  = $this->redirectUri();

        try {
            $response = Http::post($this->tokenUrl, [
                'code'          => $code,
                'client_id'     => $clientId,
                'client_secret' => $clientSecret,
                'redirect_uri'  => $redirectUri,
                'grant_type'    => 'authorization_code',
            ]);

            if (!$response->successful()) {
                Log::error('Google Calendar token exchange failed: ' . $response->body());
                return false;
            }

            $data = $response->json();

            $user->update([
                'google_access_token'    => $data['access_token'],
                'google_refresh_token'   => $data['refresh_token'] ?? $user->google_refresh_token,
                'google_token_expires_at'=> (int) (time() + ($data['expires_in'] ?? 3600)),
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Google Calendar callback error: ' . $e->getMessage());
            return false;
        }
    }

    // ─── Etkinlik oluştur ─────────────────────────────────────────────────────

    public function createEvent(Interview $interview): void
    {
        $user = $this->resolveUser($interview);
        if (!$user) return;

        $token      = $this->getAccessTokenForUser($user);
        $calendarId = $user->google_calendar_id ?: 'primary';

        if (!$token) return;

        try {
            $event    = $this->buildEventPayload($interview);
            $response = Http::withToken($token)
                ->post("{$this->baseUrl}/calendars/{$calendarId}/events", $event);

            if ($response->successful()) {
                $interview->update([
                    'google_event_id'    => $response->json('id'),
                    'google_calendar_id' => $calendarId,
                ]);
            } else {
                Log::warning('Google Calendar createEvent failed: ' . $response->body());
            }
        } catch (\Exception $e) {
            Log::error('Google Calendar createEvent error: ' . $e->getMessage());
        }
    }

    // ─── Etkinlik güncelle ────────────────────────────────────────────────────

    public function updateEvent(Interview $interview): void
    {
        if (!$interview->google_event_id) {
            $this->createEvent($interview);
            return;
        }

        $user = $this->resolveUser($interview);
        if (!$user) return;

        $token      = $this->getAccessTokenForUser($user);
        $calendarId = $interview->google_calendar_id ?: ($user->google_calendar_id ?: 'primary');

        if (!$token) return;

        try {
            $event    = $this->buildEventPayload($interview);
            $response = Http::withToken($token)
                ->put("{$this->baseUrl}/calendars/{$calendarId}/events/{$interview->google_event_id}", $event);

            if (!$response->successful()) {
                Log::warning('Google Calendar updateEvent failed: ' . $response->body());
            }
        } catch (\Exception $e) {
            Log::error('Google Calendar updateEvent error: ' . $e->getMessage());
        }
    }

    // ─── Etkinlik sil ─────────────────────────────────────────────────────────

    public function deleteEvent(string $eventId, ?User $user = null, ?string $calendarId = null): void
    {
        if (!$user) return;

        $token      = $this->getAccessTokenForUser($user);
        $calendarId = $calendarId ?: ($user->google_calendar_id ?: 'primary');

        if (!$token) return;

        try {
            Http::withToken($token)
                ->delete("{$this->baseUrl}/calendars/{$calendarId}/events/{$eventId}");
        } catch (\Exception $e) {
            Log::error('Google Calendar deleteEvent error: ' . $e->getMessage());
        }
    }

    // ─── Etkinlikleri listele (takvim görünümü için) ──────────────────────────

    public function listEvents(string $timeMin = null, string $timeMax = null, ?User $user = null): array
    {
        if (!$user) return [];

        $token      = $this->getAccessTokenForUser($user);
        $calendarId = $user->google_calendar_id ?: 'primary';

        if (!$token) return [];

        try {
            $params = [
                'singleEvents' => 'true',
                'orderBy'      => 'startTime',
                'maxResults'   => 250,
            ];
            if ($timeMin) $params['timeMin'] = $timeMin;
            if ($timeMax) $params['timeMax'] = $timeMax;

            $response = Http::withToken($token)
                ->get("{$this->baseUrl}/calendars/{$calendarId}/events", $params);

            if (!$response->successful()) {
                Log::warning('Google Calendar listEvents failed: ' . $response->body());
                return [];
            }

            return $response->json('items', []);
        } catch (\Exception $e) {
            Log::error('Google Calendar listEvents error: ' . $e->getMessage());
            return [];
        }
    }

    // ─── Kullanıcının bağlı olup olmadığını kontrol et ───────────────────────

    public function isEnabledForUser(User $user): bool
    {
        return $user->hasGoogleCalendar()
            && !empty(SiteSetting::get('google_calendar_client_id'))
            && !empty(SiteSetting::get('google_calendar_client_secret'));
    }

    // ─── Geriye dönük uyumluluk (global ayar kontrolü) ───────────────────────

    public function isEnabled(): bool
    {
        return !empty(SiteSetting::get('google_calendar_client_id'))
            && !empty(SiteSetting::get('google_calendar_client_secret'));
    }

    // ─── Token yönetimi ───────────────────────────────────────────────────────

    public function getAccessTokenForUser(User $user): ?string
    {
        $accessToken = $user->google_access_token;
        $expiresAt   = (int) $user->google_token_expires_at;

        if ($accessToken && $expiresAt > 0 && time() >= ($expiresAt - 60)) {
            $accessToken = $this->refreshAccessTokenForUser($user);
        }

        return $accessToken ?: null;
    }

    protected function refreshAccessTokenForUser(User $user): ?string
    {
        $clientId     = SiteSetting::get('google_calendar_client_id');
        $clientSecret = SiteSetting::get('google_calendar_client_secret');
        $refreshToken = $user->google_refresh_token;

        if (!$refreshToken) return null;

        try {
            $response = Http::post($this->tokenUrl, [
                'client_id'     => $clientId,
                'client_secret' => $clientSecret,
                'refresh_token' => $refreshToken,
                'grant_type'    => 'refresh_token',
            ]);

            if (!$response->successful()) return null;

            $data     = $response->json();
            $newToken = $data['access_token'];

            $user->update([
                'google_access_token'     => $newToken,
                'google_token_expires_at' => (int) (time() + ($data['expires_in'] ?? 3600)),
            ]);

            return $newToken;
        } catch (\Exception $e) {
            Log::error('Google Calendar token refresh error: ' . $e->getMessage());
            return null;
        }
    }

    // ─── Yardımcılar ─────────────────────────────────────────────────────────

    protected function resolveUser(Interview $interview): ?User
    {
        // Görüşmecinin token'ını kullan; yoksa giriş yapan kullanıcıyı dene
        $user = $interview->interviewer ?? auth()->user();

        if (!$user || !$this->isEnabledForUser($user)) {
            return null;
        }

        return $user;
    }

    protected function redirectUri(): string
    {
        return url('/admin/profil/google-callback');
    }

    protected function buildEventPayload(Interview $interview): array
    {
        $endTime = $interview->scheduled_at->copy()->addMinutes((int) $interview->duration_minutes);

        $description = '';
        if ($interview->application) {
            $description .= "Başvuran: {$interview->application->full_name}\n";
            $description .= "E-posta: {$interview->application->email}\n";
            if ($interview->application->phone) {
                $description .= "Telefon: {$interview->application->phone}\n";
            }
        }
        if ($interview->notes) {
            $description .= "\nNotlar: {$interview->notes}";
        }

        $event = [
            'summary'     => $interview->title,
            'description' => trim($description),
            'start'       => ['dateTime' => $interview->scheduled_at->toRfc3339String(), 'timeZone' => config('app.timezone', 'Europe/Istanbul')],
            'end'         => ['dateTime' => $endTime->toRfc3339String(), 'timeZone' => config('app.timezone', 'Europe/Istanbul')],
        ];

        if ($interview->meeting_link) {
            $event['location'] = $interview->meeting_link;
        } elseif ($interview->location) {
            $event['location'] = $interview->location;
        }

        return $event;
    }
}