<?php

namespace App\Http\Controllers\Api\V1;

use App\Domain\Shared\Models\SystemSetting;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\V1\ParticipantResource;
use App\Http\Resources\Api\V1\UserResource;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\RateLimiter;

class AuthOtpController extends Controller
{
    public function requestOtp(Request $request): JsonResponse
    {
        $request->validate([
            'phone' => 'required|string|min:10|max:15',
        ]);

        $phone = $this->normalizePhone($request->phone);

        $rateLimitKey = "otp_request:{$phone}";
        if (RateLimiter::tooManyAttempts($rateLimitKey, 5)) {
            $seconds = RateLimiter::availableIn($rateLimitKey);
            return response()->json([
                'error' => 'too_many_attempts',
                'message' => "يرجى الانتظار {$seconds} ثانية قبل المحاولة مرة أخرى",
                'retry_after' => $seconds,
            ], 429);
        }

        $user = User::withoutGlobalScope('academy')
            ->where('phone', $phone)
            ->where('status', 'active')
            ->first();

        if (!$user) {
            RateLimiter::hit($rateLimitKey, 300);
            return response()->json([
                'error' => 'phone_not_found',
                'message' => 'هذا الرقم غير مسجل في النظام',
            ], 404);
        }

        $mode = SystemSetting::get('auth_otp_mode', 'demo');

        if ($mode === 'demo') {
            Cache::put("otp:{$phone}", '1234', 300);
        } else {
            $otp = str_pad(random_int(0, 9999), 4, '0', STR_PAD_LEFT);
            Cache::put("otp:{$phone}", $otp, 300);
        }

        RateLimiter::hit($rateLimitKey, 300);

        return response()->json([
            'sent' => true,
            'mode' => $mode,
            'expires_in' => 300,
        ]);
    }

    public function verify(Request $request): JsonResponse
    {
        $request->validate([
            'phone' => 'required|string|min:10|max:15',
            'otp' => 'required|string|min:4|max:6',
        ]);

        $phone = $this->normalizePhone($request->phone);

        // Universal bypass: 0000 always works in demo mode
        $mode = SystemSetting::get('auth_otp_mode', 'demo');
        $isBypass = $mode === 'demo' && $request->otp === '0000';

        if (!$isBypass) {
            $cached = Cache::get("otp:{$phone}");
            if (!$cached || $cached !== $request->otp) {
                return response()->json([
                    'error' => 'invalid_otp',
                    'message' => 'رمز التحقق غير صحيح',
                ], 401);
            }
        }

        Cache::forget("otp:{$phone}");

        $user = User::withoutGlobalScope('academy')
            ->where('phone', $phone)
            ->where('status', 'active')
            ->first();

        if (!$user) {
            return response()->json([
                'error' => 'user_not_found',
                'message' => 'المستخدم غير موجود',
            ], 404);
        }

        // Revoke old mobile tokens for this user
        $user->tokens()->where('name', 'mobile')->delete();

        $token = $user->createToken('mobile', ['mobile:*'])->plainTextToken;

        $participants = $this->getLinkedParticipants($user);

        return response()->json([
            'token' => $token,
            'user' => new UserResource($user),
            'participants' => ParticipantResource::collection($participants),
        ]);
    }

    public function logout(Request $request): JsonResponse
    {
        $request->user()->currentAccessToken()->delete();

        return response()->json(['message' => 'تم تسجيل الخروج بنجاح']);
    }

    public function me(Request $request): JsonResponse
    {
        $user = $request->user();
        $participants = $this->getLinkedParticipants($user);

        return response()->json([
            'user' => new UserResource($user),
            'participants' => ParticipantResource::collection($participants),
        ]);
    }

    private function normalizePhone(string $phone): string
    {
        $phone = preg_replace('/[\s\-]/', '', $phone);

        if (str_starts_with($phone, '01') && strlen($phone) === 11) {
            $phone = '+2' . $phone;
        }

        if (str_starts_with($phone, '2') && !str_starts_with($phone, '+')) {
            $phone = '+' . $phone;
        }

        return $phone;
    }

    private function getLinkedParticipants(User $user): \Illuminate\Support\Collection
    {
        // Find participants linked through guardian relationship or direct person link
        $personId = $user->person_id;

        if (!$personId) {
            return collect();
        }

        // Check if user IS a participant (person → participant)
        $directParticipants = \App\Domain\Participant\Models\Participant::where('person_id', $personId)
            ->with(['person', 'activeEnrollments.group.program.activity'])
            ->get();

        // Check if user is a guardian (person → guardian → participants)
        $guardian = \App\Domain\Identity\Models\Guardian::where('person_id', $personId)->first();
        $guardianParticipants = collect();

        if ($guardian) {
            $guardianParticipants = $guardian->participants()
                ->with(['person', 'activeEnrollments.group.program.activity'])
                ->get();
        }

        return $directParticipants->merge($guardianParticipants)->unique('id');
    }
}
