<?php

namespace App\Http\Controllers\Api\Delivery;

use App\Http\Controllers\Controller;
use App\Models\DeliveryPartner;
use App\Models\DeliveryPartnerApplication;
use App\Services\AccountService;
use App\Services\OtpService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
    public function __construct(private OtpService $otpService) {}

    public function startApplication(Request $request): JsonResponse
    {
        $request->validate([
            'name'  => 'required|string|max:100',
            'phone' => 'required|string|regex:/^03[0-9]{9}$/',
            'cnic'  => 'required|string|regex:/^[0-9]{5}-[0-9]{7}-[0-9]{1}$/',
        ]);

        if (DeliveryPartnerApplication::where('phone', $request->phone)->exists()) {
            return response()->json(['message' => 'Application already exists for this phone.'], 422);
        }

        $app = DeliveryPartnerApplication::create([
            'name'         => $request->name,
            'phone'        => $request->phone,
            'cnic'         => $request->cnic,
            'status'       => 'draft',
            'current_step' => 1,
        ]);

        $this->otpService->generate($request->phone, 'register');

        return response()->json(['message' => 'OTP sent.', 'application_id' => $app->id]);
    }

    public function verifyPhone(Request $request): JsonResponse
    {
        $request->validate([
            'application_id' => 'required|exists:delivery_partner_applications,id',
            'code'           => 'required|string|size:6',
        ]);

        $app = DeliveryPartnerApplication::findOrFail($request->application_id);

        if (! $this->otpService->verify($app->phone, $request->code, 'register')) {
            return response()->json(['message' => 'Invalid or expired OTP.'], 422);
        }

        $app->update(['step1_phone_verified' => true, 'current_step' => 2]);

        return response()->json(['message' => 'Phone verified.', 'application' => $app]);
    }

    public function sendLoginOtp(Request $request): JsonResponse
    {
        $request->validate(['phone' => 'required|string|regex:/^03[0-9]{9}$/']);

        if (! DeliveryPartner::where('phone', $request->phone)->exists()) {
            return response()->json(['message' => 'Delivery partner not found.'], 404);
        }

        $this->otpService->generate($request->phone, 'login');

        return response()->json(['message' => 'OTP sent.']);
    }

    public function login(Request $request): JsonResponse
    {
        $request->validate([
            'phone' => 'required|string|regex:/^03[0-9]{9}$/',
            'code'  => 'required|string|size:6',
        ]);

        if (! $this->otpService->verify($request->phone, $request->code, 'login')) {
            return response()->json(['message' => 'Invalid or expired OTP.'], 422);
        }

        $partner = DeliveryPartner::where('phone', $request->phone)->firstOrFail();

        if (! $partner->isActive()) {
            return response()->json(['message' => 'Your account is suspended.'], 403);
        }

        $token = Auth::guard('delivery')->login($partner);

        return response()->json([
            'token_type'   => 'bearer',
            'access_token' => $token,
            'expires_in'   => Auth::guard('delivery')->factory()->getTTL() * 60,
            'partner'      => [
                'id'           => $partner->id,
                'name'         => $partner->name,
                'phone'        => $partner->phone,
                'vehicle_type' => $partner->vehicle_type,
                'is_online'    => $partner->is_online,
                'status'       => $partner->status,
            ],
        ]);
    }

    public function refresh(): JsonResponse
    {
        $token = Auth::guard('delivery')->refresh();
        return response()->json(['access_token' => $token]);
    }

    public function logout(): JsonResponse
    {
        Auth::guard('delivery')->logout();
        return response()->json(['message' => 'Logged out.']);
    }

    public function me(): JsonResponse
    {
        return response()->json(Auth::guard('delivery')->user());
    }

    // Change phone — step 1: send OTP to the new number.
    public function changePhoneRequest(Request $request, AccountService $accounts): JsonResponse
    {
        $request->validate(['new_phone' => 'required|string|regex:/^03[0-9]{9}$/']);

        if (DeliveryPartner::where('phone', $request->new_phone)->exists()) {
            return response()->json(['message' => 'That number is already in use.'], 422);
        }

        $accounts->sendPhoneChangeOtp($request->new_phone);

        return response()->json(['message' => 'OTP sent to the new number.']);
    }

    // Change phone — step 2: verify the OTP and switch the number.
    public function changePhoneConfirm(Request $request, AccountService $accounts): JsonResponse
    {
        $request->validate([
            'new_phone' => 'required|string|regex:/^03[0-9]{9}$/',
            'code'      => 'required|string|size:6',
        ]);

        if (DeliveryPartner::where('phone', $request->new_phone)->exists()) {
            return response()->json(['message' => 'That number is already in use.'], 422);
        }

        $partner = Auth::guard('delivery')->user();
        if (! $accounts->confirmPhoneChange($partner, $request->new_phone, $request->code)) {
            return response()->json(['message' => 'Invalid or expired OTP.'], 422);
        }

        return response()->json(['message' => 'Phone number updated.', 'phone' => $partner->phone]);
    }

    // Self-service account deletion.
    public function deleteAccount(Request $request, AccountService $accounts): JsonResponse
    {
        $accounts->requestDeletion(Auth::guard('delivery')->user());
        Auth::guard('delivery')->logout();

        return response()->json(['message' => 'Your rider account has been deactivated and is scheduled for deletion.']);
    }
}
