<?php

namespace Licenzo\Http\Controller\Api\V1;

use Licenzo\Framework\Http\Request;
use Licenzo\Helper\LicenzoKey;
use Licenzo\Model\License;
use Licenzo\Model\Customer;
use Licenzo\Model\LicenseEvent;
use Licenzo\Model\Product;
use Licenzo\Model\ProductVariation;
use Licenzo\Model\LicenseProduct;
use Licenzo\Model\Subscription;
use Licenzo\Model\SubscriptionProduct;

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

class LicenseController
{
    /**
     * List licenses
     */
    public function index(Request $request)
    {
        try {
            $filter = $request->getSafe([
                'search' => 'sanitize_text_field',
                'status' => 'sanitize_text_field',
            ]);

            $query = License::query();
            $query->with(['customer', 'subscription', 'licenseProducts.product', 'licenseProducts.variation']);

            if (!empty($filter['search'])) {
                $search = $filter['search'];
                $query->where(function ($licenseQuery) use ($search) {
                    $licenseQuery->where('license_key', 'like', "%{$search}%")
                        ->orWhereHas('customer', function ($customerQuery) use ($search) {
                            $customerQuery->where('first_name', 'like', "%{$search}%")
                                ->orWhere('last_name', 'like', "%{$search}%")
                                ->orWhere('email', 'like', "%{$search}%");
                        })
                        ->orWhereHas('subscription', function ($subscriptionQuery) use ($search) {
                            $subscriptionQuery->where('subscription_name', 'like', "%{$search}%");
                        })
                        ->orWhereHas('licenseProducts', function ($licenseProductQuery) use ($search) {
                            $licenseProductQuery->where('product_name', 'like', "%{$search}%")
                                ->orWhere('variation_name', 'like', "%{$search}%");
                        });
                });
            }

            if (!empty($filter['status'])) {
                $query->where('status', $filter['status']);
            }

            $licenses = $query->orderBy('created_at', 'desc')->paginate();

            return [
                'success'  => true,
                'licenses' => $licenses,
                'filters'  => $filter,
            ];
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => __('Failed to fetch licenses.', 'licenzo'),
                'status'  => 500,
            ];
        }
    }

    /**
     * Create a new license
     */
    public function store(Request $request)
    {
        try {
            $data = $request->getSafe([
                'license_key'      => 'sanitize_text_field',
                'customer_id'      => 'absint',
                'subscription_id'  => 'absint',
                'product_id'       => 'absint',
                'variation_id'     => 'absint',
                'expire_date'      => 'date',
                'support_till'     => 'sanitize_text_field',
                'activation_limit' => 'absint',
                'status'           => 'sanitize_text_field',
            ]);

            if (empty($data['license_key']) || empty($data['customer_id']) || empty($data['product_id']) || empty($data['subscription_id'])) {
                return [
                    'success' => false,
                    'message' => __('License key, customer, subscription, and product are required.', 'licenzo'),
                ];
            }
            if (empty($data['variation_id'])) {
                return [
                    'success' => false,
                    'message' => __('Variation are required.', 'licenzo'),
                ];
            }

            // Validate subscription ownership and product mapping
            $subscription = Subscription::find($data['subscription_id']);
            if (!$subscription) {
                return [
                    'success' => false,
                    'message' => __('Subscription not found.', 'licenzo'),
                ];
            }

            if ((int) $subscription->customer_id !== (int) $data['customer_id']) {
                return [
                    'success' => false,
                    'message' => __('Subscription does not belong to the selected customer.', 'licenzo'),
                ];
            }

            $subscriptionProductExists = SubscriptionProduct::where('subscription_id', $data['subscription_id'])
                ->where('product_id', $data['product_id'])
                ->where('variation_id', $data['variation_id'])
                ->exists();

            if (!$subscriptionProductExists) {
                return [
                    'success' => false,
                    'message' => __('Selected product variation is not assigned to this subscription.', 'licenzo'),
                ];
            }

            if (
                License::where('subscription_id', $data['subscription_id'])
                    ->whereHas('licenseProducts', function ($query) use ($data) {
                        $query->where('product_id', $data['product_id'])
                            ->where('variation_id', $data['variation_id']);
                    })
                    ->exists()
            ) {
                return [
                    'success' => false,
                    'message' => __('License already exists for this subscription product.', 'licenzo'),
                ];
            }

            $product = Product::find($data['product_id']);
            if (!$product) {
                return [
                    'success' => false,
                    'message' => __('Product not found.', 'licenzo'),
                ];
            }

            $variation = null;
            $variationName = null;
            if (!empty($data['variation_id'])) {
                $variation = ProductVariation::find($data['variation_id']);
                if ($variation) {
                    $variationName = $variation->name;
                }
            }

            $license = License::create([
                'uuid'             => wp_generate_uuid4(),
                'license_key'      => $data['license_key'],
                'customer_id'      => $data['customer_id'],
                'subscription_id'  => $data['subscription_id'],
                'status'           => $data['status'] ?? 'active',
                'activation_limit' => $data['activation_limit'] ?? 0,
                'expire_date'      => empty($data['expire_date']) ? null : $data['expire_date'],
                'support_till'     => $data['support_till'] ?: null,
            ]);

            LicenseProduct::create([
                'license_id'       => $license->id,
                'product_id'       => $data['product_id'],
                'variation_id'     => $data['variation_id'] ?? null,
                'product_name'     => $product->name,
                'variation_name'   => $variationName,
                'started_at'       => gmdate('Y-m-d'),
                'expire_date'      => empty($data['expire_date']) ? null : $data['expire_date'],
                'activation_count' => 1,
            ]);

            return [
                'success' => true,
                'license' => $license,
            ];
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => (defined('WP_DEBUG') && WP_DEBUG) ? $e->getMessage() : __('An error occurred', 'licenzo'),
            ];
        }
    }


    /**
     * Show single license
     */
    public function show($id)
    {
        $license = License::with(['customer', 'licenseProducts.product', 'licenseProducts.variation', 'subscription'])
            ->find($id);

        if (!$license) {
            return [
                'success' => false,
                'message' => __('License not found.', 'licenzo'),
            ];
        }

        $license->setRelation(
            'activations',
            $license->activations()
                ->with(['product', 'variation'])
                ->orderBy('created_at', 'desc')
                ->limit(50)
                ->get()
        );

        $license->setRelation(
            'events',
            $license->events()
                ->orderBy('created_at', 'desc')
                ->limit(20)
                ->get()
        );

        if ($license->customer) {
            $license->customer->lifetime_value = $license->customer->lifetime_value;
        }

        return [
            'success' => true,
            'license' => $license,
        ];
    }

    public function update($id, Request $request)
    {
        $license = License::find($id);
        if (!$license) return ['success' => false, 'message' => __('License not found', 'licenzo')];

        $data = $request->getSafe([
            'activation_count' => 'absint',
            'activation_limit' => 'absint',
            'expire_date'      => 'sanitize_text_field',
            'support_till'     => 'sanitize_text_field',
            'status'           => 'sanitize_text_field',
        ]);


        $license->update($data);

        return ['success' => true, 'license' => $license];
    }

    public function destroy($id)
    {
        try {
            $license = License::find($id);

            if (!$license) {
                return [
                    'success' => false,
                    'message' => __('License not found.', 'licenzo'),
                    'status'  => 404,
                ];
            }

            if ($license->status === 'active') {
                return [
                    'success' => false,
                    'message' => __('Cannot delete an active license. Revoke or expire it first.', 'licenzo'),
                    'status'  => 422,
                ];
            }

            $license->activations()->delete();
            $license->licenseProducts()->delete();
            $license->events()->delete();
            $license->delete();

            return [
                'success' => true,
                'message' => __('License deleted successfully.', 'licenzo'),
            ];
        } catch (\Throwable $th) {
            return [
                'success' => false,
                'message' => (defined('WP_DEBUG') && WP_DEBUG) ? $th->getMessage() : __('An error occurred', 'licenzo'),
                'status'  => 500,
            ];
        }
    }

    public function updateLicenseProduct($license, $licenseProduct, Request $request)
    {
        $license = LicenseProduct::where('license_id', $license)->find($licenseProduct);
        if (!$license) {
            return ['success' => false, 'message' => __('Product not found', 'licenzo')];
        }

        $data = $request->getSafe([
            'started_at'       => 'sanitize_text_field',
            'expire_date'      => 'sanitize_text_field',
            'activation_count' => 'absint',
        ]);

        $license->update($data);

        return ['success' => true, 'license_product' => $license];
    }

    public function generateSubscriptionLicense(Request $request)
    {
        try {
            // Sanitize input
            $data = $request->getSafe([
                'license_key'      => 'sanitize_text_field',
                'subscriptionId'   => 'absint',
                'activation_limit' => 'absint',
                'subProductId'     => 'absint',
                'customerId'       => 'absint',
                'status'           => 'sanitize_text_field',
            ]);

            // Basic validation
            if (empty($data['license_key']) || empty($data['subscriptionId']) || empty($data['subProductId']) || empty($data['customerId'])) {
                return [
                    'success' => false,
                    'message' => __('License key, subscription, sub product, and customer are required.', 'licenzo'),
                ];
            }

            // Duplicate license key check
            if (License::where('license_key', $data['license_key'])->exists()) {
                return [
                    'success' => false,
                    'message' => __('License key already exists.', 'licenzo'),
                ];
            }

            // Fetch customer
            $customer = \Licenzo\Model\Customer::find($data['customerId']);
            if (!$customer) {
                return [
                    'success' => false,
                    'message' => __('Customer not found.', 'licenzo'),
                ];
            }

            // Fetch subscription
            $subscription = Subscription::find($data['subscriptionId']);
            if (!$subscription) {
                return [
                    'success' => false,
                    'message' => __('Subscription not found.', 'licenzo'),
                ];
            }

            if ((int) $subscription->customer_id !== (int) $data['customerId']) {
                return [
                    'success' => false,
                    'message' => __('Subscription does not belong to the selected customer.', 'licenzo'),
                ];
            }

            // Fetch subscription product
            $subscriptionProduct = SubscriptionProduct::find($data['subProductId']);
            if (!$subscriptionProduct) {
                return [
                    'success' => false,
                    'message' => __('Subscription product not found.', 'licenzo'),
                ];
            }

            if ((int) $subscriptionProduct->subscription_id !== (int) $subscription->id) {
                return [
                    'success' => false,
                    'message' => __('Subscription product does not belong to the selected subscription.', 'licenzo'),
                ];
            }

            // Check if this subscription product already has a license
            if (License::where('subscription_id', $data['subscriptionId'])
                ->whereHas('licenseProducts', function ($query) use ($subscriptionProduct) {
                    $query->where('product_id', $subscriptionProduct->product_id)
                        ->where('variation_id', $subscriptionProduct->variation_id);
                })->exists()
            ) {
                return [
                    'success' => false,
                    'message' => __('License already exists for this subscription product.', 'licenzo'),
                ];
            }

            // Fetch base product and variation
            $baseProduct = Product::find($subscriptionProduct->product_id);
            $baseVariation = ProductVariation::find($subscriptionProduct->variation_id);

            if (!$baseProduct || !$baseVariation) {
                return [
                    'success' => false,
                    'message' => __('Product or variation not found.', 'licenzo'),
                ];
            }


            // Create the license
            $license = License::create([
                'uuid'            => wp_generate_uuid4(),
                'license_key'     => $data['license_key'],
                'customer_id'     => $data['customerId'],
                'subscription_id' => $data['subscriptionId'],
                'status'          => $data['status'] ?? 'active',
                'expire_date'     => $subscription->expire_at
                    ? gmdate('Y-m-d', strtotime($subscription->expire_at))
                    : null,
                'support_till'    => $baseVariation->support_for
                    ? gmdate('Y-m-d', strtotime('+' . $baseVariation->support_for . ' ' . $baseVariation->support_for_unit))
                    : null,
            ]);

            // Attach product to the license
            $licenseProduct = LicenseProduct::create([
                'license_id'       => $license->id,
                'product_id'       => $baseProduct->id,
                'variation_id'     => $baseVariation->id,
                'product_name'     => $baseProduct->name,
                'variation_name'   => $baseVariation->name,
                'started_at'       => gmdate('Y-m-d'),
                'expire_date'     => $subscription->expire_at
                    ? gmdate('Y-m-d', strtotime($subscription->expire_at))
                    : null,
                'activation_count' => 0,
            ]);

            return [
                'success' => true,
                'license' => $license,
            ];
        } catch (\Throwable $th) {
            return [
                'success' => false,
                'message' => (defined('WP_DEBUG') && WP_DEBUG) ? $th->getMessage() : __('An error occurred', 'licenzo'),
            ];
        }
    }

    public function transferLicense($id, Request $request)
    {
        return [
            'success' => false,
            'message' => __('License transfer is coming soon.', 'licenzo'),
            'status'  => 403,
        ];
    }

    public function licenseGenerator()
    {
        $licenseKey = \Licenzo\Helper\LicenzoKey::generate();

        return [
            'success'     => true,
            'license_key' => $licenseKey,
        ];
    }
}
