<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\StudentExamSession;
use App\Services\StudentExamService;
use App\Services\StudentMobileAuthService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class StudentAuthController extends Controller
{
    public function __construct(
        private readonly StudentMobileAuthService $mobileAuthService,
        private readonly StudentExamService $examService,
    ) {
    }

    private function appBootstrapPayload(): array
    {
        return [
            'api_base_path' => '/api/' . trim((string) config('mobile_exam.api_prefix', 'secure-student-api'), '/'),
            'security' => [
                'client_header' => (string) config('mobile_exam.client_header', 'X-Mobile-Client'),
                'key_header' => (string) config('mobile_exam.key_header', 'X-Mobile-Key'),
                'signature_required' => (bool) config('mobile_exam.require_signature', false),
                'signature_header' => (string) config('mobile_exam.signature_header', 'X-Mobile-Signature'),
                'timestamp_header' => (string) config('mobile_exam.timestamp_header', 'X-Mobile-Timestamp'),
                'signature_ttl_seconds' => max(30, (int) config('mobile_exam.signature_ttl_seconds', 300)),
                'single_active_device' => (bool) config('mobile_exam.single_active_device', true),
                'single_active_exam_session' => (bool) config('mobile_exam.single_active_exam_session', true),
            ],
            'exam' => [
                'heartbeat_timeout_seconds' => max(5, (int) config('mobile_exam.heartbeat_timeout_seconds', 20)),
                'default_duration_minutes' => max(1, (int) config('mobile_exam.exam_duration_minutes', 25)),
                'auto_submit_events' => array_values(config('mobile_exam.auto_submit_events', [])),
            ],
        ];
    }

    public function login(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'login' => ['required', 'string', 'max:190'],
            'password' => ['required', 'string', 'max:190'],
            'device_uid' => ['required', 'string', 'max:190'],
            'device_name' => ['nullable', 'string', 'max:190'],
            'platform' => ['nullable', 'string', 'max:40'],
            'app_version' => ['nullable', 'string', 'max:40'],
        ]);

        $result = $this->mobileAuthService->attemptStudentLogin(
            $validated['login'],
            $validated['password'],
            [
                'device_uid' => $validated['device_uid'],
                'device_name' => $validated['device_name'] ?? null,
                'platform' => $validated['platform'] ?? null,
                'app_version' => $validated['app_version'] ?? null,
            ],
            $request,
        );

        if (($result['status'] ?? null) !== 'ok') {
            $statusCode = match ($result['status'] ?? 'invalid_credentials') {
                'blocked' => 423,
                'exam_active' => 423,
                default => 401,
            };

            return response()->json([
                'message' => $result['message'] ?? 'Login failed.',
            ], $statusCode);
        }

        return response()->json([
            'message' => 'Student login successful.',
            'token' => $result['token'],
            'token_type' => 'Bearer',
            'student' => $this->examService->buildStudentProfilePayload($result['user']),
            'device_session' => [
                'session_key' => $result['device_session']->session_key,
                'device_uid' => $result['device_session']->device_uid,
                'device_name' => $result['device_session']->device_name,
                'platform' => $result['device_session']->platform,
                'app_version' => $result['device_session']->app_version,
                'login_at' => $result['device_session']->login_at?->toIso8601String(),
            ],
            'app_bootstrap' => $this->appBootstrapPayload(),
            'active_exam_session' => $this->examService->activeExamSessionBrief($result['user']),
        ]);
    }

    public function register(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:100'],
            'mobile_number' => ['required', 'regex:/^[6-9][0-9]{9}$/', 'unique:users,mobileno'],
            'password' => ['required', 'string', 'min:6', 'max:50', 'same:confirm_password'],
            'confirm_password' => ['required', 'string', 'min:6', 'max:50'],
            'school_code' => ['nullable', 'string', 'max:100'],
            'device_uid' => ['required', 'string', 'max:190'],
            'device_name' => ['nullable', 'string', 'max:190'],
            'platform' => ['nullable', 'string', 'max:40'],
            'app_version' => ['nullable', 'string', 'max:40'],
        ]);

        $result = $this->mobileAuthService->registerStudent(
            $validated,
            [
                'device_uid' => $validated['device_uid'],
                'device_name' => $validated['device_name'] ?? null,
                'platform' => $validated['platform'] ?? null,
                'app_version' => $validated['app_version'] ?? null,
            ],
            $request,
        );

        return response()->json([
            'message' => 'Student registration successful.',
            'token' => $result['token'],
            'token_type' => 'Bearer',
            'student' => $this->examService->buildStudentProfilePayload($result['user']),
            'device_session' => [
                'session_key' => $result['device_session']->session_key,
                'device_uid' => $result['device_session']->device_uid,
                'device_name' => $result['device_session']->device_name,
                'platform' => $result['device_session']->platform,
                'app_version' => $result['device_session']->app_version,
                'login_at' => $result['device_session']->login_at?->toIso8601String(),
            ],
            'app_bootstrap' => $this->appBootstrapPayload(),
        ], 201);
    }

    public function sendForgotPasswordOtp(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'mobile_number' => ['required', 'regex:/^[6-9][0-9]{9}$/'],
        ]);

        $result = $this->mobileAuthService->sendForgotPasswordOtp(
            (string) $validated['mobile_number'],
            $request,
        );

        $statusCode = match ($result['status'] ?? 'missing_user') {
            'sent' => 200,
            'missing_user' => 404,
            default => 422,
        };

        return response()->json($result, $statusCode);
    }

    public function verifyForgotPasswordOtp(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'mobile_number' => ['required', 'regex:/^[6-9][0-9]{9}$/'],
            'otp' => ['required', 'digits:6'],
        ]);

        $result = $this->mobileAuthService->verifyForgotPasswordOtp(
            (string) $validated['mobile_number'],
            (string) $validated['otp'],
            $request,
        );

        $statusCode = match ($result['status'] ?? 'invalid_otp') {
            'verified' => 200,
            'missing_user' => 404,
            'invalid_otp' => 422,
            default => 422,
        };

        return response()->json($result, $statusCode);
    }

    public function resetForgotPassword(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'mobile_number' => ['required', 'regex:/^[6-9][0-9]{9}$/'],
            'reset_token' => ['required', 'string', 'min:20', 'max:190'],
            'password' => ['required', 'string', 'min:6', 'max:50', 'same:confirm_password'],
            'confirm_password' => ['required', 'string', 'min:6', 'max:50'],
        ]);

        $result = $this->mobileAuthService->resetPasswordWithVerifiedToken(
            (string) $validated['mobile_number'],
            (string) $validated['reset_token'],
            (string) $validated['password'],
            $request,
        );

        $statusCode = match ($result['status'] ?? 'invalid_reset_token') {
            'updated' => 200,
            'missing_user' => 404,
            'invalid_reset_token' => 422,
            default => 422,
        };

        return response()->json($result, $statusCode);
    }

    public function logout(Request $request): JsonResponse
    {
        $accessToken = $request->attributes->get('mobileAccessToken');
        $deviceSession = $request->attributes->get('studentDeviceSession');
        $user = $request->user();

        if ($user && $deviceSession) {
            $activeExamSession = StudentExamSession::query()
                ->where('user_id', $user->id)
                ->where('student_device_session_id', $deviceSession->id)
                ->where('status', 'active')
                ->latest('id')
                ->first();

            if ($activeExamSession) {
                $this->examService->submitExamSession(
                    $activeExamSession,
                    $activeExamSession->draft_answers ?? [],
                    (int) $activeExamSession->elapsed_seconds,
                    'student_logout',
                    $request,
                    true,
                );
            }
        }

        if ($accessToken) {
            $this->mobileAuthService->revokeCurrentSession($accessToken, $deviceSession, $request);
        }

        return response()->json([
            'message' => 'Student logout successful.',
        ]);
    }

    public function me(Request $request): JsonResponse
    {
        $user = $request->user();
        $deviceSession = $request->attributes->get('studentDeviceSession');

        return response()->json([
            'student' => $this->examService->buildStudentProfilePayload($user),
            'device_session' => $deviceSession ? [
                'session_key' => $deviceSession->session_key,
                'device_uid' => $deviceSession->device_uid,
                'device_name' => $deviceSession->device_name,
                'platform' => $deviceSession->platform,
                'app_version' => $deviceSession->app_version,
                'last_seen_at' => $deviceSession->last_seen_at?->toIso8601String(),
            ] : null,
            'app_bootstrap' => $this->appBootstrapPayload(),
            'active_exam_session' => $this->examService->activeExamSessionBrief($user),
        ]);
    }
}
