<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Http\Requests\Auth\OtpRequest;
use App\Models\Otp;
use App\Services\OtpService;
use App\Support\ApiResponse;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Mortezaa97\SmsManager\Traits\SmsLogger;

class OtpController extends Controller
{
    public function store(OtpRequest $request, OtpService $otpService)
    {
        $cellphone = (string) $request->validated('cellphone');
        $data = ['cellphone' => $cellphone];

        try {
            DB::beginTransaction();

            $duration = (int) config('sms-manager.duration_restriction', 30);
            $limit = (int) config('sms-manager.sms_limit', 5);

            $recentOtpCount = Otp::query()
                ->where(function ($query) use ($cellphone, $request): void {
                    $query->where('cellphone', $cellphone)
                        ->orWhere('ip', $request->ip());
                })
                ->where('created_at', '>=', now()->subMinutes(max(1, $duration)))
                ->count();

            if ($recentOtpCount >= $limit) {
                DB::rollBack();

                return ApiResponse::response(
                    message: "شما بیش از حد مجاز پیامک درخواست کرده اید لطفا {$duration} دقیقه دیگر مجددا تلاش کنید.",
                    status: 422
                );
            }

            $code = (string) $otpService->generateOtp();
            $data['code'] = Hash::make($code);
            $data['expire_at'] = now()->addMinutes(max(1, $duration));

            $otp = Otp::query()->create($data);
            $otpService->sendOtp($cellphone, $code);

            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();

            try {
                SmsLogger::Log($exception->getMessage(), $cellphone, null, null, 'otp');
            } catch (Exception) {
                // ignore logging failures
            }

            return ApiResponse::serverError($exception->getMessage());
        }

        return ApiResponse::created([
            'cellphone' => $otp->cellphone,
            'expire_at' => $otp->expire_at?->toISOString(),
        ], 'کد تایید ارسال شد.');
    }
}
