<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Http\Requests\Screening\UpdateScreeningRequest;
use App\Models\Category;
use App\Models\Screening;
use App\Services\ActivityLogger;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Inertia\Inertia;
use Inertia\Response;

final class ScreeningController extends Controller
{
    /**
     * Create a new screening session for the authenticated user.
     */
    public function store(Request $request): RedirectResponse
    {
        $screening = Screening::create([
            'user_id' => auth()->id(),
        ]);

        ActivityLogger::log('screening_started', auth()->id());

        return redirect()->route('screening.show', $screening);
    }

    /**
     * Display the screening questionnaire.
     */
    public function show(Screening $screening): Response
    {
        return Inertia::render('Screening/Show', [
            'screening' => $screening,
            'questions' => array_values(config('screening.questions')),
        ]);
    }

    /**
     * Save screening answers and redirect to result.
     */
    public function update(UpdateScreeningRequest $request, Screening $screening): RedirectResponse
    {
        $validated = $request->validated();

        $this->saveAnswers($screening, Arr::get($validated, 'answers'));
        $this->calculateAndUpdateScore($screening, Arr::get($validated, 'answers'));

        ActivityLogger::log('screening_completed', auth()->id(), metadata: ['score' => $screening->score, 'passed' => $screening->passed]);

        return redirect()->route('screening.result', $screening);
    }

    /**
     * Display the screening result with available categories.
     */
    public function result(Screening $screening): Response
    {
        return Inertia::render('Screening/Result', [
            'screening' => $screening,
            'passed' => $screening->passed,
            'score' => $screening->score,
            'totalQuestions' => count(config('screening.questions')),
            'categories' => $screening->passed ? Category::orderBy('sort_order')->get(['id', 'name']) : [],
        ]);
    }

    /**
     * Save screening answers to the database using upsert pattern.
     */
    private function saveAnswers(Screening $screening, array $answers): void
    {
        foreach ($answers as $questionNumber => $value) {
            $screening->answers()->updateOrCreate(
                [
                    'screening_id' => $screening->id,
                    'question_number' => (int) $questionNumber,
                ],
                [
                    'value' => $value,
                ]
            );
        }
    }

    /**
     * Calculate the score and update the screening record.
     */
    private function calculateAndUpdateScore(Screening $screening, array $answers): void
    {
        $score = $this->calculateScore($answers);
        $passed = $score >= config('screening.passing_score', 5);

        $screening->update([
            'score' => $score,
            'passed' => $passed,
        ]);
    }

    /**
     * Calculate the total score from the answers — yes = 1, unknown = 0.5, no = 0.
     */
    private function calculateScore(array $answers): float
    {
        $score = 0;

        foreach ($answers as $value) {
            if ($value === 'yes') {
                $score++;
            } elseif ($value === 'unknown') {
                $score += 0.5;
            }
        }

        return $score;
    }
}
