<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Models\Answer;
use App\Models\Category;
use App\Models\Log;
use App\Models\Question;
use App\Models\QuestionGroup;
use App\Models\Screening;
use App\Models\Session;
use Inertia\Testing\AssertableInertia as Assert;
use Tests\TestCase;

class SessionLifecycleTest extends TestCase
{
    public function test_authenticated_user_can_create_session(): void
    {
        $user = $this->createAuthenticatedUser();
        $category = Category::factory()->create();
        $screening = Screening::factory()->create(['user_id' => $user->id]);

        $response = $this->post('/sessions', [
            'category_id' => $category->id,
            'screening_id' => $screening->id,
        ]);

        $session = Session::latest()->first();

        $response->assertRedirect("/sessions/{$session->id}");

        $this->assertDatabaseHas('questionnaire_sessions', [
            'user_id' => $user->id,
            'category_id' => $category->id,
            'screening_id' => $screening->id,
            'status' => 'in_progress',
        ]);
    }

    public function test_unauthenticated_user_cannot_create_session(): void
    {
        $category = Category::factory()->create();
        $screening = Screening::factory()->create();

        $this->post('/sessions', [
            'category_id' => $category->id,
            'screening_id' => $screening->id,
        ])->assertRedirect('/login');
    }

    public function test_show_returns_inertia_props(): 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',
        ]);

        $this->get("/sessions/{$session->id}")
            ->assertInertia(fn (Assert $page) => $page
                ->component('Session/Show')
                ->has('session')
                ->has('questionGroups')
                ->has('answers')
                ->has('score')
            );
    }

    public function test_can_save_answers(): 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' => 'Test explanation',
                ],
            ],
        ])->assertRedirect();

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

    public function test_can_save_additional_comments(): void
    {
        $user = $this->createAuthenticatedUser();
        $category = Category::factory()->create();

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

        $this->put("/sessions/{$session->id}", [
            'additional_comments' => 'Test comments',
        ])->assertRedirect();

        $session->refresh();

        $this->assertEquals('Test comments', $session->additional_comments);
    }

    public function test_complete_session_redirects_to_result(): void
    {
        $user = $this->createAuthenticatedUser();
        $category = Category::factory()->create();

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

        $this->put("/sessions/{$session->id}", [
            'complete' => true,
        ])->assertRedirect("/sessions/{$session->id}/result");
    }

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

        $this->post('/sessions', [
            'category_id' => $category->id,
            'screening_id' => $screening->id,
        ]);

        $session = Session::latest()->first();

        $this->assertDatabaseHas('logs', [
            'user_id' => $user->id,
            'session_id' => $session->id,
            'category_id' => $category->id,
            'action' => 'session_started',
        ]);
    }

    public function test_activity_log_created_on_session_completion(): void
    {
        $user = $this->createAuthenticatedUser();
        $category = Category::factory()->create();

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

        $this->put("/sessions/{$session->id}", [
            'complete' => true,
        ]);

        $log = Log::where('action', 'session_completed')->latest()->first();

        $this->assertNotNull($log);
        $this->assertEquals($user->id, $log->user_id);
        $this->assertEquals($session->id, $log->session_id);
        $this->assertEquals($category->id, $log->category_id);
    }
}
