<?php

namespace App\Http\Requests\Inquiry;

use App\Models\Inquiry;
use App\Models\Person;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class GetQuestionnaireRequest 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.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            // API authentication
            'apiKey' => 'required|string|exists:agents,id',
            'token' => 'required|string',
            
            // Questionnaire identification
            'inquiry_id' => [
                'required',
                'string',
                'exists:inquiries,id'
            ],
            
            // Person selection (optional)
            'person_id' => [
                'sometimes',
                'nullable',
                'string',
                Rule::exists('people', 'id')->where(function ($query) {
                    return $query->where('inquiry_id', $this->input('inquiry_id'));
                })
            ],
            
            // Step selection (optional)
            'step' => [
                'sometimes',
                'nullable',
                'integer',
                'min:1',
                'max:4'
            ],
            
            // Control flags
            'reset' => 'sometimes|boolean',
            'force_new' => 'sometimes|boolean',
            'include_completed' => 'sometimes|boolean',
            
            // Language for response
            'language' => 'sometimes|string|in:en,zh,fa',
        ];
    }

    /**
     * Get custom messages for validator errors.
     *
     * @return array<string, string>
     */
    public function messages(): array
    {
        return [
            'inquiry_id.exists' => 'The specified inquiry does not exist.',
            'person_id.exists' => 'The specified person does not exist in this inquiry.',
            'step.min' => 'Step must be between 1 and 4.',
            'step.max' => 'Step must be between 1 and 4.',
        ];
    }

    /**
     * Get custom attributes for validator errors.
     *
     * @return array<string, string>
     */
    public function attributes(): array
    {
        return [
            'apiKey' => 'API Key',
            'token' => 'Token',
            'inquiry_id' => 'inquiry ID',
            'person_id' => 'person ID',
            'step' => 'step',
        ];
    }

    /**
     * Prepare the data for validation.
     */
    protected function prepareForValidation(): void
    {
        // Get API key from header
        $apiKey = $this->header('API-Key');
        
        // Get language from header
        $language = $this->header('Accept-Language', 'en');
        
        // Get token from bearer token
        $token = $this->bearerToken();
        
        $this->merge([
            'apiKey' => $apiKey,
            'token' => $token,
            'inquiry_id' => $this->query('inquiry_id'),
            'person_id' => $this->query('person_id'),
            'step' => $this->query('step') ? (int) $this->query('step') : null,
            'reset' => filter_var($this->query('reset', false), FILTER_VALIDATE_BOOLEAN),
            'force_new' => filter_var($this->query('force_new', false), FILTER_VALIDATE_BOOLEAN),
            'include_completed' => filter_var($this->query('include_completed', false), FILTER_VALIDATE_BOOLEAN),
            'language' => in_array($language, ['en', 'zh', 'fa']) ? $language : 'en',
        ]);
    }

    /**
     * Get validated data with additional processing.
     *
     * @return array
     */
    public function validatedData(): array
    {
        $validated = $this->validated();
        
        // Ensure step is within valid range if provided
        if (isset($validated['step']) && ($validated['step'] < 1 || $validated['step'] > 4)) {
            $validated['step'] = null;
        }
        
        return $validated;
    }

    /**
     * Check if the request is for a specific step.
     *
     * @return bool
     */
    public function hasStep(): bool
    {
        return !empty($this->validated('step'));
    }

    /**
     * Check if the request should reset existing questionnaire.
     *
     * @return bool
     */
    public function shouldReset(): bool
    {
        return $this->validated('reset', false);
    }

    /**
     * Check if the request should force a new questionnaire.
     *
     * @return bool
     */
    public function shouldForceNew(): bool
    {
        return $this->validated('force_new', false);
    }

    /**
     * Check if completed questionnaires should be included.
     *
     * @return bool
     */
    public function shouldIncludeCompleted(): bool
    {
        return $this->validated('include_completed', false);
    }

    /**
     * Get the preferred language for response.
     *
     * @return string
     */
    public function getPreferredLanguage(): string
    {
        return $this->validated('language', 'en');
    }

    /**
     * Get the inquiry ID.
     *
     * @return string|null
     */
    public function getInquiryId(): ?string
    {
        return $this->validated('inquiry_id');
    }

    /**
     * Get the person ID.
     *
     * @return string|null
     */
    public function getPersonId(): ?string
    {
        return $this->validated('person_id');
    }

    /**
     * Get the requested step.
     *
     * @return int|null
     */
    public function getStep(): ?int
    {
        return $this->validated('step');
    }

    /**
     * Validate that the inquiry exists and is accessible.
     *
     * @return bool
     */
    public function validateInquiryAccess(): bool
    {
        $inquiryId = $this->validated('inquiry_id');
        if (!$inquiryId) {
            return false;
        }

        // Check if inquiry exists and belongs to the agent
        $inquiry = Inquiry::find($inquiryId);
        if (!$inquiry) {
            return false;
        }

        // Verify agent access (using API key)
        $agentId = $this->validated('apiKey');
        if ($inquiry->agent_id !== $agentId) {
            return false;
        }

        return true;
    }

    /**
     * Validate that the person belongs to the inquiry.
     *
     * @return bool
     */
    public function validatePersonAccess(): bool
    {
        $inquiryId = $this->validated('inquiry_id');
        $personId = $this->validated('person_id');
        
        if (!$inquiryId || !$personId) {
            return false;
        }

        // Check if person exists and belongs to inquiry
        $person = Person::where('id', $personId)
            ->where('inquiry_id', $inquiryId)
            ->first();

        return $person !== null;
    }

    /**
     * Get inquiry model.
     *
     * @return Inquiry|null
     */
    public function getInquiry(): ?Inquiry
    {
        return Inquiry::find($this->validated('inquiry_id'));
    }

    /**
     * Get person model.
     *
     * @return Person|null
     */
    public function getPerson(): ?Person
    {
        $inquiryId = $this->validated('inquiry_id');
        $personId = $this->validated('person_id');
        
        if (!$inquiryId || !$personId) {
            return null;
        }

        return Person::where('id', $personId)
            ->where('inquiry_id', $inquiryId)
            ->first();
    }
}