<?php

namespace App\Http\Requests\Mentorship;

use Illuminate\Foundation\Http\FormRequest;

class SessionRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     */
    public function rules(): array
    {
        $isUpdate = in_array($this->method(), ['PUT', 'PATCH']);

        $rules = [
            'assignment_id' => [
                'required',
                'exists:mentorship_assignments,id',
            ],
            'title' => [
                'required',
                'string',
                'max:191',
                'min:3',
            ],
            'description' => [
                'nullable',
                'string',
                'max:3000',
            ],
            'agenda' => [
                'nullable',
                'string',
                'max:3000',
            ],
            'notes' => [
                'nullable',
                'string',
                'max:2000',
            ],
            'type' => [
                'required',
                'in:online,in_person',
            ],
            'session_number' => [
                'nullable',
                'in:first,regular,last',
            ],
            'start_time' => [
                'required',
                'date',
                $isUpdate ? null : 'after:now',
            ],
            'end_time' => [
                'required',
                'date',
                'after:start_time',
            ],
            'timezone' => [
                'nullable',
                'string',
                'max:50',
            ],
            'duration_minutes' => [
                'nullable',
                'integer',
                'min:15',
                'max:480', // 8 hours max
            ],
            // In-person session fields
            'venue' => [
                'required_if:type,in_person',
                'nullable',
                'string',
                'max:500',
            ],
            'venue_address' => [
                'nullable',
                'string',
                'max:500',
            ],
            'venue_instructions' => [
                'nullable',
                'string',
                'max:1000',
            ],
            // Online session fields (Google Meet)
            'meeting_link' => [
                'nullable',
                'string',
                'max:500',
                'url',
            ],
            'meeting_id' => [
                'nullable',
                'string',
                'max:100',
            ],
            'meeting_password' => [
                'nullable',
                'string',
                'max:100',
            ],
            // Attachments
            'attachments' => [
                'nullable',
                'array',
                'max:10',
            ],
            'attachments.*' => [
                'file',
                'max:10240', // 10MB max
            ],
        ];

        return $rules;
    }

    /**
     * Get custom messages for validator errors.
     */
    public function messages(): array
    {
        return [
            'assignment_id.required' => 'Please select an assignment.',
            'assignment_id.exists' => 'The selected assignment does not exist.',
            'title.required' => 'Please enter a session title.',
            'title.min' => 'The session title must be at least 3 characters.',
            'type.required' => 'Please select a session type.',
            'type.in' => 'Please select either online or in-person.',
            'start_time.required' => 'Please select a start time.',
            'start_time.after' => 'The start time must be in the future.',
            'end_time.required' => 'Please select an end time.',
            'end_time.after' => 'The end time must be after the start time.',
            'duration_minutes.min' => 'The session must be at least 15 minutes.',
            'duration_minutes.max' => 'The session cannot exceed 8 hours (480 minutes).',
            'venue.required_if' => 'Please enter a venue for in-person sessions.',
            'meeting_link.url' => 'Please enter a valid meeting link URL.',
            'attachments.max' => 'You can attach a maximum of 10 files.',
            'attachments.*.max' => 'Each attachment must not exceed 10MB.',
        ];
    }

    /**
     * Prepare the data for validation.
     */
    protected function prepareForValidation(): void
    {
        // Combine separate date + time fields into full datetime strings
        // when the form submits them as bare HH:MM values (create / edit forms).
        // The reschedule form already sends full datetimes — those are left untouched.
        if ($this->has('date') && $this->has('start_time') && $this->has('end_time')) {
            $bareTimePattern = '/^\d{2}:\d{2}(:\d{2})?$/';

            if (preg_match($bareTimePattern, $this->input('start_time'))
                && preg_match($bareTimePattern, $this->input('end_time'))) {
                $date = $this->input('date');
                $this->merge([
                    'start_time' => $date . ' ' . $this->input('start_time'),
                    'end_time'   => $date . ' ' . $this->input('end_time'),
                ]);
            }
        }

        // Calculate duration if start and end times are provided
        if ($this->has('start_time') && $this->has('end_time')) {
            $start = \Carbon\Carbon::parse($this->input('start_time'));
            $end = \Carbon\Carbon::parse($this->input('end_time'));
            $duration = $start->diffInMinutes($end);
            
            $this->merge(['duration_minutes' => $duration]);
        }

        // Set default timezone if not provided
        if (!$this->has('timezone')) {
            $this->merge(['timezone' => 'Africa/Kampala']);
        }
    }

    /**
     * Configure the validator instance.
     */
    public function withValidator($validator): void
    {
        $validator->after(function ($validator) {
            // Check for scheduling conflicts
            if ($this->has('assignment_id') && $this->has('start_time') && $this->has('end_time')) {
                $assignment = \App\Models\Mentorship\Assignment::find($this->input('assignment_id'));
                
                if ($assignment) {
                    $conflict = \App\Models\Mentorship\Session::where('assignment_id', $this->input('assignment_id'))
                        ->where('status', '!=', 'cancelled')
                        ->where(function ($query) {
                            $query->whereBetween('start_time', [$this->input('start_time'), $this->input('end_time')])
                                ->orWhereBetween('end_time', [$this->input('start_time'), $this->input('end_time')])
                                ->orWhere(function ($q) {
                                    $q->where('start_time', '<=', $this->input('start_time'))
                                        ->where('end_time', '>=', $this->input('end_time'));
                                });
                        })
                        ->exists();

                    if ($conflict) {
                        $validator->errors()->add('start_time', 'There is a scheduling conflict with another session.');
                    }
                }
            }
        });
    }

    /**
     * Get validated data with additional processing.
     */
    public function validated($key = null, $default = null): array
    {
        $validated = parent::validated($key, $default);

        // XSS Prevention
        $textFields = ['title', 'description', 'agenda', 'notes', 'venue', 'venue_instructions'];
        foreach ($textFields as $field) {
            if (isset($validated[$field])) {
                $validated[$field] = strip_tags($validated[$field], '<p><br><strong><em><u><ol><ul><li><a>');
            }
        }

        // Add programme_id from assignment
        if (isset($validated['assignment_id'])) {
            $assignment = \App\Models\Mentorship\Assignment::find($validated['assignment_id']);
            if ($assignment) {
                $validated['programme_id'] = $assignment->programme_id;
            }
        }

        return $validated;
    }
}
