<?php

namespace App\Http\Requests\Inquiry;

use App\Models\QuestionnaireAnswer;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class SubmitQuestionnaireRequest 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
            'questionnaire_id' => [
                'required',
                'string',
                'exists:questionnaire_answers,id'
            ],
            
            // Step information
            'step' => [
                'required',
                'integer',
                'min:1',
                'max:4'
            ],
            
            // Answers (JSON string or array)
            'answers' => [
                'required',
                'array',
                'min:1'
            ],
            'answers.*' => [
                'sometimes',
                'nullable',
                Rule::in(['yes', 'no', 'true', 'false', true, false, 0, 1, '0', '1'])
            ],
            
            // Additional step-specific fields
            'is_smoker' => [
                'sometimes',
                'boolean',
                'required_if:step,4'
            ],
            'years_smoking' => [
                'sometimes',
                'nullable',
                'integer',
                'min:0',
                'max:100',
                'required_if:step,4'
            ],
            'uses_vaping' => [
                'sometimes',
                'boolean',
                'required_if:step,4'
            ],
            
            // Control flags
            'is_final_submission' => 'sometimes|boolean',
            'save_draft' => 'sometimes|boolean',
            'skip_validation' => 'sometimes|boolean',
            'force_submit' => 'sometimes|boolean',
            
            // Review information (for admin review)
            'review_notes' => 'sometimes|nullable|string|max:1000',
            'admin_override_rate' => [
                'sometimes',
                'nullable',
                'string',
                Rule::in(['A', 'B', 'C'])
            ],
            'admin_override_surcharge' => 'sometimes|nullable|numeric|min:0|max:100',
            
            // 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 [
            'questionnaire_id.exists' => 'The specified questionnaire does not exist.',
            'step.min' => 'Step must be between 1 and 4.',
            'step.max' => 'Step must be between 1 and 4.',
            'answers.required' => 'Answers are required for the questionnaire.',
            'answers.array' => 'Answers must be provided as an array.',
            'answers.min' => 'At least one answer must be provided.',
            'is_smoker.required_if' => 'Smoking status is required for Step 4.',
            'years_smoking.required_if' => 'Years of smoking is required for Step 4.',
            'uses_vaping.required_if' => 'Vaping status is required for Step 4.',
            'answers.*.in' => 'Answer must be one of: yes, no, true, false, 0, 1.',
        ];
    }

    /**
     * Get custom attributes for validator errors.
     *
     * @return array<string, string>
     */
    public function attributes(): array
    {
        return [
            'apiKey' => 'API Key',
            'token' => 'Token',
            'questionnaire_id' => 'questionnaire ID',
            'step' => 'step',
            'answers' => 'answers',
            'is_smoker' => 'smoker status',
            'years_smoking' => 'years of smoking',
            'uses_vaping' => 'vaping status',
        ];
    }

    /**
     * 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();
        
        // Parse answers from JSON string if needed
        $answers = $this->input('answers');
        if (is_string($answers)) {
            try {
                $decoded = json_decode($answers, true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    $answers = $decoded;
                }
            } catch (\Exception $e) {
                // Keep as is, validation will fail
            }
        }
        
        $this->merge([
            'apiKey' => $apiKey,
            'token' => $token,
            'questionnaire_id' => $this->input('questionnaire_id'),
            'step' => (int) $this->input('step'),
            'answers' => is_array($answers) ? $answers : [],
            'is_smoker' => filter_var($this->input('is_smoker'), FILTER_VALIDATE_BOOLEAN),
            'years_smoking' => $this->input('years_smoking') ? (int) $this->input('years_smoking') : null,
            'uses_vaping' => filter_var($this->input('uses_vaping'), FILTER_VALIDATE_BOOLEAN),
            'is_final_submission' => filter_var($this->input('is_final_submission', false), FILTER_VALIDATE_BOOLEAN),
            'save_draft' => filter_var($this->input('save_draft', false), FILTER_VALIDATE_BOOLEAN),
            'skip_validation' => filter_var($this->input('skip_validation', false), FILTER_VALIDATE_BOOLEAN),
            'force_submit' => filter_var($this->input('force_submit', false), FILTER_VALIDATE_BOOLEAN),
            'review_notes' => $this->input('review_notes'),
            'admin_override_rate' => $this->input('admin_override_rate'),
            'admin_override_surcharge' => $this->input('admin_override_surcharge') ? (float) $this->input('admin_override_surcharge') : null,
            'language' => in_array($language, ['en', 'zh', 'fa']) ? $language : 'en',
        ]);
    }

    /**
     * Get validated data with additional processing.
     *
     * @return array
     */
    public function validatedData(): array
    {
        $validated = $this->validated();
        
        // Normalize answer values
        if (isset($validated['answers']) && is_array($validated['answers'])) {
            $validated['answers'] = $this->normalizeAnswers($validated['answers']);
        }
        
        // Add smoking info to answers for step 4
        if ($validated['step'] === 4) {
            $validated['answers']['is_smoker'] = $validated['is_smoker'] ?? false;
            $validated['answers']['years_smoking'] = $validated['years_smoking'] ?? 0;
            $validated['answers']['uses_vaping'] = $validated['uses_vaping'] ?? false;
        }
        
        return $validated;
    }

    /**
     * Normalize answer values to consistent format.
     */
    private function normalizeAnswers(array $answers): array
    {
        $normalized = [];
        
        foreach ($answers as $key => $value) {
            if (is_bool($value)) {
                $normalized[$key] = $value ? 'yes' : 'no';
            } elseif (in_array($value, [1, '1', 'true', true], true)) {
                $normalized[$key] = 'yes';
            } elseif (in_array($value, [0, '0', 'false', false], true)) {
                $normalized[$key] = 'no';
            } elseif (in_array(strtolower($value), ['yes', 'no'])) {
                $normalized[$key] = strtolower($value);
            } else {
                $normalized[$key] = $value; // Keep as is, validation will catch invalid values
            }
        }
        
        return $normalized;
    }

    /**
     * Check if this is a final submission.
     *
     * @return bool
     */
    public function isFinalSubmission(): bool
    {
        return $this->validated('is_final_submission', false);
    }

    /**
     * Check if this should be saved as a draft.
     *
     * @return bool
     */
    public function shouldSaveDraft(): bool
    {
        return $this->validated('save_draft', false);
    }

    /**
     * Check if validation should be skipped.
     *
     * @return bool
     */
    public function shouldSkipValidation(): bool
    {
        return $this->validated('skip_validation', false);
    }

    /**
     * Check if submission should be forced.
     *
     * @return bool
     */
    public function shouldForceSubmit(): bool
    {
        return $this->validated('force_submit', false);
    }

    /**
     * Check if admin override is requested.
     *
     * @return bool
     */
    public function hasAdminOverride(): bool
    {
        return !empty($this->validated('admin_override_rate')) || 
               !empty($this->validated('admin_override_surcharge'));
    }

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

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

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

    /**
     * Get the answers.
     *
     * @return array
     */
    public function getAnswers(): array
    {
        return $this->validated('answers', []);
    }

    /**
     * Get smoking information.
     *
     * @return array
     */
    public function getSmokingInfo(): array
    {
        return [
            'is_smoker' => $this->validated('is_smoker', false),
            'years_smoking' => $this->validated('years_smoking', 0),
            'uses_vaping' => $this->validated('uses_vaping', false),
        ];
    }

    /**
     * Get admin override information.
     *
     * @return array
     */
    public function getAdminOverride(): array
    {
        return [
            'rate' => $this->validated('admin_override_rate'),
            'surcharge' => $this->validated('admin_override_surcharge'),
            'notes' => $this->validated('review_notes'),
        ];
    }

    /**
     * Validate that the questionnaire exists and is accessible.
     *
     * @return bool
     */
    public function validateQuestionnaireAccess(): bool
    {
        $questionnaireId = $this->validated('questionnaire_id');
        if (!$questionnaireId) {
            return false;
        }

        // Check if questionnaire exists
        $questionnaire = QuestionnaireAnswer::find($questionnaireId);
        if (!$questionnaire) {
            return false;
        }

        // Load related data for further validation
        $questionnaire->load(['person.inquiry']);
        
        // Verify agent access (using API key)
        $agentId = $this->validated('apiKey');
        if ($questionnaire->inquiry->agent_id !== $agentId) {
            return false;
        }

        return true;
    }

    /**
     * Validate that the step is appropriate for the questionnaire state.
     *
     * @return array
     */
    public function validateStepProgression(): array
    {
        $questionnaireId = $this->validated('questionnaire_id');
        $step = $this->validated('step');
        
        if (!$questionnaireId) {
            return [false, 'Questionnaire ID is required'];
        }

        $questionnaire = QuestionnaireAnswer::find($questionnaireId);
        if (!$questionnaire) {
            return [false, 'Questionnaire not found'];
        }

        // Check if questionnaire is already completed
        if ($questionnaire->isCompleted() && !$this->shouldForceSubmit()) {
            return [false, 'Questionnaire is already completed'];
        }

        // Check if questionnaire is rejected
        if ($questionnaire->isRejected() && !$this->shouldForceSubmit()) {
            return [false, 'Questionnaire is rejected'];
        }

        // Validate step progression
        switch ($step) {
            case 1:
                // Step 1 is always allowed
                break;
                
            case 2:
                // Need Step 1 completed and passed
                if (!$questionnaire->step1_answers) {
                    return [false, 'Step 1 must be completed first'];
                }
                if (!$questionnaire->step1_passed) {
                    return [false, 'Cannot proceed to Step 2: Eligibility check failed'];
                }
                break;
                
            case 3:
                // Need Step 2 completed and C rate not triggered
                if (!$questionnaire->step2_answers) {
                    return [false, 'Step 2 must be completed first'];
                }
                if ($questionnaire->step2_triggered_c_rate) {
                    return [false, 'Cannot proceed to Step 3: C rate already triggered'];
                }
                break;
                
            case 4:
                // Need Step 1 completed and passed
                if (!$questionnaire->step1_answers || !$questionnaire->step1_passed) {
                    return [false, 'Step 1 must be completed and passed first'];
                }
                // If C rate not triggered, need Step 3 completed
                if (!$questionnaire->step2_triggered_c_rate && !$questionnaire->step3_answers) {
                    return [false, 'Step 3 must be completed first'];
                }
                break;
        }

        return [true, 'Step progression is valid'];
    }

    /**
     * Validate that all required questions for the step are answered.
     *
     * @param array $requiredQuestions
     * @return array
     */
    public function validateRequiredQuestions(array $requiredQuestions): array
    {
        $answers = $this->getAnswers();
        $missingQuestions = [];
        
        foreach ($requiredQuestions as $question) {
            $questionId = $question['code'] ?? null;
            if ($questionId && !isset($answers[$questionId])) {
                $missingQuestions[] = $questionId;
            }
        }
        
        if (!empty($missingQuestions)) {
            return [
                false,
                'Missing answers for questions: ' . implode(', ', $missingQuestions)
            ];
        }
        
        return [true, 'All required questions answered'];
    }

    /**
     * Get questionnaire model.
     *
     * @return QuestionnaireAnswer|null
     */
    public function getQuestionnaire(): ?QuestionnaireAnswer
    {
        return QuestionnaireAnswer::find($this->validated('questionnaire_id'));
    }
}