<?php

namespace App\Services;

use App\Models\OtpCode;
use App\Models\Setting;
use App\Models\SmsTemplate;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;

class OtpService
{
    protected Client $client;

    public function __construct()
    {
        $this->client = new Client([
            'timeout' => 10,
            'verify' => public_path('cacert.pem'),
        ]);
    }

    public function generateOtp(): string
    {
        return str_pad((string) random_int(100000, 999999), 6, '0', STR_PAD_LEFT);
    }

    public function sendLoginOtp(string $mobile, string $otp): bool
    {
        $template = SmsTemplate::where('identifier', 'login_otp')->where('is_active', true)->first();
        $templateId = $template?->template_id;
        $message = $template?->body ?? "{$otp} is your verification code for Kiyo E-commerce.";
        $message = str_replace('[[otp]]', $otp, $message);

        return $this->sendOtpViaFast2sms($mobile, $otp, $templateId, $message);
    }

    public function storeOtp(string $mobile, string $otp, string $type = 'login'): void
    {
        // Delete old OTPs for this mobile and type
        OtpCode::where('mobile', $mobile)
            ->where('type', $type)
            ->delete();

        OtpCode::create([
            'mobile' => $mobile,
            'type' => $type,
            'otp_hash' => Hash::make($otp),
            'expires_at' => now()->addMinutes(5),
        ]);
    }

    public function verifyOtp(string $mobile, string $otp, string $type = 'login'): bool
    {
        $otpCode = OtpCode::where('mobile', $mobile)
            ->where('type', $type)
            ->where('expires_at', '>', now())
            ->latest()
            ->first();

        if (!$otpCode) {
            return false;
        }

        if (Hash::check($otp, $otpCode->otp_hash)) {
            $otpCode->delete();
            return true;
        }

        return false;
    }

    public function sendDiscountOtp(string $mobile, string $otp): bool
    {
        $template = SmsTemplate::where('identifier', 'pos_discount')->where('is_active', true)->first();
        $templateId = $template?->template_id;
        if (!$templateId) {
            $loginTemplate = SmsTemplate::where('identifier', 'login_otp')->where('is_active', true)->first();
            $templateId = $loginTemplate?->template_id;
        }
        $message = $template?->body ?? "{$otp} is your verification code for discount/transaction.";
        $message = str_replace('[[otp]]', $otp, $message);

        return $this->sendOtpViaFast2sms($mobile, $otp, $templateId, $message);
    }

    /**
     * Send OTP via Fast2SMS. Shared logic for login, discount, etc.
     */
    protected function sendOtpViaFast2sms(string $mobile, string $otp, ?string $templateId, string $message): bool
    {
        $smsUrl = Setting::get('sms_fast2sms_url') ?: 'https://www.fast2sms.com/dev/bulkV2';
        $apiKey = Setting::get('sms_fast2sms_api_key');

        if (!$apiKey) {
            Log::error('Fast2SMS API key not configured. Please configure it in Admin > Settings > SMS Configuration');
            throw new \RuntimeException('SMS API key not configured. Set it in Admin > Settings > SMS Configuration.');
        }

        $sender = Setting::get('sms_fast2sms_sender', 'KIYO');
        $route = Setting::get('sms_fast2sms_route', 'q');

        $params = [
            'route' => $route,
            'sender_id' => $sender,
            'message' => $message,
            'language' => 'english',
            'flash' => 0,
            'numbers' => $this->normalizeIndianMobile($mobile),
        ];

        if ($templateId) {
            $params['variables_values'] = $otp;
            $params['template_id'] = $templateId;
        }

        try {
            $response = $this->client->post($smsUrl, [
                'headers' => [
                    'authorization' => $apiKey,
                ],
                'form_params' => $params,
            ]);

            $result = json_decode($response->getBody()->getContents(), true);

            Log::info('Fast2SMS OTP sent', [
                'mobile' => $mobile,
                'response' => $result,
            ]);

            if (!($result['return'] ?? false)) {
                $apiMessage = $result['message'] ?? $result['msg'] ?? 'SMS provider rejected the request.';
                Log::warning('Fast2SMS returned failure', ['result' => $result]);
                throw new \RuntimeException($apiMessage);
            }

            return true;
        } catch (\GuzzleHttp\Exception\RequestException $e) {
            $msg = $e->getMessage();
            if ($e->hasResponse()) {
                $body = (string) $e->getResponse()->getBody();
                $decoded = json_decode($body, true);
                if (!empty($decoded['message'])) {
                    $msg = $decoded['message'];
                } elseif (!empty($decoded['msg'])) {
                    $msg = $decoded['msg'];
                }
            }
            Log::error('Fast2SMS OTP failed', ['mobile' => $mobile, 'error' => $msg]);
            throw new \RuntimeException('SMS delivery failed: ' . $msg);
        } catch (\Exception $e) {
            if ($e instanceof \RuntimeException) {
                throw $e;
            }
            Log::error('Fast2SMS OTP failed', ['mobile' => $mobile, 'error' => $e->getMessage()]);
            throw new \RuntimeException('Could not send OTP: ' . $e->getMessage());
        }
    }

    protected function normalizeIndianMobile(string $mobile): string
    {
        // Remove +91 prefix if present (expecting +91 prefix from validation)
        $mobile = preg_replace('/^\+91/', '', $mobile);

        return $mobile;
    }

    public function smsWalletBalance(): array
    {
        $smsUrl = Setting::get('sms_fast2sms_url') ?: 'https://www.fast2sms.com/dev/bulkV2'; 
        $smsUrl = str_replace('/dev/bulkV2', '', $smsUrl);
        $smsUrl = str_replace('/dev/api', '', $smsUrl);
        $apiKey = Setting::get('sms_fast2sms_api_key');
        if (!$apiKey) {
            Log::error('SMS API key not configured. Please configure it in Admin > Settings > SMS Configuration');
            $message = 'SMS API key not configured. Set it in Admin > Settings > SMS Configuration.';
        }

        try {
            $response = $this->client->post($smsUrl . '/dev/wallet', [
                'headers' => [
                    'authorization' => $apiKey,
                    'accept' => 'application/json',
                    'cache-control' => 'no-cache',
                    'content-type' => 'application/json',
                ],
            ]);

            $result = json_decode($response->getBody()->getContents(), true);

            Log::info('SMS wallet balance checked', ['response' => $result]);

            if (!($result['return'] ?? false)) {
                $message = $result['message'] ?? $result['msg'] ?? 'SMS provider rejected the request.';
                Log::warning('SMS wallet balance check returned failure', ['result' => $result]);
            }
            
            $result['smsUrl'] = $smsUrl;
            return $result;
        } catch (\GuzzleHttp\Exception\RequestException $e) {
            $msg = $e->getMessage();
            if ($e->hasResponse()) {
                $body = (string) $e->getResponse()->getBody();
                $decoded = json_decode($body, true);
                if (!empty($decoded['message'])) {
                    $msg = $decoded['message'];
                } elseif (!empty($decoded['msg'])) {
                    $msg = $decoded['msg'];
                }
            }
            Log::error('SMS wallet balance check failed', ['error' => $msg]);
            $message = 'SMS wallet balance check failed: ' . $msg;
        } catch (\Exception $e) {
            Log::error('SMS wallet balance check failed', ['error' => $e->getMessage()]);
            $message = 'Could not check SMS wallet balance: ' . $e->getMessage();
        }

        return [
            'return' => false,
            'message' => $message,
            'smsUrl' => $smsUrl,
        ];
    }
}
