<?php

namespace App\Http\Controllers\Api\Scores;

use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Scores\ScoreUpdateRequest;
use App\Http\Resources\Scores\ScoreStudentResource;
use App\Models\Student;
use App\Services\Scores\ExamScoreService;
use App\Services\Scores\SemesterScoreService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class MidtermController extends BaseApiController
{
    public function __construct(
        private ExamScoreService $service,
        private SemesterScoreService $semesterScoreService
    ) {
        parent::__construct();
    }

    public function index(Request $request): JsonResponse
    {
        $data = array_merge($request->query->all(), $request->all(), $request->json()->all());
        $validator = Validator::make($data, [
            'class_section_id' => ['nullable', 'integer', 'min:1'],
            'semester' => ['nullable', 'string', 'max:50'],
            'school_year' => ['nullable', 'string', 'max:50'],
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => 'Validation failed.',
                'errors' => $validator->errors(),
            ], 422);
        }

        $payload = $validator->validated();
        $classSectionId = isset($payload['class_section_id']) ? (int) $payload['class_section_id'] : null;

        if ($classSectionId === null || $classSectionId <= 0) {
            $userId = $this->authenticatedUserIdOrUnauthorized();
            if ($userId instanceof JsonResponse) {
                return $userId;
            }

            $classSectionId = $this->service->resolveClassSectionIdForTeacher(
                $userId,
                null,
                $payload['school_year'] ?? null
            );

            if ($classSectionId === null) {
                return response()->json([
                    'message' => 'Validation failed.',
                    'errors' => [
                        'class_section_id' => ['Provide class_section_id or assign this account to a class for the selected school year.'],
                    ],
                ], 422);
            }
        }

        $data = $this->service->list('midterm_exam', $classSectionId, $payload['semester'] ?? null, $payload['school_year'] ?? null);

        return response()->json([
            'ok' => true,
            'students' => ScoreStudentResource::collection($data['students']),
            'class_section_name' => $data['classSectionName'],
            'semester' => $data['semester'],
            'school_year' => $data['schoolYear'],
            'scores_locked' => $data['scoresLocked'],
            'missing_ok_map' => $data['missingOkMap'],
        ]);
    }

    public function update(ScoreUpdateRequest $request): JsonResponse
    {
        $userId = $this->authenticatedUserIdOrUnauthorized();
        if ($userId instanceof JsonResponse) {
            return $userId;
        }

        $payload = $request->validated();
        $count = $this->service->update(
            'midterm_exam',
            (int) $payload['class_section_id'],
            (string) $payload['semester'],
            (string) $payload['school_year'],
            $payload['scores'],
            $payload['missing_ok'] ?? [],
            $userId
        );

        $this->refreshSemesterScores((int) $payload['class_section_id'], (string) $payload['semester'], (string) $payload['school_year'], $userId);

        return response()->json(['ok' => true, 'updated' => $count]);
    }

    public function bySchoolYear(Request $request): JsonResponse
    {
        $data = array_merge($request->query->all(), $request->all(), $request->json()->all());
        $validator = Validator::make($data, [
            'school_year' => ['required', 'string', 'max:50'],
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => 'Validation failed.',
                'errors' => $validator->errors(),
            ], 422);
        }

        $payload = $validator->validated();
        $data = $this->service->listBySchoolYear('midterm_exam', $payload['school_year']);

        return response()->json([
            'ok' => true,
            'school_year' => $data['schoolYear'],
            'count' => count($data['rows']),
            'rows' => $data['rows'],
        ]);
    }

    private function refreshSemesterScores(int $classSectionId, string $semester, string $schoolYear, int $actorUserId): void
    {
        $studentInfo = Student::getStudentInfoByClassSectionId($classSectionId, $semester, $schoolYear, $actorUserId);
        if (empty($studentInfo)) {
            return;
        }
        try {
            $this->semesterScoreService->updateScoresForStudents($studentInfo, $semester, $schoolYear);
        } catch (\Throwable $e) {
        }
    }

    /**
     * @return int|JsonResponse
     */
    private function authenticatedUserIdOrUnauthorized(): int|JsonResponse
    {
        $userId = (int) (auth()->id() ?? 0);
        if ($userId <= 0) {
            return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
        }

        return $userId;
    }
}
