<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Helpers\ApiResponse;
use App\Mail\TwoFactorOtp;
use App\Services\Auth\OtpService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use OpenApi\Attributes as OA;

class OtpController extends Controller
{
    public function __construct(protected OtpService $otpService) {}

    #[OA\Post(
        path: '/v1/otp/send',
        operationId: 'otpSend',
        tags: ['OTP'],
        summary: 'Send a 6-digit OTP to the given email',
        requestBody: new OA\RequestBody(
            required: true,
            content: new OA\JsonContent(
                required: ['email'],
                properties: [new OA\Property(property: 'email', type: 'string', format: 'email')]
            )
        ),
        responses: [
            new OA\Response(response: 200, description: 'OTP sent'),
            new OA\Response(response: 500, description: 'Mail delivery failed'),
        ]
    )]
    public function send(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
        ]);

        $email = $request->email;
        $code = $this->otpService->generate($email);

        try {
            Mail::to($email)->send(new TwoFactorOtp(
                otp: $code,
                ipAddress: $request->ip(),
                userAgent: $request->userAgent(),
            ));
        } catch (\Throwable $e) {
            Log::error('OTP send failed', ['email' => $email, 'error' => $e->getMessage()]);

            return ApiResponse::serverError('Failed to send OTP. Please try again later.');
        }

        return ApiResponse::success(null, 'OTP has been sent to your email');
    }

    #[OA\Post(
        path: '/v1/otp/verify',
        operationId: 'otpVerify',
        tags: ['OTP'],
        summary: 'Verify an OTP code',
        requestBody: new OA\RequestBody(
            required: true,
            content: new OA\JsonContent(
                required: ['email', 'code'],
                properties: [
                    new OA\Property(property: 'email', type: 'string', format: 'email'),
                    new OA\Property(property: 'code', type: 'string', minLength: 6, maxLength: 6, example: '123456'),
                ]
            )
        ),
        responses: [
            new OA\Response(response: 200, description: 'OTP verified'),
            new OA\Response(response: 422, description: 'Invalid or expired OTP'),
        ]
    )]
    public function verify(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'code' => 'required|string|size:6',
        ]);

        if (! $this->otpService->verify($request->input('email'), $request->input('code'))) {
            return ApiResponse::error('Invalid or expired OTP code', 422);
        }

        return ApiResponse::success(null, 'OTP verified successfully');
    }
}
