<?php

namespace App\Services;

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

/**
 * MeetService
 * 
 * Public service for other modules to create Google Meet video conferences.
 * Provides a simple, standardized interface for meeting creation with
 * comprehensive error handling and logging.
 * 
 * @example
 * ```php
 * $meetService = app(MeetService::class);
 * 
 * $result = $meetService->createMeeting(
 *     'Project Review Meeting',
 *     '2024-01-15T10:00:00',
 *     '2024-01-15T11:00:00',
 *     ['user1@example.com', 'user2@example.com']
 * );
 * 
 * if ($result['success']) {
 *     echo $result['meeting_link'];
 * }
 * ```
 */
class MeetService
{
    /**
     * Configuration service instance.
     *
     * @var GoogleMeetConfigurationService
     */
    protected GoogleMeetConfigurationService $configService;

    /**
     * Meet provider instance.
     *
     * @var MeetProvider
     */
    protected MeetProvider $meetProvider;

    /**
     * Create a new MeetService instance.
     *
     * @param GoogleMeetConfigurationService $configService
     * @param MeetProvider $meetProvider
     */
    public function __construct(
        GoogleMeetConfigurationService $configService,
        MeetProvider $meetProvider
    ) {
        $this->configService = $configService;
        $this->meetProvider = $meetProvider;
    }

    /**
     * Create a Google Meet video conference.
     *
     * @param string $summary Meeting title/summary
     * @param string $startTime ISO 8601 datetime string or any valid date format
     * @param string $endTime ISO 8601 datetime string or any valid date format
     * @param array $attendees Array of attendee email addresses
     * @param string|null $description Optional meeting description
     * @return array Standardized response with success status and meeting details
     */
    public function createMeeting(
        string $summary,
        string $startTime,
        string $endTime,
        array $attendees = [],
        ?string $description = null
    ): array {
        try {
            // Check if Google Meet is configured
            if (!$this->configService->isConfigured()) {
                return $this->errorResponse(
                    'Google Meet is not configured. Please configure the integration in the admin panel.',
                    'not_configured'
                );
            }

            // Get configuration
            $config = $this->configService->getConfigurationOrFail();

            // Check if authenticated
            if (!$config->hasValidToken()) {
                return $this->errorResponse(
                    'Google Meet is not authenticated. Please authenticate in the admin panel.',
                    'not_authenticated'
                );
            }

            // Create the meeting
            $result = $this->meetProvider->createMeeting(
                $config,
                $summary,
                $startTime,
                $endTime,
                $attendees,
                $description
            );

            return $this->successResponse(
                'Meeting created successfully',
                $result
            );
        } catch (\Exception $e) {
            Log::error('MeetService: Failed to create meeting', [
                'error' => $e->getMessage(),
                'summary' => $summary,
                'attendees_count' => count($attendees),
            ]);

            return $this->errorResponse(
                'Failed to create meeting: ' . $e->getMessage(),
                'creation_failed',
                ['exception' => $e->getMessage()]
            );
        }
    }

    /**
     * Create a quick meeting with default duration.
     *
     * @param string $summary Meeting title
     * @param int $durationMinutes Meeting duration in minutes (default: 60)
     * @param array $attendees Array of attendee email addresses
     * @return array
     */
    public function createQuickMeeting(
        string $summary,
        int $durationMinutes = 60,
        array $attendees = []
    ): array {
        $startTime = now()->addMinutes(15); // Start in 15 minutes
        $endTime = (clone $startTime)->addMinutes($durationMinutes);

        return $this->createMeeting(
            $summary,
            $startTime->toIso8601String(),
            $endTime->toIso8601String(),
            $attendees
        );
    }

    /**
     * Schedule a meeting at a specific time.
     *
     * @param string $summary Meeting title
     * @param \DateTime|string $startDateTime Meeting start time
     * @param int $durationMinutes Meeting duration in minutes
     * @param array $attendees Array of attendee email addresses
     * @param string|null $description Meeting description
     * @return array
     */
    public function scheduleMeeting(
        string $summary,
        $startDateTime,
        int $durationMinutes = 60,
        array $attendees = [],
        ?string $description = null
    ): array {
        $start = Carbon::parse($startDateTime);
        $end = (clone $start)->addMinutes($durationMinutes);

        return $this->createMeeting(
            $summary,
            $start->toIso8601String(),
            $end->toIso8601String(),
            $attendees,
            $description
        );
    }

    /**
     * Test the Google Meet connection.
     *
     * @return array
     */
    public function testConnection(): array
    {
        try {
            if (!$this->configService->isConfigured()) {
                return $this->errorResponse(
                    'Google Meet is not configured.',
                    'not_configured'
                );
            }

            $config = $this->configService->getConfigurationOrFail();
            $result = $this->meetProvider->testConnection($config);

            return $result;
        } catch (\Exception $e) {
            return $this->errorResponse(
                'Connection test failed: ' . $e->getMessage(),
                'test_failed'
            );
        }
    }

    /**
     * Check if Google Meet is available and ready to use.
     *
     * @return bool
     */
    public function isAvailable(): bool
    {
        return $this->configService->isConfigured()
            && $this->configService->isAuthenticated();
    }

    /**
     * Get the current configuration status.
     *
     * @return array
     */
    public function getStatus(): array
    {
        return [
            'available' => $this->isAvailable(),
            'configured' => $this->configService->isConfigured(),
            'authenticated' => $this->configService->isAuthenticated(),
            'summary' => $this->configService->getStatusSummary(),
        ];
    }

    /**
     * Build success response.
     *
     * @param string $message
     * @param array $data
     * @return array
     */
    protected function successResponse(string $message, array $data = []): array
    {
        return [
            'success' => true,
            'message' => $message,
            'meeting_link' => $data['meeting_link'] ?? null,
            'meeting_id' => $data['meeting_id'] ?? null,
            'calendar_event_id' => $data['calendar_event_id'] ?? null,
            'summary' => $data['summary'] ?? null,
            'start_time' => $data['start_time'] ?? null,
            'end_time' => $data['end_time'] ?? null,
            'attendees' => $data['attendees'] ?? [],
            'data' => $data,
        ];
    }

    /**
     * Build error response.
     *
     * @param string $message
     * @param string $code
     * @param array $details
     * @return array
     */
    protected function errorResponse(
        string $message,
        string $code,
        array $details = []
    ): array {
        return [
            'success' => false,
            'message' => $message,
            'error_code' => $code,
            'meeting_link' => null,
            'meeting_id' => null,
            'details' => $details,
        ];
    }

    /**
     * Validate meeting parameters before creation.
     *
     * @param string $summary
     * @param string $startTime
     * @param string $endTime
     * @param array $attendees
     * @return array
     */
    public function validateMeetingParameters(
        string $summary,
        string $startTime,
        string $endTime,
        array $attendees = []
    ): array {
        $errors = [];

        // Validate summary
        if (empty(trim($summary))) {
            $errors[] = 'Meeting summary is required.';
        } elseif (strlen($summary) > 500) {
            $errors[] = 'Meeting summary cannot exceed 500 characters.';
        }

        // Validate times
        try {
            $start = Carbon::parse($startTime);
            $end = Carbon::parse($endTime);

            if ($start->isPast()) {
                $errors[] = 'Meeting start time cannot be in the past.';
            }

            if ($end->lte($start)) {
                $errors[] = 'Meeting end time must be after start time.';
            }

            // Check for reasonable duration (max 24 hours)
            if ($start->diffInHours($end) > 24) {
                $errors[] = 'Meeting duration cannot exceed 24 hours.';
            }
        } catch (\Exception $e) {
            $errors[] = 'Invalid date/time format. Use ISO 8601 format (e.g., 2024-01-15T10:00:00).';
        }

        // Validate attendees
        foreach ($attendees as $email) {
            if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
                $errors[] = "Invalid email address: {$email}";
            }
        }

        // Check max attendees
        if (count($attendees) > 100) {
            $errors[] = 'Maximum 100 attendees allowed.';
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
        ];
    }

    /**
     * Create meeting with validation.
     *
     * @param string $summary
     * @param string $startTime
     * @param string $endTime
     * @param array $attendees
     * @param string|null $description
     * @return array
     */
    public function createMeetingWithValidation(
        string $summary,
        string $startTime,
        string $endTime,
        array $attendees = [],
        ?string $description = null
    ): array {
        // Validate parameters
        $validation = $this->validateMeetingParameters($summary, $startTime, $endTime, $attendees);

        if (!$validation['valid']) {
            return $this->errorResponse(
                'Validation failed: ' . implode(' ', $validation['errors']),
                'validation_failed',
                ['validation_errors' => $validation['errors']]
            );
        }

        return $this->createMeeting($summary, $startTime, $endTime, $attendees, $description);
    }
}
