<?php

namespace Modules\Identity\Http\Controllers;

use App\Models\User;
use Illuminate\Routing\Controller;
use Illuminate\Validation\ValidationException;
use Modules\Identity\Enums\TokenAbility;
use Modules\Identity\Http\Requests\RegisterRequest;
use Modules\Identity\Http\Requests\RequestRegistrationCodeRequest;
use Modules\Identity\Http\Requests\VerifyRegistrationCodeRequest;
use Modules\Identity\Models\RegistrationVerification;

/**
 * Confirm-first registration (mini app / mobile app): request a code for an
 * email or phone, verify it, then complete registration with the
 * verification_token that step returns. Kept as three actions on one
 * controller since they're steps of a single flow sharing the same model.
 */
class RegistrationController extends Controller
{
    public function requestCode(RequestRegistrationCodeRequest $request): array
    {
        RegistrationVerification::issueFor($request->string('identifier')->toString(), $request->identifierType());

        return ['message' => 'A verification code has been sent.'];
    }

    public function verifyCode(VerifyRegistrationCodeRequest $request): array
    {
        $verification = RegistrationVerification::where('identifier', $request->string('identifier'))->first();

        if (! $verification || $verification->isExpired()) {
            throw ValidationException::withMessages([
                'code' => ['This code has expired. Please request a new one.'],
            ]);
        }

        if (! $verification->attemptVerify($request->string('code')->toString())) {
            throw ValidationException::withMessages([
                'code' => ['The provided code is incorrect.'],
            ]);
        }

        return ['verification_token' => $verification->verification_token];
    }

    public function store(RegisterRequest $request): array
    {
        $verification = RegistrationVerification::where('verification_token', $request->string('verification_token'))->first();

        if (! $verification || ! $verification->isVerified() || $verification->isConsumed() || $verification->isExpired()) {
            throw ValidationException::withMessages([
                'verification_token' => ['This verification has expired or was already used. Please start again.'],
            ]);
        }

        $user = User::create([
            'name' => $request->string('name'),
            'email' => $verification->type === 'email' ? $verification->identifier : null,
            'phone' => $verification->type === 'phone' ? $verification->identifier : null,
            'password' => $request->string('password'),
        ]);

        $verification->update(['consumed_at' => now()]);

        $token = $user->createToken(
            $request->string('device_name')->toString(),
            TokenAbility::customerAbilities(),
        );

        return [
            'token' => $token->plainTextToken,
        ];
    }
}
