<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Models\Answer;
use App\Models\Category;
use App\Models\Question;
use App\Models\QuestionGroup;
use App\Models\Screening;
use App\Models\Session;
use Tests\TestCase;

class AnswerTest extends TestCase
{
    public function test_answer_saved_with_value_and_text_value(): void
    {
        $user = $this->createAuthenticatedUser();
        $category = Category::factory()->create();
        $group = QuestionGroup::factory()->create(['category_id' => $category->id]);
        $question = Question::factory()->create(['question_group_id' => $group->id]);

        $session = Session::factory()->create([
            'user_id' => $user->id,
            'category_id' => $category->id,
        ]);

        $this->put("/sessions/{$session->id}", [
            'answers' => [
                $question->id => [
                    'value' => 'yes',
                    'text_value' => 'Detailed explanation here',
                ],
            ],
        ]);

        $this->assertDatabaseHas('answers', [
            'session_id' => $session->id,
            'question_id' => $question->id,
            'value' => 'yes',
            'text_value' => 'Detailed explanation here',
        ]);
    }

    public function test_upsert_updates_existing_answer(): void
    {
        $user = $this->createAuthenticatedUser();
        $category = Category::factory()->create();
        $group = QuestionGroup::factory()->create(['category_id' => $category->id]);
        $question = Question::factory()->create(['question_group_id' => $group->id]);

        $session = Session::factory()->create([
            'user_id' => $user->id,
            'category_id' => $category->id,
        ]);

        Answer::factory()->create([
            'session_id' => $session->id,
            'question_id' => $question->id,
            'value' => 'yes',
            'text_value' => 'Original text',
        ]);

        $this->put("/sessions/{$session->id}", [
            'answers' => [
                $question->id => [
                    'value' => 'no',
                    'text_value' => 'Updated text',
                ],
            ],
        ]);

        $this->assertDatabaseHas('answers', [
            'session_id' => $session->id,
            'question_id' => $question->id,
            'value' => 'no',
            'text_value' => 'Updated text',
        ]);

        $this->assertEquals(1, Answer::where('session_id', $session->id)->count());
    }

    public function test_invalid_value_rejected_with_422(): void
    {
        $user = $this->createAuthenticatedUser();
        $category = Category::factory()->create();
        $group = QuestionGroup::factory()->create(['category_id' => $category->id]);
        $question = Question::factory()->create(['question_group_id' => $group->id]);

        $session = Session::factory()->create([
            'user_id' => $user->id,
            'category_id' => $category->id,
        ]);

        $response = $this->put("/sessions/{$session->id}", [
            'answers' => [
                $question->id => [
                    'value' => 'invalid',
                ],
            ],
        ]);

        $response->assertSessionHasErrors();
    }

    public function test_not_applicable_accepted_as_valid_value(): void
    {
        $user = $this->createAuthenticatedUser();
        $category = Category::factory()->create();
        $group = QuestionGroup::factory()->create(['category_id' => $category->id]);
        $question = Question::factory()->create(['question_group_id' => $group->id]);

        $session = Session::factory()->create([
            'user_id' => $user->id,
            'category_id' => $category->id,
        ]);

        $this->put("/sessions/{$session->id}", [
            'answers' => [
                $question->id => [
                    'value' => 'not_applicable',
                ],
            ],
        ])->assertRedirect();

        $this->assertDatabaseHas('answers', [
            'session_id' => $session->id,
            'question_id' => $question->id,
            'value' => 'not_applicable',
        ]);
    }

    public function test_screening_answer_validation_requires_all_ten_answers(): void
    {
        $user = $this->createAuthenticatedUser();
        $screening = Screening::factory()->create(['user_id' => $user->id]);

        $response = $this->put("/screening/{$screening->id}", [
            'answers' => [
                1 => 'yes',
                2 => 'yes',
                3 => 'yes',
            ],
        ]);

        $response->assertSessionHasErrors('answers');
    }

    public function test_screening_answer_validation_rejects_invalid_values(): void
    {
        $user = $this->createAuthenticatedUser();
        $screening = Screening::factory()->create(['user_id' => $user->id]);

        $answers = array_fill(1, 10, 'invalid');

        $response = $this->put("/screening/{$screening->id}", [
            'answers' => $answers,
        ]);

        $response->assertSessionHasErrors();
    }

    public function test_screening_answer_validation_accepts_all_ten_valid_answers(): void
    {
        $user = $this->createAuthenticatedUser();
        $screening = Screening::factory()->create(['user_id' => $user->id]);

        $answers = array_fill(1, 10, 'yes');

        $this->put("/screening/{$screening->id}", [
            'answers' => $answers,
        ])->assertRedirect("/screening/{$screening->id}/result");

        $this->assertEquals(10, $screening->answers()->count());
    }
}
