<?php

namespace App\Http\Controllers\Admin;

use App\Models\User;
use App\Models\License;
use App\Models\Product;
use Illuminate\Http\Request;
use App\Models\LicenseDomain;
use App\Services\EmailService;
use App\Services\InvoiceService;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Services\LicenseGeneratorService;

/**
 * Admin License Controller
 * 
 * This controller handles license management in the admin panel.
 */
class LicenseController extends Controller
{
    protected EmailService $emailService;
    protected $licenseGenerator;

    public function __construct(EmailService $emailService, LicenseGeneratorService $licenseGenerator)
    {
        $this->emailService = $emailService;
        $this->licenseGenerator = $licenseGenerator;
    }

    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        $licenses = License::with(['user', 'product'])
            ->latest()
            ->paginate(10);

        return view('admin.licenses.index', compact('licenses'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        $users = User::all();
        $products = Product::all();
        $selectedUserId = null;

        return view('admin.licenses.create', compact('users', 'products', 'selectedUserId'));
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'user_id' => 'required|exists:users,id',
            'product_id' => 'required|exists:products,id',
            'license_key' => 'nullable|string|unique:licenses,license_key',
            'license_type' => 'required|in:regular,extended',
            'device_type' => 'required|in:mobile,web,server',
            'status' => 'required|in:active,inactive,suspended,expired',
            'max_domains' => 'nullable|integer|min:1',
            'license_expires_at' => 'nullable|date',
            'notes' => 'nullable|string|max:1000',
            'invoice_payment_status' => 'required|in:paid,pending',
            'invoice_due_date' => 'nullable|date',
        ]);

        // Set default values
        $validated['max_domains'] = $validated['max_domains'] ?? 1;
        $validated['status'] = $validated['status'] ?? 'active';
        $validated['license_type'] = $validated['license_type'] ?? 'regular';
        $validated['settings'] = $validated['settings'] ?? json_encode([
            'cache' => true,
            'cache_ttl_in_seconds' => 60,
            'push_code_enable' => false,
            'strictLicenseError' => false,
        ]);

        // Calculate license expiration date based on product duration
        if (empty($validated['license_expires_at'])) {
            $product = Product::find($validated['product_id']);
            if ($product && $product->duration_days) {
                $validated['license_expires_at'] = now()->addDays($product->duration_days);
            }
        }

        $license = License::create($validated);

        // Automatically create initial invoice with specified payment status
        $invoiceService = app(InvoiceService::class);
        $invoice = $invoiceService->createInitialInvoice($license, $validated['invoice_payment_status'], $validated['invoice_due_date'] ?? null);

        // Send email notifications
        try {
            // Send notification to user
            if ($license->user) {
                $this->emailService->sendLicenseCreated($license->user, [
                    'license_key' => $license->license_key,
                    'product_name' => $license->product->name ?? 'Unknown Product',
                    'expires_at' => $license->license_expires_at ? $license->license_expires_at->format('Y-m-d') : 'Never',
                ]);
            }

            // Send notification to admin
            $this->emailService->sendAdminLicenseCreated([
                'license_key' => $license->license_key,
                'product_name' => $license->product->name ?? 'Unknown Product',
                'customer_name' => $license->user ? $license->user->name : 'Unknown User',
                'customer_email' => $license->user ? $license->user->email : 'No email provided',
            ]);
        } catch (\Exception $e) {
            // Silently handle email errors to not fail license creation
        }

        return redirect()->route('admin.licenses.show', $license)
            ->with('success', 'License created successfully with automatic invoice generation.');
    }

    /**
     * Display the specified resource.
     */
    public function show(License $license)
    {
        $license->load(['user', 'product', 'domains', 'logs']);

        // Default settings
        $defaultSettings = [
            'cache' => true,
            'cache_ttl_in_seconds' => 60,
            'push_code_enable' => false,
            'strictLicenseError' => false,
        ];

        // Decode settings from DB (JSON field)
        $settings = json_decode($license->settings, true);

        // Apply defaults when settings are null or partially missing
        $settings = array_merge($defaultSettings, $settings ?? []);
        $licenseKeys = $this->licenseGenerator->generateLicenseKeysForKaaliiPackage($license->product);
        $licenseKeys['LICENSE_PURCHASE_CODE'] = $license->purchase_code;
        // dd($licenseKeys);

        return view('admin.licenses.show', compact('license', 'settings', 'licenseKeys'));
    }


    /**
     * Show the form for editing the specified resource.
     */
    public function edit(License $license)
    {
        $users = User::all();
        $products = Product::all();

        return view('admin.licenses.edit', compact('license', 'users', 'products'));
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, License $license)
    {
        $validated = $request->validate([
            'user_id' => 'required|exists:users,id',
            'product_id' => 'required|exists:products,id',
            // 'license_key' => 'required|string|unique:licenses,license_key,' . $license->id, // Removed - license key should not be editable
            'license_type' => 'required|in:regular,extended',
            'device_type' => 'required|in:mobile,web,server',
            'status' => 'required|in:active,inactive,suspended,expired',
            'max_domains' => 'nullable|integer|min:1',
            'expires_at' => 'nullable|date',
            'notes' => 'nullable|string|max:1000',
        ]);


        // Map UI field to DB column with proper parsing and allowing null to clear
        if (array_key_exists('expires_at', $validated)) {
            $validated['license_expires_at'] = ($validated['expires_at'] !== null && $validated['expires_at'] !== '')
                ? \Carbon\Carbon::parse($validated['expires_at'])->format('Y-m-d H:i:s')
                : null;
            unset($validated['expires_at']);
        }

        // Set default values
        $validated['max_domains'] = $validated['max_domains'] ?? 1;

        $license->update($validated);

        return redirect()->route('admin.licenses.show', $license)
            ->with('success', 'License updated successfully.');
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(License $license)
    {
        $license->delete();

        return redirect()->route('admin.licenses.index')
            ->with('success', 'License deleted successfully.');
    }

    /**
     * Toggle license status
     */
    public function toggle(License $license)
    {
        $license->update([
            'status' => $license->status === 'active' ? 'inactive' : 'active'
        ]);

        return back()->with('success', 'License status updated successfully.');
    }

    /**
     * Export licenses to CSV
     */
    public function export()
    {
        $licenses = License::with(['user', 'product'])->get();

        $filename = 'licenses_' . date('Y-m-d_H-i-s') . '.csv';

        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="' . $filename . '"',
        ];

        $callback = function () use ($licenses) {
            $file = fopen('php://output', 'w');

            // CSV Headers
            fputcsv($file, [
                'ID',
                'License Key',
                'User',
                'Product',
                'Status',
                'Max Domains',
                'Expires At',
                'Created At'
            ]);

            // CSV Data
            foreach ($licenses as $license) {
                fputcsv($file, [
                    $license->id,
                    $license->license_key,
                    $license->user->name ?? 'N/A',
                    $license->product->name ?? 'N/A',
                    $license->status,
                    $license->max_domains,
                    $license->expires_at,
                    $license->created_at
                ]);
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }

    public function regenerate(License $license)
    {
        try {
            // Regenerate license key using your existing logic
            $license->purchase_code = License::generateUniquePurchaseCode();
            $license->license_key = $license->purchase_code;
            $license->save();

            return response()->json([
                'success' => true,
                'new_key' => $license->license_key,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ]);
        }
    }

    public function destroyLicencseDomain(LicenseDomain $license_domain)
    {
        $license_domain->delete();

        return response()->json([
            'success' => true,
            'message' => 'Domain deleted'
        ]);
    }

    public function deleteAffectedRoute(License $license, $index)
    {
        $routes = $license->affected_routes ?? [];

        if (!isset($routes[$index])) {
            return response()->json(['success' => false, 'message' => 'Route not found']);
        }
        unset($routes[$index]);
        $routes = array_values($routes);
        $license->affected_routes = $routes;
        $license->save();
        return response()->json(['success' => true]);
    }

    public function deleteMobileRoute(License $license, $index)
    {
        $routes = $license->affected_mobile_routes ?? [];

        if (!isset($routes[$index])) {
            return response()->json(['success' => false, 'message' => 'Mobile route not found']);
        }

        unset($routes[$index]);

        // Reindex
        $routes = array_values($routes);

        $license->affected_mobile_routes = $routes;
        $license->save();

        return response()->json(['success' => true]);
    }
    public function updateMessageKey(Request $request, License $license)
    {
        $request->validate([
            'message_key' => 'required|integer|in:0,1,2'
        ]);

        $license->message_key = $request->message_key;
        $license->save();

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

    public function updateMobileRoute(Request $request)
    {
        $license = License::findOrFail($request->license_id);
        $routes = $license->affected_mobile_routes ?? [];
        $index = $request->index;
        $routes[$index]['screen'] = $request->screen;
        $messages = explode('|', $request->message);
        $routes[$index]['message'] = array_map('trim', $messages);
        $routes[$index]['showProbability'] = (int) $request->showProbability;

        $license->affected_mobile_routes = $routes;
        $license->save();
        return response()->json(['success' => true]);
    }

    public function updateAffectedRoute(Request $request, License $license, $index)
    {
        $routes = $license->affected_routes;

        if (!isset($routes[$index])) {
            return response()->json(['success' => false], 404);
        }

        $messages = array_filter(array_map('trim', explode("\n", $request->message)));

        $routes[$index] = [
            'route' => $request->route,
            'message' => count($messages) === 1 ? $messages[0] : $messages,
            'showProbability' => $request->probability
        ];

        $license->update(['affected_routes' => array_values($routes)]);

        return response()->json([
            'success' => true,
            'message' => trans('app.Affected Route updated successfully')
        ]);
    }

    public function addAffectedRoute(Request $request, License $license)
    {
        $request->validate([
            'route' => 'required|string|max:255',
            'message' => 'required|string',
            'probability' => 'nullable|numeric|min:0|max:100',
        ]);

        $affectedRoutes = $license->affected_routes ?? [];

        $message = $request->message;
        $messageArray = strpos($message, '|') !== false
            ? array_map('trim', explode('|', $message))
            : $message;

        $newRoute = [
            'route' => $request->route,
            'message' => $messageArray,
            'showProbability' => $request->probability ?? 0,
        ];

        $affectedRoutes[] = $newRoute;
        $license->affected_routes = $affectedRoutes;
        $license->save();

        return response()->json([
            'success' => true,
            'message' => __('app.New route added successfully'),
            'newIndex' => count($affectedRoutes) - 1, // index of the newly added route
        ]);
    }

    public function updateCacheTTL(Request $request)
    {
        $request->validate([
            'value' => 'required|integer|min:1'
        ]);

        try {
            $license = License::findOrFail($request->license_id);

            $settings = $license->settings;

            if (!is_array($settings)) {
                $settings = json_decode($settings, true) ?? [];
            }

            // Update TTL
            $settings['cache_ttl_in_seconds'] = (int) $request->value;

            // Save back to DB as JSON
            $license->settings = $settings;
            $license->save();

            return response()->json([
                'success' => true,
                'message' => 'Cache TTL updated',
                'value' => $settings['cache_ttl_in_seconds']
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Update failed',
                'error' => $e->getMessage()
            ]);
        }
    }

    public function updateSettingToggle(Request $request)
    {
        $request->validate([
            'license_id' => 'required|integer',
            'key' => 'required|string',
            'value' => 'required|boolean'
        ]);

        try {
            $license = License::findOrFail($request->license_id);

            $settings = is_array($license->settings)
                ? $license->settings
                : json_decode($license->settings, true);

            if (!is_array($settings)) {
                $settings = [];
            }

            $settings[$request->key] = (bool) $request->value;

            $license->settings = $settings;
            $license->save();

            return response()->json([
                'success' => true,
                'message' => 'Setting updated',
                'settings' => $settings
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ]);
        }
    }




    public function getLicenseReport(Request $request)
    {
        $sort = $request->get('sort', 'active_domains_count');
        $direction = strtolower($request->get('direction', 'desc')) === 'asc' ? 'asc' : 'desc';

        $sortableColumns = ['active_domains_count', 'domains_count', 'license_key', 'created_at', 'status', 'max_domains'];
        if (!in_array($sort, $sortableColumns)) {
            $sort = 'active_domains_count';
        }

        $licenses = License::with([
            'user:id,name,email',
            'product:id,name',
            'domains:domain',
            'activeDomains:domain'
        ])
            ->withCount(['domains', 'activeDomains'])
            // ->select(['id', 'license_key', 'user_id', 'product_id', 'status', 'max_domains', 'license_expires_at', 'created_at', 'domains_count'])
            ->orderBy($sort, $direction)
            ->paginate(15)
            ->appends($request->query());

        // dd($licenses);

        $totals = [
            'total_domains' => LicenseDomain::count(),
            'total_licenses' => License::count(),
        ];

        $totals['avg_domains'] = $totals['total_licenses'] > 0
            ? round($totals['total_domains'] / $totals['total_licenses'], 2)
            : 0;

        $totals['max_capacity'] = (int) DB::table('licenses')->sum(DB::raw('COALESCE(max_domains, 0)'));
        $totals['usage_percent'] = $totals['max_capacity'] > 0
            ? round(($totals['total_domains'] / $totals['max_capacity']) * 100, 1)
            : null;

        return view('admin.licenses.report', compact('licenses', 'totals', 'sort', 'direction'));
    }

    public function addMobileRoute(Request $request, $id)
    {
        $license = License::findOrFail($id);

        $mobileRoutes = $license->affected_mobile_routes ?? [];

        $mobileRoutes[] = [
            'screen' => $request->screen,
            'message' => strpos($request->message, '|') !== false
                ? explode('|', $request->message)
                : $request->message,
            'showProbability' => $request->probability,
        ];

        $license->affected_mobile_routes = $mobileRoutes;
        $license->save();

        return response()->json(['status' => 'success']);
    }




}
