<?php

namespace App\Http\Controllers\Meet;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Meet\Concerns\ScopesToAccount;
use App\Services\Meet\AvailabilityService;
use App\Services\Meet\CalendarService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\View\View;

class CalendarController extends Controller
{
    use ScopesToAccount;

    public function __construct(
        protected CalendarService $calendar,
        protected AvailabilityService $availability,
    ) {}

    public function settings(Request $request): View
    {
        $this->authorizeAbility($request, 'meetings.manage');
        $organization = $this->organization($request);
        $user = $request->user();

        return view('meet.settings.calendar', [
            'organization' => $organization,
            'googleConnected' => (bool) $this->calendar->connectionFor($user, 'google'),
            'microsoftConnected' => (bool) $this->calendar->connectionFor($user, 'microsoft'),
            'mailConnected' => (bool) $this->calendar->connectionFor($user, 'mail'),
            'mailConfigured' => filled(config('meet.calendar.mail.api_key')),
            'googleAuthUrl' => $this->calendar->oauthRedirectUrl('google'),
            'microsoftAuthUrl' => $this->calendar->oauthRedirectUrl('microsoft'),
        ]);
    }

    public function connectMail(Request $request): RedirectResponse
    {
        $this->authorizeAbility($request, 'meetings.manage');
        abort_unless(config('meet.calendar.mail.api_key'), 503, 'Ladill Mail calendar is not configured.');

        $validated = $request->validate([
            'mailbox_email' => ['nullable', 'email', 'max:255'],
        ]);

        $this->calendar->connectMail(
            $request->user(),
            $this->organization($request)->id,
            $validated['mailbox_email'] ?? null,
        );

        return redirect()->route('meet.settings.calendar')
            ->with('success', 'Ladill Mail calendar connected.');
    }

    public function connect(Request $request, string $provider): RedirectResponse
    {
        $this->authorizeAbility($request, 'meetings.manage');
        abort_unless(in_array($provider, ['google', 'microsoft'], true), 404);

        $url = $this->calendar->oauthRedirectUrl($provider);
        abort_unless($url, 503, 'Calendar integration is not configured.');

        $request->session()->put('meet.calendar.provider', $provider);

        return redirect()->away($url);
    }

    public function callback(Request $request): RedirectResponse
    {
        $this->authorizeAbility($request, 'meetings.manage');
        $provider = $request->session()->pull('meet.calendar.provider', 'google');
        $code = (string) $request->query('code');

        abort_unless($code !== '', 422, 'Authorization failed.');

        $connection = $this->calendar->handleOAuthCallback(
            $provider,
            $code,
            $request->user(),
            $this->organization($request)->id,
        );

        return redirect()->route('meet.settings.calendar')
            ->with($connection ? 'success' : 'error', $connection
                ? ucfirst($provider).' Calendar connected.'
                : 'Could not connect calendar.');
    }

    public function availability(Request $request): JsonResponse
    {
        $this->authorizeAbility($request, 'meetings.create');

        $validated = $request->validate([
            'scheduled_at' => ['required', 'date'],
            'duration_minutes' => ['nullable', 'integer', 'min:15', 'max:480'],
        ]);

        $start = Carbon::parse($validated['scheduled_at']);
        $duration = (int) ($validated['duration_minutes'] ?? 60);

        $result = $this->availability->checkHostAvailability(
            $request->user()->ownerRef(),
            $this->organization($request)->id,
            $start,
            $duration,
        );

        return response()->json($result);
    }
}
