<?php

namespace App\Http\Controllers;

use App\Models\EmailVerification;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;

class EmailVerificationController extends Controller
{
    public function sendOtp(Request $request)
    {
        $request->validate([
            'init_data' => ['required', 'string'],
            'email' => ['required', 'email', 'ends_with:@gmail.com'],
        ]);

        $user = $this->getTelegramUser($request->init_data);

        if (!$user) {
            return response()->json([
                'success' => false,
                'message' => 'Telegram authentication failed.',
            ], 401);
        }

        if ($user->email_verified_at) {
            return response()->json([
                'success' => true,
                'message' => 'Email already verified.',
                'already_verified' => true,
            ]);
        }

        $recent = EmailVerification::where('user_id', $user->id)
            ->where('created_at', '>', now()->subSeconds(60))
            ->exists();

        if ($recent) {
            return response()->json([
                'success' => false,
                'message' => 'Please wait 60 seconds before requesting another OTP.',
            ], 429);
        }

        $otp = (string) random_int(100000, 999999);

        EmailVerification::where('user_id', $user->id)
            ->whereNull('verified_at')
            ->delete();

        EmailVerification::create([
            'user_id' => $user->id,
            'email' => $request->email,
            'otp_hash' => Hash::make($otp),
            'expires_at' => now()->addMinutes(10),
            'attempts' => 0,
        ]);

        Mail::raw(
            "Your BDCodeShop verification code is: {$otp}\n\nThis code will expire in 10 minutes.\nIf you did not request this code, please ignore this email.",
            function ($message) use ($request) {
                $message
                    ->to($request->email)
                    ->subject('BDCodeShop - Email Verification Code');
            }
        );

        return response()->json([
            'success' => true,
            'message' => 'OTP sent successfully.',
        ]);
    }

    public function verifyOtp(Request $request)
    {
        $request->validate([
            'init_data' => ['required', 'string'],
            'otp' => ['required', 'digits:6'],
        ]);

        $user = $this->getTelegramUser($request->init_data);

        if (!$user) {
            return response()->json([
                'success' => false,
                'message' => 'Telegram authentication failed.',
            ], 401);
        }

        $verification = EmailVerification::where('user_id', $user->id)
            ->whereNull('verified_at')
            ->latest()
            ->first();

        if (!$verification) {
            return response()->json([
                'success' => false,
                'message' => 'No active OTP found.',
            ], 422);
        }

        if (now()->greaterThan($verification->expires_at)) {
            return response()->json([
                'success' => false,
                'message' => 'OTP has expired. Please request a new one.',
            ], 422);
        }

        if ($verification->attempts >= 5) {
            return response()->json([
                'success' => false,
                'message' => 'Too many incorrect attempts. Please request a new OTP.',
            ], 429);
        }

        if (!Hash::check($request->otp, $verification->otp_hash)) {
            $verification->increment('attempts');

            return response()->json([
                'success' => false,
                'message' => 'Incorrect OTP.',
            ], 422);
        }

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

        $user->update([
            'email' => $verification->email,
            'email_verified_at' => now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Email verified successfully.',
            'next_step' => 'device_verification',
        ]);
    }

    private function getTelegramUser(string $initData): ?User
    {
        parse_str($initData, $data);

        if (
            empty($data['hash']) ||
            empty($data['auth_date']) ||
            empty($data['user'])
        ) {
            return null;
        }

        if (time() - (int) $data['auth_date'] > 86400) {
            return null;
        }

        $receivedHash = $data['hash'];
        unset($data['hash']);

        ksort($data);

        $dataCheckString = collect($data)
            ->map(fn ($value, $key) => $key . '=' . $value)
            ->implode("\n");

        $botToken = config('services.telegram.bot_token');

        if (!$botToken) {
            return null;
        }

        $secretKey = hash_hmac(
            'sha256',
            $botToken,
            'WebAppData',
            true
        );

        $calculatedHash = hash_hmac(
            'sha256',
            $dataCheckString,
            $secretKey
        );

        if (!hash_equals($calculatedHash, $receivedHash)) {
            return null;
        }

        $telegramUser = json_decode($data['user'], true);

        if (!is_array($telegramUser) || empty($telegramUser['id'])) {
            return null;
        }

        return User::where(
            'telegram_id',
            (string) $telegramUser['id']
        )->first();
    }
}
