<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\AuditLog;
use App\Models\License;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class LicenseController extends Controller
{
    // Pricing map (hours => price per device in INR)
    private $pricing = [
        5    => 25,
        24   => 50,
        72   => 150,
        168  => 300,
        360  => 450,
        720  => 600,
        1440 => 1200,
    ];

    public function index(Request $request)
    {
        $user  = auth()->user();
        $query = License::with('creator')->latest();

        // Hide developer keys from UI display
        $query->where('key', 'not like', 'DEVx%');

        if ($user->isOwner()) {
            // Owner sees ALL keys on the server — no filter
        } elseif ($user->isAdmin()) {
            // Admin sees own keys + keys created by their direct resellers
            $resellerIds = User::where('referred_by', $user->id)
                ->where('role', 'reseller')
                ->pluck('id');
            $query->whereIn('created_by', $resellerIds->push($user->id));
        } else {
            // Reseller sees only their own keys
            $query->where('created_by', $user->id);
        }

        if ($request->search) {
            $query->where('key', 'like', "%{$request->search}%");
        }

        $perPage  = $request->get('per_page', 10);
        $licenses = $query->paginate($perPage);

        return response()->json(['success' => true, 'data' => $licenses]);
    }

    public function store(Request $request)
    {
        $request->validate([
            'game'           => 'required|string',
            'max_devices'    => 'required|integer|min:1',
            'keys_count'     => 'required|integer|min:1|max:100',
            'duration_hours' => 'required|integer',
            'custom_key'     => 'nullable|string|max:64|unique:licenses,key',
        ]);

        $user           = auth()->user();
        $pricePerDevice = $this->pricing[$request->duration_hours] ?? 50;
        $totalCost      = $pricePerDevice * $request->max_devices * $request->keys_count;

        // Check balance for all users (Owner, Admin, Reseller)
        if ($user->balance < $totalCost) {
            return response()->json(['success' => false, 'message' => 'Insufficient balance'], 402);
        }

        $generated = [];
        for ($i = 0; $i < $request->keys_count; $i++) {
            // Use custom key only for single-key generation by owner/admin
            if ($request->custom_key && $i === 0 && ($user->isOwner() || $user->isAdmin())) {
                $key = strtoupper(trim($request->custom_key));
            } else {
                $hours = (int) $request->duration_hours;
                if ($hours === 5) {
                    $prefix = '5H';
                } elseif ($hours === 24) {
                    $prefix = '1D';
                } elseif ($hours === 72) {
                    $prefix = '3D';
                } elseif ($hours === 168) {
                    $prefix = '7D';
                } elseif ($hours === 360) {
                    $prefix = '15D';
                } elseif ($hours === 720) {
                    $prefix = '30D';
                } elseif ($hours === 1440) {
                    $prefix = '60D';
                } else {
                    $prefix = $hours . 'H';
                }
                $key = $prefix . 'x' . strtolower($user->username) . 'xtx' . strtolower(\Illuminate\Support\Str::random(5));
            }
            License::create([
                'key'            => $key,
                'created_by'     => $user->id,
                'game'           => $request->game,
                'max_devices'    => $request->max_devices,
                'duration_hours' => $request->duration_hours,
                'expires_at'     => null, // Set to NULL initially so the key starts counting down ONLY on first activation/verify!
                'is_active'      => true,
            ]);
            $generated[] = $key;
        }

        // Deduct balance for all users (Owner, Admin, Reseller)
        $user->decrement('balance', $totalCost);
        // Refresh model to get the updated balance
        $user->refresh();

        AuditLog::record('GENERATE_KEYS', "Generated {$request->keys_count} keys. Cost: ₹{$totalCost}");

        return response()->json([
            'success'        => true,
            'keys'           => $generated,
            'total_cost'     => $totalCost,
            'keys_count'     => $request->keys_count,
            'game'           => $request->game,
            'admin_username' => $user->username,
            'duration_hours' => $request->duration_hours,
            'max_devices'    => $request->max_devices,
            'remaining_balance' => $user->balance,
        ]);
    }

    /**
     * Check if the authenticated user can manage (block/delete/reset) a license.
     * Owner → any key. Admin → own keys + direct resellers' keys. Reseller → own keys only.
     */
    private function canManage(License $license): bool
    {
        $user = auth()->user();

        if ($user->isOwner()) return true;

        if ($user->isAdmin()) {
            if ($license->created_by === $user->id) return true;
            $resellerIds = User::where('referred_by', $user->id)
                ->where('role', 'reseller')
                ->pluck('id');
            return $resellerIds->contains($license->created_by);
        }

        // Reseller can manage own keys only
        return $license->created_by === $user->id;
    }

    public function verify(Request $request)
    {
        // Support both web panel format (key/device_id) and C++ client format (user_key/serial)
        $key = $request->input('key') ?? $request->input('user_key');
        $deviceId = $request->input('device_id') ?? $request->input('serial');

        if (!$key) {
            return response()->json([
                'status' => false,
                'reason' => 'License key is required.'
            ], 400);
        }

        $license = License::where('key', $key)->first();

        if (!$license) {
            return response()->json([
                'status' => false,
                'reason' => 'Key not found'
            ], 404);
        }

        if ($license->is_blocked) {
            return response()->json([
                'status' => false,
                'reason' => 'Key is blocked'
            ], 403);
        }

        // Set expiration on first activation/verify
        if (is_null($license->expires_at)) {
            $license->expires_at = now()->addHours($license->duration_hours);
            $license->save();
        }

        if ($license->isExpired()) {
            return response()->json([
                'status' => false,
                'reason' => 'Key has expired'
            ], 403);
        }

        // Bind device ID if provided
        if ($deviceId) {
            $devices = $license->devices ?? [];
            if (!in_array($deviceId, $devices)) {
                if (count($devices) >= $license->max_devices) {
                    return response()->json([
                        'status' => false,
                        'reason' => 'DEVICE LIMIT REACHED, RESET IT',
                    ], 400);
                }
                $devices[] = $deviceId;
                $license->devices = $devices;
                $license->device_count = count($devices);
                $license->save();
            }
        }

        $modesSetting = \App\Models\Setting::where('key', 'app_modes')->first();
        $modes = $modesSetting ? $modesSetting->value : [
            'imgui_mode_enabled' => true,
            'auto_mode_enabled' => true,
        ];

        // Return a response structure that satisfies both the C++ client expectations and the web panel verify format.
        return response()->json([
            // Web panel support
            'success'      => true,
            'expires_at'   => $license->expires_at,
            'game'         => $license->game,
            'max_devices'  => $license->max_devices,
            'device_count' => $license->device_count,

            // C++ Client support (expects status = true, data.token, data.rng, data.EXP)
            'status'       => true,
            'data'         => [
                'token'      => md5("PUBG-" . $key . "-" . ($deviceId ?? '') . "-Vm8Lk7Uj2JmsjCPVPVjrLa7zgfx3uz9E"),
                'rng'        => time(),
                'EXP'        => $license->expires_at ? $license->expires_at->toDateTimeString() : 'NULL',
                'imgui_mode' => (bool) ($modes['imgui_mode_enabled'] ?? true),
                'auto_mode'  => (bool) ($modes['auto_mode_enabled'] ?? true),
            ]
        ]);
    }

    public function publicReset(Request $request)
    {
        $request->validate([
            'key' => 'required|string',
        ]);

        $license = License::where('key', $request->key)->first();

        if (!$license) {
            return response()->json([
                'success' => false,
                'message' => 'License key not found.'
            ], 404);
        }

        if ($license->is_blocked) {
            return response()->json([
                'success' => false,
                'message' => 'Key is blocked.'
            ], 403);
        }

        if ($license->isExpired()) {
            return response()->json([
                'success' => false,
                'message' => 'Key has expired.'
            ], 403);
        }

        $now = now();
        $lastReset = $license->last_reset_at;

        // Calculate limits within 24 hours
        if (!$lastReset || $lastReset->diffInHours($now) >= 24) {
            $remaining = 4;
        } else {
            $remaining = 4 - $license->device_reset_count;
        }

        if ($remaining <= 0) {
            return response()->json([
                'success' => false,
                'message' => 'No More Device left try after 24 hours Please, Thank You!'
            ], 429);
        }

        // Perform reset
        if (!$lastReset || $lastReset->diffInHours($now) >= 24) {
            $license->device_reset_count = 1;
        } else {
            $license->device_reset_count += 1;
        }

        $license->last_reset_at = $now;
        $license->devices = null;
        $license->device_count = 0;
        $license->save();

        $finalRemaining = 4 - $license->device_reset_count;

        if ($finalRemaining <= 0) {
            return response()->json([
                'success' => true,
                'message' => 'No More Device left try after 24 hours Please, Thank You!'
            ]);
        }

        return response()->json([
            'success' => true,
            'message' => "Device reset successfully! Limits remaining: {$finalRemaining}/4"
        ]);
    }

    public function block(Request $request, License $license)
    {
        if (!$this->canManage($license)) {
            return response()->json(['success' => false, 'message' => 'Forbidden'], 403);
        }
        $license->update(['is_blocked' => !$license->is_blocked]);
        AuditLog::record('TOGGLE_BLOCK_KEY', "Key {$license->key} block toggled to " . ($license->is_blocked ? 'blocked' : 'unblocked'));
        return response()->json(['success' => true, 'is_blocked' => $license->is_blocked]);
    }

    public function resetHwid(Request $request, License $license)
    {
        if (!$this->canManage($license)) {
            return response()->json(['success' => false, 'message' => 'Forbidden'], 403);
        }
        $license->update(['device_count' => 0, 'devices' => null]);
        AuditLog::record('RESET_HWID', "HWID reset for key {$license->key}");
        return response()->json(['success' => true, 'message' => 'HWID/device reset successfully']);
    }

    public function destroy(License $license)
    {
        if (!$this->canManage($license)) {
            return response()->json(['success' => false, 'message' => 'Forbidden'], 403);
        }
        $key = $license->key;
        $license->delete();
        AuditLog::record('DELETE_KEY', "Key {$key} deleted");
        return response()->json(['success' => true, 'message' => 'Key deleted']);
     }

     public function update(Request $request, License $license)
     {
         if (!$this->canManage($license)) {
             return response()->json(['success' => false, 'message' => 'Forbidden'], 403);
         }

         $request->validate([
             'key'         => 'required|string|max:64|unique:licenses,key,' . $license->id,
             'max_devices' => 'required|integer|min:1',
         ]);

         $oldKey = $license->key;
         $oldMax = $license->max_devices;

         $license->update([
             'key'         => trim($request->key),
             'max_devices' => $request->max_devices,
         ]);

         AuditLog::record('UPDATE_KEY', "Updated key {$oldKey} to {$license->key}, max devices from {$oldMax} to {$license->max_devices}");

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

    public function stats()
    {
        $user  = auth()->user();

        if ($user->isOwner()) {
            $query = License::query();
        } elseif ($user->isAdmin()) {
            $resellerIds = User::where('referred_by', $user->id)
                ->where('role', 'reseller')
                ->pluck('id')
                ->push($user->id);
            $query = License::whereIn('created_by', $resellerIds);
        } else {
            $query = License::where('created_by', $user->id);
        }

        return response()->json([
            'success' => true,
            'data'    => [
                'total'   => (clone $query)->count(),
                'active'  => (clone $query)->where('is_active', true)->where('is_blocked', false)->whereDate('expires_at', '>=', now())->count(),
                'expired' => (clone $query)->where('expires_at', '<', now())->count(),
                'unused'  => (clone $query)->where('device_count', 0)->count(),
                'blocked' => (clone $query)->where('is_blocked', true)->count(),
            ],
        ]);
    }
}
