<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Concerns\WritesAuthLog;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\ConfirmEmailRequest;
use App\Http\Requests\Auth\RegisterRequest;
use App\Http\Requests\Auth\ResendCodeRequest;
use App\Models\User;
use App\Services\Auth\RegistrationException;
use App\Services\Auth\RegistrationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;

/**
 * Самозапись клиента (G1/SP1): register → confirm-email → (вход).
 * Подтверждение почты 6-значным кодом; новый тенант создаётся в статусе
 * pending_email_confirm, активируется и получает 300 ₽ при подтверждении.
 */
class RegistrationController extends Controller
{
    use WritesAuthLog;

    public function register(RegisterRequest $request, RegistrationService $service): JsonResponse
    {
        try {
            $result = $service->register(
                $request->string('email')->toString(),
                $request->string('password')->toString(),
                $request->input('captcha_token'),
                $request->ip(),
            );
        } catch (RegistrationException $e) {
            return $this->registrationError($e);
        }

        $payload = [
            'status' => $result['status'],
            'email' => $result['user']->email,
            'expires_at' => $result['verification']->expires_at->toIso8601String(),
        ];
        if ($result['dev_code'] !== null) {
            $payload['_dev_plain_code'] = $result['dev_code'];
        }

        return response()->json($payload, 201);
    }

    public function confirmEmail(ConfirmEmailRequest $request, RegistrationService $service): JsonResponse
    {
        try {
            $user = $service->confirm(
                $request->string('email')->toString(),
                $request->string('code')->toString(),
            );
        } catch (RegistrationException $e) {
            $payload = ['message' => 'Код подтверждения недействителен.', 'reason' => $e->reason];
            if ($e->attemptsRemaining !== null) {
                $payload['attempts_remaining'] = $e->attemptsRemaining;
            }

            return response()->json($payload, 422);
        }

        Auth::login($user);
        $request->session()->regenerate();
        $this->logAuthEvent('register_success', $user->id, $user->tenant_id, $user->email, $request->ip(), $request->userAgent(), null);

        return response()->json([
            'user' => $this->userResource($user),
            'requires_2fa' => false,
        ]);
    }

    public function resendCode(ResendCodeRequest $request, RegistrationService $service): JsonResponse
    {
        $devCode = $service->resend($request->string('email')->toString());

        $payload = ['message' => 'Если аккаунт ожидает подтверждения, мы отправили новый код на указанный email.'];
        if ($devCode !== null) {
            $payload['_dev_plain_code'] = $devCode;
        }

        return response()->json($payload);
    }

    private function registrationError(RegistrationException $e): JsonResponse
    {
        $map = [
            'captcha_failed' => ['captcha_token', 'Проверка «я не робот» не пройдена.'],
            'email_taken' => ['email', 'Аккаунт с таким email уже существует.'],
        ];
        [$field, $message] = $map[$e->reason] ?? ['email', 'Не удалось зарегистрировать аккаунт.'];

        return response()->json([
            'message' => $message,
            'errors' => [$field => [$message]],
        ], 422);
    }

    /** @return array<string, mixed> */
    private function userResource(User $user): array
    {
        return [
            'id' => $user->id,
            'email' => $user->email,
            'first_name' => $user->first_name,
            'last_name' => $user->last_name,
            'phone' => $user->phone,
            'timezone' => $user->timezone,
            'tenant_id' => $user->tenant_id,
            'totp_enabled' => $user->totp_enabled,
            'last_login_at' => $user->last_login_at,
            'notification_preferences' => $user->notification_preferences,
            'sound_enabled' => $user->sound_enabled,
        ];
    }
}
