<?php

namespace Licenzo\Services\Logging;

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

use Licenzo\Framework\Http\Request;
use Licenzo\Model\License;
use Licenzo\Model\LicenseActivation;
use Licenzo\Model\LicenseEvent as LicenseEventModel;
use Licenzo\Services\Logging\Concerns\CapturesContext;
use Licenzo\Services\Logging\Concerns\HandlesErrors;

/**
 * LicenseEvent Logger
 *
 * Automatically logs license events with complete audit trail.
 * Minimal user input required - auto-populates all fields from context.
 *
 * Usage:
 *   LicenseEvent::log($license, 'activated');
 *   LicenseEvent::log($license, 'activated', $activation);
 *   LicenseEvent::log($license, 'validated', $activation, $request);
 */
class LicenseEvent
{
    use CapturesContext, HandlesErrors;

    /**
     * Log a license event with minimal input
     *
     * @param License $license The license model
     * @param string $eventType Event type constant (e.g., 'activated', 'validated')
     * @param LicenseActivation|null $activation Optional activation model
     * @param Request|null $request Optional request object
     * @param array $options Optional additional data
     * @return LicenseEventModel|null
     */
    public static function log(
        License $license,
        string $eventType,
        ?LicenseActivation $activation = null,
        ?Request $request = null,
        array $options = []
    ): ?LicenseEventModel {
        return static::safeExecute(function () use ($license, $eventType, $activation, $request, $options) {
            // Build complete event data
            $data = static::buildEventData($license, $eventType, $activation, $request, $options);

            // Create and return the event
            return LicenseEventModel::create($data);
        }, 'LicenseEvent::log');
    }

    /**
     * Build complete event data with auto-population
     *
     * @param License $license
     * @param string $eventType
     * @param LicenseActivation|null $activation
     * @param Request|null $request
     * @param array $options
     * @return array
     */
    protected static function buildEventData(
        License $license,
        string $eventType,
        ?LicenseActivation $activation,
        ?Request $request,
        array $options
    ): array {
        // Auto-load relationships for complete snapshot
        $license->load(['customer', 'subscription', 'licenseProducts.product', 'licenseProducts.variation']);

        // Extract product/variation info
        $productInfo = static::extractProductInfo($license, $activation);

        // Build event data snapshot
        $eventData = static::buildEventDataSnapshot($license, $activation, $options);

        // Extract request context
        $requestContext = static::extractRequestContextData($activation, $request);

        return [
            // Core IDs
            'license_id' => $license->id,
            'product_id' => $productInfo['product_id'],
            'variation_id' => $productInfo['variation_id'],
            'activation_id' => $activation?->id,

            // Cached names for quick queries
            'product_name' => $productInfo['product_name'],
            'variation_name' => $productInfo['variation_name'],

            // Event details
            'event_type' => $eventType,
            'event_source' => $options['source'] ?? static::detectSource(),
            'event_data' => $eventData,

            // Request details
            'instance_identifier' => $requestContext['instance_identifier'],
            'ip_address' => $requestContext['ip_address'],
            'user_agent' => $requestContext['user_agent'],
            'request_hash' => $requestContext['request_hash'],

            // Response details
            'response_status' => $options['response_status'] ?? 'success',
            'response_message' => $options['response_message'] ?? null,
            'response_data' => $options['response_data'] ?? null,

            // Audit
            'triggered_by' => $options['triggered_by'] ?? static::getCurrentUserId(),
        ];
    }

    /**
     * Extract product and variation information
     *
     * @param License $license
     * @param LicenseActivation|null $activation
     * @return array
     */
    protected static function extractProductInfo(License $license, ?LicenseActivation $activation): array
    {
        // Priority 1: From activation
        if ($activation) {
            return [
                'product_id' => $activation->product_id,
                'variation_id' => $activation->variation_id,
                'product_name' => $activation->product_name,
                'variation_name' => $activation->variation_name,
            ];
        }

        // Priority 2: From first license product
        $firstProduct = $license->licenseProducts->first();
        if ($firstProduct) {
            return [
                'product_id' => $firstProduct->product_id,
                'variation_id' => $firstProduct->variation_id,
                'product_name' => $firstProduct->product_name,
                'variation_name' => $firstProduct->variation_name,
            ];
        }

        // Fallback: Empty values
        return [
            'product_id' => null,
            'variation_id' => null,
            'product_name' => '',
            'variation_name' => '',
        ];
    }

    /**
     * Build event data snapshot with complete audit trail
     *
     * @param License $license
     * @param LicenseActivation|null $activation
     * @param array $options
     * @return array
     */
    protected static function buildEventDataSnapshot(
        License $license,
        ?LicenseActivation $activation,
        array $options
    ): array {
        return [
            // License snapshot
            'license' => [
                'id' => $license->id,
                'uuid' => $license->uuid,
                'license_key' => $license->license_key,
                'status' => $license->status,
                'activation_count' => $license->activation_count,
                'activation_limit' => $license->activation_limit,
                'expire_date' => $license->expire_date ? gmdate('Y-m-d H:i:s', strtotime($license->expire_date)) : null,
                'support_till' => $license->support_till ? gmdate('Y-m-d H:i:s', strtotime($license->support_till)) : null,
                'subscription_id' => $license->subscription_id,
            ],

            // Customer snapshot
            'customer' => $license->customer ? [
                'id' => $license->customer->id,
                'email' => $license->customer->email,
                'first_name' => $license->customer->first_name,
                'last_name' => $license->customer->last_name,
                'user_id' => $license->customer->user_id,
            ] : null,

            // Subscription snapshot (if exists)
            'subscription' => $license->subscription ? [
                'id' => $license->subscription->id,
                'uuid' => $license->subscription->uuid,
                'status' => $license->subscription->status,
                'billing_cycle' => $license->subscription->billing_cycle,
                'next_billing_date' => $license->subscription->next_billing_date ? gmdate('Y-m-d H:i:s', strtotime($license->subscription->next_billing_date)) : null,
            ] : null,

            // Products snapshot
            'products' => $license->licenseProducts->map(fn($lp) => [
                'id' => $lp->id,
                'product_id' => $lp->product_id,
                'variation_id' => $lp->variation_id,
                'product_name' => $lp->product_name,
                'variation_name' => $lp->variation_name,
                'started_at' => $lp->started_at,
                'expire_date' => $lp->expire_date,
                'activation_count' => $lp->activation_count,
            ])->toArray(),

            // Activation snapshot (if provided)
            'activation' => $activation ? [
                'id' => $activation->id,
                'instance_identifier' => $activation->instance_identifier,
                'activation_hash' => $activation->activation_hash,
                'status' => $activation->status,
                'ip_address' => $activation->ip_address,
                'user_agent' => $activation->user_agent,
                'activated_at' => $activation->activated_at ? gmdate('Y-m-d H:i:s', strtotime($activation->activated_at)) : null,
                'last_validated_at' => $activation->last_validated_at ? gmdate('Y-m-d H:i:s', strtotime($activation->last_validated_at)) : null,
                'activation_method' => $activation->activation_method,
            ] : null,

            // Custom data from options
            'custom_data' => $options['data'] ?? [],
        ];
    }

    /**
     * Extract request context data
     *
     * @param LicenseActivation|null $activation
     * @param Request|null $request
     * @return array
     */
    protected static function extractRequestContextData(?LicenseActivation $activation, ?Request $request): array
    {
        return [
            'instance_identifier' => static::extractInstanceIdentifier($request)
                ?? $activation?->instance_identifier,
            'ip_address' => $request?->ip() ?? static::getClientIp(),
            'user_agent' => $request?->userAgent() ?? static::getUserAgent(),
            'request_hash' => static::extractRequestHash($request),
        ];
    }
}

