<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\KaaliiPackageVersion;
use App\Models\License;
use App\Models\Product;
use App\Models\RequestDataLog;
use App\Models\Setting;
use App\Services\EnvatoService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;

class LicenseApiController extends Controller
{
    protected $envatoService;

    public function __construct(EnvatoService $envatoService)
    {
        $this->envatoService = $envatoService;
    }

    /**
     * Get API token from database settings
     */
    private function getApiToken(): string
    {
        return \App\Helpers\ConfigHelper::getSetting('license_api_token', '', 'LICENSE_API_TOKEN');
    }

    /**
     * Verify license endpoint
     * This endpoint is used by the generated license files
     */
    public function verify(Request $request): JsonResponse
    {
        // Check authorization header
        $authHeader = $request->header('Authorization') ?? $request->header('AuthorizationX');
        $expectedToken = 'Bearer ' . $this->getApiToken();
        // dd($authHeader, $expectedToken);

        if (!$expectedToken || $authHeader !== $expectedToken) {
            // Log unauthorized attempt
            $this->logApiVerificationAttempt($request, false, 'Unauthorized access attempt', 'api');

            return response()->json([
                'valid' => false,
                'message' => 'Unauthorized',
                'error_code' => 'UNAUTHORIZED'
            ], 401);
        }

        $validated = $request->validate([
            'purchase_code' => 'required|string|min:10|max:100',
            'product_slug' => 'required|string|max:255',
            'domain' => 'nullable|string|max:255',
            'verification_key' => 'nullable|string|max:255',
            'device_type' => 'nullable|in:1,2', // 1=web and 2=mob
        ]);

        $purchaseCode = $validated['purchase_code'];
        $productSlug = $validated['product_slug'];
        $domain = $validated['domain'] ?? null;
        $verificationKey = $validated['verification_key'] ?? null;
        $deviceType = $validated['device_type'] ?? 1; // default set as web device

        try {
            // Find product by slug
            $product = Product::where('slug', $productSlug)->first();

            if (!$product) {
                $this->logApiVerificationAttempt($request, false, 'Product not found', 'api');

                return response()->json([
                    'valid' => false,
                    'message' => 'Product not found',
                    'error_code' => 'PRODUCT_NOT_FOUND'
                ], 404);
            }

            // Verify verification key if provided
            if ($verificationKey && !$this->verifyVerificationKey($product, $verificationKey)) {
                $this->logApiVerificationAttempt($request, false, 'Invalid verification key', 'api');

                return response()->json([
                    'valid' => false,
                    'message' => 'Invalid verification key',
                    'error_code' => 'INVALID_VERIFICATION_KEY'
                ], 403);
            }

            // Step 1: Check if license exists in our database
            $license = License::where('purchase_code', $purchaseCode)
                ->where('product_id', $product->id)
                ->first();

            $databaseValid = false;
            $envatoValid = false;
            $verificationMethod = '';

            // Step 2: Check database license first
            if ($license) {
                // License exists, check its status
                if ($license->status === 'active') {
                    // Check if license has expired
                    if ($license->license_expires_at && $license->license_expires_at->isPast()) {
                        $this->logApiVerificationAttempt($request, false, 'License has expired', 'api');
                        return response()->json([
                            'valid' => false,
                            'message' => 'License has expired',
                            'error_code' => 'LICENSE_EXPIRED',
                            'data' => [
                                'expires_at' => $license->license_expires_at->toISOString()
                            ]
                        ], 403);
                    }

                    $databaseValid = true;
                    $verificationMethod = 'database_only';
                } elseif ($license->status === 'suspended') {
                    $this->logApiVerificationAttempt($request, false, 'License is suspended', 'api');
                    return response()->json([
                        'valid' => false,
                        'message' => 'License is suspended',
                        'error_code' => 'LICENSE_SUSPENDED'
                    ], 403);
                } else {
                    $this->logApiVerificationAttempt($request, false, 'License is not active', 'api');
                    return response()->json([
                        'valid' => false,
                        'message' => 'License is not active',
                        'error_code' => 'LICENSE_INACTIVE'
                    ], 403);
                }
            } else {
                // Step 3: If not in database, try Envato API
                $envatoData = $this->envatoService->verifyPurchase($purchaseCode);
                if ($envatoData && isset($envatoData['item']['id']) && $envatoData['item']['id'] == $product->envato_item_id) {
                    $envatoValid = true;
                    // Create license automatically from Envato
                    $license = $this->createLicenseFromEnvato($product, $purchaseCode, $envatoData);
                    $databaseValid = true;
                    $verificationMethod = 'envato_auto_created';
                } else {
                    // Both invalid - reject and log error
                    $this->logApiVerificationAttempt($request, false, 'License not found', 'api');

                    return response()->json([
                        'valid' => false,
                        'message' => 'License not found',
                        'error_code' => 'LICENSE_NOT_FOUND'
                    ], 404);
                }
            }

            // Step 5: Handle domain registration/verification
            if ($domain) {
                // Check if auto domain registration is enabled
                $autoRegisterDomains = \App\Helpers\ConfigHelper::getSetting('license_auto_register_domains', false);
                $isTestMode = config('app.env') === 'local' || config('app.debug') === true;

                if ($autoRegisterDomains || $isTestMode) {
                    // Auto register mode: Register domain automatically
                    $this->registerDomainForLicense($license, $domain);
                    $this->logApiVerificationAttempt($request, true, 'Domain registered automatically', 'api', [
                        'domain' => $domain,
                        'license_id' => $license->id,
                        'mode' => $isTestMode ? 'test' : 'auto_register'
                    ]);
                } else {
                    // Verification mode: Verify domain authorization
                    if (!$this->verifyDomain($license, $domain)) {
                        $this->logApiVerificationAttempt($request, false, 'Domain not authorized for this license', 'api');

                        return response()->json([
                            'valid' => false,
                            'message' => 'Domain not authorized for this license',
                            'error_code' => 'DOMAIN_NOT_AUTHORIZED'
                        ], 403);
                    }
                }
            }

            // Step 6: Log successful verification
            $this->logApiVerificationAttempt($request, true, 'License verified successfully', 'api', [
                'license_id' => $license->id,
                'verification_method' => $verificationMethod,
                'envato_valid' => $envatoValid,
                'database_valid' => $databaseValid,
            ]);

            // Step 7: Log verification in database
            $this->logVerification($license, $domain, $verificationMethod);

            // AffectedRoutes
            $effectedRoutes = $license->affected_routes && is_string($license->affected_routes) ? json_decode($license->affected_routes, true) : $license->affected_routes;
            $effectedRoutes = $effectedRoutes ?? [];
            $effectedRoutesWithHtmlCode = [];
            foreach ($effectedRoutes as $element) {
                $effectedRoutesWithHtmlCode[] = [
                    'route' => $element['route'],
                    'showProbability' => number_format($element['showProbability'], 2) ?? 0,
                    'app_messages' => is_array($element['message']) ? $element['message'] : [$element['message']],
                    'html_code' => $this->generateHtmlInjectionCode($element['message'], $license->message_key)
                ];
            }
            // dd($effectedRoutes);
            $effectedMobileRoutes = $license->affected_mobile_routes && is_string($license->affected_mobile_routes) ? json_decode($license->affected_mobile_routes, true) : [];
            $effectedMobileRoutes = $effectedMobileRoutes ?? [];

            $effectedMobileRoutesWithMessages = [];
            foreach ($effectedMobileRoutes as $element) {
                $effectedMobileRoutesWithMessages[] = [
                    'screen' => $element['screen'],
                    'showProbability' => number_format($element['showProbability'], 2) ?? 0,
                    'app_messages' => is_array($element['message']) ? $element['message'] : [$element['message']],
                ];
            }

            $settings = $license->settings ? json_decode($license->settings, true) : [
                'cache' => true,
                'cache_ttl_in_seconds' => 60,
                'push_code_enable' => false,
                'strictLicenseError' => false,
            ];
            if ($settings['push_code_enable']) {
                $settings['cache'] = false;
            }

            $allowedDomains = $license->allowed_domains && is_string($license->allowed_domains) ? json_decode($license->allowed_domains, true) : [];
            $allowedDomains = $allowedDomains ?? [];
            $authorizedDomains = $license->domains()->where('status', 'active')->pluck('domain')->toArray();

            // library info
            // dd($request['library_tech_stack']);
            $library_info = $license->library_info ? json_decode($license->library_info, true) : [];
            $isDbLibraryInfoExist = !empty($library_info);
            // $tech_stack = $tech_stack = $request['library_tech_stack'] ?? ($library_info['tech_stack'] ?? '');
            $tech_stack = $request['library_tech_stack'] ?? '';
            // dd($tech_stack);
            $tech_stack_id = \App\Models\ProgrammingLanguage::where('slug', $tech_stack)->first();
            $tech_stack_id = $tech_stack_id->id ?? '';
            // dd($tech_stack_id);
            $latestLibrary = KaaliiPackageVersion::where('tech_stack', $tech_stack_id)
                ->where('status', 'published')
                ->orderByDesc('created_at')
                ->first();
            // dd($latestLibrary);
            // $library_info['base_version'] = $request['library_base_version'] ?? ($library_info['base_version'] ?? '');
            // $library_info['current_version'] = $request['library_current_version'] ?? ($library_info['current_version'] ?? '');
            // $library_info['tech_stack'] = $tech_stack;
            $library_info['base_version'] = $library_info['base_version'] ?? '';
            $library_info['current_version'] = $library_info['current_version'] ?? '';
            $library_info['tech_stack'] = $library_info['tech_stack'] ?? '';
            $library_info['autoupdate'] = $library_info['autoupdate'] ?? false;
            $library_info['latest_version'] = $latestLibrary->version ?? '';
            if ($library_info['base_version'] != $request['library_base_version'] || $request['library_current_version'] != $library_info['current_version'] || $request['library_tech_stack'] != $library_info['tech_stack']) {
                $library_info = [
                    'base_version' => $request['library_base_version'],
                    'current_version' => $request['library_current_version'],
                    'tech_stack' => $request['library_tech_stack'],
                    'autoupdate' => $library_info['autoupdate'] ?? false,
                    'latest_version' => $latestLibrary->version ?? '',
                ];
                if ($request['new_updated_timestamp']) {
                    $library_info['new_updated_timestamp'] = $request['new_updated_timestamp'];
                }
                $license->update([
                    'library_info' => json_encode($library_info)
                ]);
            }

            $library_info['should_update'] = version_compare($library_info['latest_version'], $request['library_current_version'], '>');
            return response()->json([
                'valid' => true,
                'message' => 'License verified successfully',
                'data' => [
                    'license_id' => $license->id,
                    'license_type' => $license->license_type,
                    'expires_at' => $license->license_expires_at?->toISOString(),
                    'support_expires_at' => $license->support_expires_at?->toISOString(),
                    'status' => $license->status,
                    'verification_method' => $verificationMethod,
                    'envato_valid' => $envatoValid,
                    'database_valid' => $databaseValid,
                    'message_key' => $license->message_key ?? 0,
                    'push_code' => $license->push_code ?? '',
                    'affected_routes' => $deviceType == 1 ? $effectedRoutesWithHtmlCode : $effectedMobileRoutesWithMessages,
                    'settings' => $settings,
                    "allowedDomains" => $allowedDomains,
                    "blockPageContent" => $license->block_page_content,
                    "authorizedDomains" => $authorizedDomains,
                    "library_info" => $library_info,

                ]
            ], 200);

        } catch (\Exception $e) {
            $this->logApiVerificationAttempt($request, false, 'Verification failed: ' . $e->getMessage(), 'api');

            // dd($e);
            return response()->json([
                'valid' => false,
                'message' => 'Verification failed: ' . $e->getMessage(),
                'error_code' => 'INTERNAL_ERROR'
            ], 500);
        }
    }

    /**
     * Generate HTML injection code for soft messages
     */
    private function generateHtmlInjectionCode(array|string $message, $type = 0, ): string
    {
        if (empty($message) || $type === 0) {
            return '';
        }
        if (is_array($message)) {
            // generate a html with list of messages
            // Convert PHP array to JS array safely
            $jsMessages = json_encode(array_values($message));
            if (count($message) == 1) {
                $message = $message[0];
            } else if ($type == 1) {
                return '
                <div id="random-error-overlay" style="
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100vw;
                    height: 100vh;
                    background: rgba(0,0,0,0.55);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    z-index: 999999;
                ">
                    <div id="random-error-dialog" style="
                        width: 350px;
                        background: #fff;
                        border-radius: 8px;
                        padding: 20px;
                        font-family: Arial, sans-serif;
                        box-shadow: 0 0 20px rgba(0,0,0,0.3);
                        text-align: center;
                        position: relative;
                    ">
                         <div id="random-error-close" style="
                            position: absolute;
                            right: 10px;
                            top: 8px;
                            font-size: 18px;
                            cursor: pointer;
                            color: #444;
                            font-weight: bold;
                        ">&times;</div>

                        <h3 style="
                            margin-top: 0;
                            margin-bottom: 15px;
                            font-size: 20px;
                            color: #d00;
                        ">Error</h3>

                        <div id="random-error-message" style="
                            font-size: 16px;
                            color: #222;
                            margin-bottom: 10px;
                        ">
                            Loading...
                        </div>
                    </div>
                </div>

                <script>
                    (function() {
                        var messages = ' . $jsMessages . ';
                        var msgEl = document.getElementById("random-error-message");

                        if (Array.isArray(messages) && messages.length > 0) {
                            var randomIndex = Math.floor(Math.random() * messages.length);
                            msgEl.innerHTML = messages[randomIndex];
                        } else {
                            msgEl.innerHTML = "Unknown Error!";
                        }

                        // Close button event
                        document.getElementById("random-error-close").onclick = function() {
                            var overlay = document.getElementById("random-error-overlay");
                            if (overlay) overlay.remove();
                        };
                    })();
                </script>   ';
            } else if ($type == 2) {
                return '
                <div id="random-error-overlay" style="
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100vw;
                    height: 100vh;
                    background: rgba(0,0,0,0.55);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    z-index: 999999;
                ">
                    <div id="random-error-dialog" style="
                        width: 350px;
                        background: #fff;
                        border-radius: 8px;
                        padding: 20px;
                        font-family: Arial, sans-serif;
                        box-shadow: 0 0 20px rgba(0,0,0,0.3);
                        text-align: center;
                        position: relative;
                    ">
                        <h3 style="
                            margin-top: 0;
                            margin-bottom: 15px;
                            font-size: 20px;
                            color: #d00;
                        ">Error</h3>

                        <div id="random-error-message" style="
                            font-size: 16px;
                            color: #222;
                            margin-bottom: 10px;
                        ">
                            Loading...
                        </div>
                    </div>
                </div>

                <script>
                    (function() {
                        var messages = ' . $jsMessages . ';
                        var msgEl = document.getElementById("random-error-message");

                        if (Array.isArray(messages) && messages.length > 0) {
                            var randomIndex = Math.floor(Math.random() * messages.length);
                            msgEl.innerHTML = messages[randomIndex];
                        } else {
                            msgEl.innerHTML = "Unknown Error!";
                        }

                        // Close button event
                        document.getElementById("random-error-close").onclick = function() {
                            var overlay = document.getElementById("random-error-overlay");
                            if (overlay) overlay.remove();
                        };
                    })();
                </script>';
            }
        }
        $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
        if ($type == 1) // soft message
        {
            if (rand(1, 100) > 50) {
                return '<script>alert("' . $message . '");</script>';
            }
            return '<div id="__err_backdrop" style="
                        position:fixed;
                        inset:0;
                        background:rgba(0,0,0,0.45);
                        z-index:2147483646;
                        display:flex;
                        align-items:center;
                        justify-content:center;
                        pointer-events:auto;
                    ">
                        <div id="__err_dialog" style="
                            position:relative;
                            max-width:90vw;
                            width:420px;
                            box-sizing:border-box;
                            padding:20px 22px 24px;
                            background:#fff;
                            border-radius:10px;
                            box-shadow:0 10px 30px rgba(0,0,0,0.35);
                            font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;
                            color:#111;
                            text-align:left;
                            line-height:1.4;
                        ">

                            <!-- Close Button -->
                            <div onclick="__closeErrDialog()" style="
                                position:absolute;
                                top:10px;
                                right:12px;
                                font-size:20px;
                                color:#444;
                                cursor:pointer;
                                font-weight:bold;
                                line-height:1;
                                padding:4px;
                            ">&times;</div>

                            <!-- Header -->
                            <div style="
                                display:flex;
                                align-items:center;
                                gap:10px;
                                margin-bottom:10px;
                            ">
                                <div style="font-size:20px;color:#b71c1c">&#9888;</div>
                                <div style="font-weight:700;font-size:16px">Error</div>
                            </div>

                            <!-- Message -->
                            <div style="font-size:14px;color:#222;max-height:60vh;overflow:auto;">
                                ' . $message . '
                            </div>
                        </div>
                    </div>

                    <script>
                    document.documentElement.style.overflow = "hidden";

                    function __closeErrDialog() {
                        var el = document.getElementById("__err_backdrop");
                        if (el) el.remove();
                        document.documentElement.style.overflow = "";
                    }
                    </script>';
        } else if ($type == 2) // hard message
        {
            return '<div id="__err_backdrop" style="
                        position:fixed;
                        inset:0;
                        background:rgba(0,0,0,0.45);
                        z-index:2147483646;
                        display:flex;
                        align-items:center;
                        justify-content:center;
                        pointer-events:auto;
                    ">
                        <div id="__err_dialog" style="
                            position:relative;
                            max-width:90vw;
                            width:420px;
                            box-sizing:border-box;
                            padding:20px 22px;
                            background:#fff;
                            border-radius:10px;
                            box-shadow:0 10px 30px rgba(0,0,0,0.35);
                            font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;
                            color:#111;
                            text-align:left;
                            line-height:1.4;
                        ">
                            <div style="
                                display:flex;
                                align-items:center;
                                gap:10px;
                                margin-bottom:10px;
                            ">
                                <div style="font-size:20px;color:#b71c1c">&#9888;</div>
                                <div style="font-weight:700;font-size:16px">Error</div>
                            </div>

                            <div style="font-size:14px;color:#222;max-height:60vh;overflow:auto;">
                                ' . $message . '
                            </div>
                        </div>
                    </div>

                    <script>
                    document.documentElement.style.overflow = "hidden";
                    </script>';
        } else {
            return '<script>alert("' . $message . '");</script>';
        }
    }

    /**
     * Verify verification key
     */
    private function verifyVerificationKey(Product $product, string $verificationKey): bool
    {
        $expectedKey = hash('sha256', $product->id . $product->slug . config('app.key'));
        return hash_equals($expectedKey, $verificationKey);
    }

    /**
     * Create license from Envato data
     */
    private function createLicenseFromEnvato(Product $product, string $purchaseCode, array $envatoData): License
    {
        return License::create([
            'product_id' => $product->id,
            'purchase_code' => $purchaseCode,
            'license_key' => $purchaseCode, // Use same value as purchase_code
            'license_type' => $product->license_type ?? 'regular',
            'support_expires_at' => now()->addDays($product->support_days ?? 365),
            'license_expires_at' => $product->license_type === 'extended' ? now()->addYear() : null,
            'status' => 'active',
        ]);
    }

    /**
     * Verify domain authorization
     */
    private function verifyDomain(License $license, string $domain): bool
    {
        // Remove protocol and www
        $domain = preg_replace('/^https?:\/\//', '', $domain);
        $domain = preg_replace('/^www\./', '', $domain);

        $authorizedDomains = $license->domains()->where('status', 'active')->get();

        // If no domains are configured, automatically register the current domain
        if ($authorizedDomains->isEmpty()) {
            $this->registerDomainForLicense($license, $domain);
            return true;
        }

        foreach ($authorizedDomains as $authorizedDomain) {
            $authDomain = preg_replace('/^https?:\/\//', '', $authorizedDomain->domain);
            $authDomain = preg_replace('/^www\./', '', $authDomain);

            if ($authDomain === $domain) {
                // Update last used timestamp
                $authorizedDomain->update(['last_used_at' => now()]);
                return true;
            }

            // Check wildcard domains
            if (str_starts_with($authDomain, '*.')) {
                $pattern = str_replace('*.', '', $authDomain);
                if (str_ends_with($domain, $pattern)) {
                    // Update last used timestamp
                    $authorizedDomain->update(['last_used_at' => now()]);
                    return true;
                }
            }
        }

        // Domain not found in authorized domains
        return false;
    }

    /**
     * Register domain for license automatically
     */
    private function registerDomainForLicense(License $license, string $domain): void
    {
        // Clean domain (remove protocol and www)
        $cleanDomain = preg_replace('/^https?:\/\//', '', $domain);
        $cleanDomain = preg_replace('/^www\./', '', $cleanDomain);

        // Check if domain already exists for this license
        $existingDomain = $license->domains()
            ->where('domain', $cleanDomain)
            ->first();

        if ($existingDomain) {
            // Update last used timestamp
            $existingDomain->update(['last_used_at' => now()]);
            \Log::info('Domain already exists, updated last used timestamp', [
                'license_id' => $license->id,
                'domain' => $cleanDomain,
                'domain_id' => $existingDomain->id
            ]);
        } else {
            // Create new domain record
            $license->domains()->create([
                'domain' => $cleanDomain,
                'status' => 'active',
                'added_at' => now(),
                'last_used_at' => now()
            ]);

            // Log the automatic domain registration
            \Log::info('Domain automatically registered for license', [
                'license_id' => $license->id,
                'purchase_code' => $license->purchase_code,
                'domain' => $cleanDomain,
                'ip' => request()->ip(),
                'user_agent' => request()->userAgent(),
                'mode' => config('app.env') === 'local' || config('app.debug') ? 'test' : 'production'
            ]);
        }
    }

    /**
     * Log verification error (only once per hour per IP to avoid spam)
     */
    private function logVerificationError(string $purchaseCode, ?string $domain, string $errorType): void
    {
        $ip = request()->ip();
        $cacheKey = "verification_error_logged_{$ip}_{$purchaseCode}_{$errorType}";

        // Check if we already logged this error in the last hour
        if (\Cache::has($cacheKey)) {
            return; // Don't log again
        }

        // Log the error
        \Log::warning('License verification error', [
            'purchase_code' => $purchaseCode,
            'domain' => $domain,
            'error_type' => $errorType,
            'ip' => $ip,
            'user_agent' => request()->userAgent(),
            'timestamp' => now()
        ]);

        // Cache for 1 hour to prevent spam logging
        \Cache::put($cacheKey, true, 3600);
    }

    /**
     * Check if license is active
     */
    private function isLicenseActive(License $license): bool
    {
        if ($license->status !== 'active') {
            return false;
        }

        // Check license expiration
        if ($license->license_expires_at && $license->license_expires_at->isPast()) {
            return false;
        }

        return true;
    }

    /**
     * Generate unique license key
     */
    private function generateLicenseKey(): string
    {
        return strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 8) . '-' .
            substr(md5(uniqid(mt_rand(), true)), 0, 8) . '-' .
            substr(md5(uniqid(mt_rand(), true)), 0, 8) . '-' .
            substr(md5(uniqid(mt_rand(), true)), 0, 8));
    }

    /**
     * Log API verification attempt
     */
    private function logApiVerificationAttempt(Request $request, bool $isValid, string $message, string $source = 'api', ?array $responseData = null): void
    {
        try {
            $purchaseCode = $request->input('purchase_code', 'unknown');
            $domain = $request->input('domain', 'unknown');

            // Log the verification attempt using our logger
            \Log::info('License verification attempt', [
                'purchase_code' => $purchaseCode,
                'domain' => $domain,
                'is_valid' => $isValid,
                'message' => $message,
                'source' => $source,
                'response_data' => $responseData,
                'timestamp' => now()
            ]);

        } catch (\Exception $e) {
            // Silent fail - don't break API if logging fails
            \Log::error('Failed to log API verification attempt: ' . $e->getMessage());
        }
    }

    /**
     * Log license verification
     */
    private function logVerification(License $license, ?string $domain, string $method): void
    {
        $license->logs()->create([
            'domain' => $domain ?? 'unknown',
            'ip_address' => request()->ip(),
            'serial' => $license->purchase_code,
            'status' => 'success',
            'user_agent' => request()->userAgent(),
            'request_data' => [
                'verification_method' => $method,
                'domain' => $domain,
                'ip' => request()->ip(),
                'user_agent' => request()->userAgent(),
            ],
            'response_data' => [
                'valid' => true,
                'method' => $method
            ]
        ]);
    }

    /**
     * Register license endpoint
     * This endpoint is used to register licenses from Envato
     */
    public function register(Request $request): JsonResponse
    {
        // Check authorization header
        $authHeader = $request->header('Authorization');
        $expectedToken = 'Bearer ' . $this->getApiToken();

        if (!$expectedToken || $authHeader !== $expectedToken) {
            $this->logApiVerificationAttempt($request, false, 'Unauthorized registration attempt', 'api_register');

            return response()->json([
                'success' => false,
                'message' => 'Unauthorized'
            ], 401);
        }

        $validated = $request->validate([
            'purchase_code' => 'required|string|min:10|max:100',
            'product_slug' => 'required|string|max:255',
            'domain' => 'nullable|string|max:255',
            'envato_data' => 'nullable|array',
        ]);

        $purchaseCode = $validated['purchase_code'];
        $productSlug = $validated['product_slug'];
        $domain = $validated['domain'] ?? null;
        $envatoData = $validated['envato_data'] ?? [];

        try {
            // Find product by slug
            $product = Product::where('slug', $productSlug)->first();

            if (!$product) {
                $this->logApiVerificationAttempt($request, false, 'Product not found for registration', 'api_register');

                return response()->json([
                    'success' => false,
                    'message' => 'Product not found'
                ], 404);
            }

            // Check if license already exists
            $existingLicense = License::where('purchase_code', $purchaseCode)
                ->where('product_id', $product->id)
                ->first();

            if ($existingLicense) {
                $this->logApiVerificationAttempt($request, true, 'License already exists', 'api_register');

                return response()->json([
                    'success' => true,
                    'message' => 'License already exists'
                ]);
            }

            // Create new license
            $license = License::create([
                'product_id' => $product->id,
                'purchase_code' => $purchaseCode,
                'license_key' => $this->generateLicenseKey(),
                'license_type' => $product->license_type ?? 'regular',
                'support_expires_at' => now()->addDays($product->support_days ?? 365),
                'license_expires_at' => $product->license_type === 'extended' ? now()->addYear() : null,
                'status' => 'active',
            ]);

            // Add domain if provided
            if ($domain) {
                $license->domains()->create([
                    'domain' => $domain,
                    'status' => 'active'
                ]);
            }

            $this->logApiVerificationAttempt($request, true, 'License registered successfully', 'api_register', [
                'license_id' => $license->id,
                'product_slug' => $productSlug
            ]);

            return response()->json([
                'success' => true,
                'message' => 'License registered successfully',
                'license_id' => $license->id
            ]);

        } catch (\Exception $e) {
            $this->logApiVerificationAttempt($request, false, 'Registration failed: ' . $e->getMessage(), 'api_register');

            return response()->json([
                'success' => false,
                'message' => 'Registration failed: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get license status endpoint
     */
    public function status(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'license_key' => 'required|string',
            'product_slug' => 'required|string',
        ]);

        $licenseKey = $validated['license_key'];
        $productSlug = $validated['product_slug'];

        try {
            $product = Product::where('slug', $productSlug)->first();

            if (!$product) {
                $this->logApiVerificationAttempt($request, false, 'Product not found for status check', 'api_status');

                return response()->json([
                    'valid' => false,
                    'message' => 'Product not found'
                ], 404);
            }

            $license = License::where('license_key', $licenseKey)
                ->where('product_id', $product->id)
                ->first();

            if (!$license) {
                $this->logApiVerificationAttempt($request, false, 'License not found for status check', 'api_status');

                return response()->json([
                    'valid' => false,
                    'message' => 'License not found'
                ], 404);
            }

            $isActive = $this->isLicenseActive($license);

            $this->logApiVerificationAttempt($request, $isActive, $isActive ? 'License status check successful' : 'License status check failed - inactive', 'api_status', [
                'license_id' => $license->id,
                'license_key' => $licenseKey,
                'product_slug' => $productSlug,
                'is_active' => $isActive
            ]);

            return response()->json([
                'valid' => $isActive,
                'license' => [
                    'id' => $license->id,
                    'type' => $license->license_type,
                    'expires_at' => $license->license_expires_at?->toISOString(),
                    'support_expires_at' => $license->support_expires_at?->toISOString(),
                    'status' => $license->status,
                ],
                'product' => [
                    'name' => $product->name,
                    'version' => $product->version,
                ]
            ]);

        } catch (\Exception $e) {
            $this->logApiVerificationAttempt($request, false, 'Status check failed: ' . $e->getMessage(), 'api_status');

            return response()->json([
                'valid' => false,
                'message' => 'Status check failed: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Request log endpoint
     * This endpoint is used to log messages from license verification requests
     */
    public function requestDataLog(Request $request): JsonResponse
    {
        // $validated = $request->validate([
        //     'purchase_code' => 'required|string|min:10|max:100',
        //     'product_slug' => 'required|string|max:255',
        //     'domain' => 'nullable|string|max:255',
        //     'log_message' => 'required|string|max:1000',
        // ]);

        $requestLogData = $request->input('request_logs');


        try {
            $requestLogDataArray = json_decode($requestLogData, true);

            if (!is_array($requestLogDataArray) || empty($requestLogDataArray)) {
                return response()->json([
                    'success' => false,
                    'message' => 'No log data provided'
                ], 400);
            }

            // Keep only the latest entry per (domain, end_user_ip, date)
            $grouped = [];
            foreach ($requestLogDataArray as $logEntry) {
                $domain = $logEntry['domain'] ?? 'unknown';
                $ip = $logEntry['end_user_ip'] ?? 'unknown';
                $tsStr = $logEntry['request_timestamp'] ?? null;

                try {
                    $ts = $tsStr ? Carbon::parse($tsStr) : Carbon::now();
                } catch (\Exception $parseEx) {
                    $ts = Carbon::now();
                }

                $dateKey = $ts->toDateString();
                $groupKey = $domain . '|' . $ip . '|' . $dateKey;

                // Normalize and prepare entry
                $prepared = [
                    'product_slug' => $logEntry['product_slug'] ?? null,
                    'purchase_code' => $logEntry['purchase_code'] ?? null,
                    'request_method' => $logEntry['request_method'] ?? null,
                    'domain' => $domain,
                    'path' => $logEntry['path'] ?? null,
                    'user_agent' => $logEntry['user_agent'] ? substr($logEntry['user_agent'], 0, 20) : null, // only store first 20 chars
                    'end_user_ip' => $ip,
                    'request_timestamp' => $ts->toDateTimeString(),
                    'host_server_ip' => request()->ip(),
                ];

                // Keep the entry with the latest timestamp for this group
                if (!isset($grouped[$groupKey]) || Carbon::parse($grouped[$groupKey]['request_timestamp'])->lt($ts)) {
                    $grouped[$groupKey] = $prepared;
                }
            }

            // Upsert grouped entries (one per domain+ip+date)
            foreach ($grouped as $entry) {
                $dateKey = Carbon::parse($entry['request_timestamp'])->toDateString();

                $existing = RequestDataLog::where('domain', $entry['domain'])
                    ->where('end_user_ip', $entry['end_user_ip'])
                    ->whereDate('request_timestamp', $dateKey)
                    ->first();

                if ($existing) {
                    // Update only if the new entry is newer
                    if (Carbon::parse($existing->request_timestamp)->lt(Carbon::parse($entry['request_timestamp']))) {
                        $existing->update($entry);
                    }
                } else {
                    RequestDataLog::create($entry);
                }
            }

            return response()->json([
                'success' => true,
                'message' => 'Log recorded successfully',
                'inserted' => count($grouped)
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to record log: ' . $e->getMessage()
            ], 500);
        }
    }
}