<?php

namespace Licenzo\Services\Logging;

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

use Licenzo\Framework\Database\Model;
use Licenzo\Model\Subscription;
use Licenzo\Model\SubscriptionEvent as SubscriptionEventModel;
use Licenzo\Services\Logging\Concerns\CapturesContext;
use Licenzo\Services\Logging\Concerns\DetectsRelations;
use Licenzo\Services\Logging\Concerns\HandlesErrors;

/**
 * SubscriptionEvent Logger
 * 
 * Automatically logs subscription events with complete audit trail.
 * Minimal user input required - auto-populates all fields from context.
 * 
 * Usage:
 *   SubscriptionEvent::log($subscription, 'status_changed');
 *   SubscriptionEvent::log($subscription, 'payment_succeeded', $transaction);
 *   SubscriptionEvent::log($subscription, 'status_changed', null, ['changes' => [...]]);
 */
class SubscriptionEvent
{
    use CapturesContext, DetectsRelations, HandlesErrors;

    /**
     * Log a subscription event with minimal input
     *
     * @param Subscription $subscription The subscription model
     * @param string $eventType Event type constant (e.g., 'status_changed', 'trial_started')
     * @param Model|null $relatedModel Optional related model (transaction, webhook, license, schedule)
     * @param array $options Optional additional data
     * @return SubscriptionEventModel|null
     */
    public static function log(
        Subscription $subscription,
        string $eventType,
        ?Model $relatedModel = null,
        array $options = []
    ): ?SubscriptionEventModel {
        return static::safeExecute(function () use ($subscription, $eventType, $relatedModel, $options) {
            // Build complete event data
            $data = static::buildEventData($subscription, $eventType, $relatedModel, $options);

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

    /**
     * Build complete event data with auto-population
     *
     * @param Subscription $subscription
     * @param string $eventType
     * @param Model|null $relatedModel
     * @param array $options
     * @return array
     */
    protected static function buildEventData(
        Subscription $subscription,
        string $eventType,
        ?Model $relatedModel,
        array $options
    ): array {
        // Auto-load relationships for complete snapshot
        $subscription->load([
            'customer',
            'subscriptionProducts.product',
            'subscriptionProducts.variation',
            'licenses'
        ]);

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

        // Extract related model info
        $relatedInfo = static::extractRelatedInfo($relatedModel);

        return [
            // Core IDs
            'subscription_id' => $subscription->id,
            'customer_id' => $subscription->customer_id,

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

            // Polymorphic relationship
            'related_id' => $relatedInfo['id'],
            'related_type' => $relatedInfo['type'],

            // Status tracking
            'status' => $options['status'] ?? SubscriptionEventModel::STATUS_PROCESSED,

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

    /**
     * Build event data snapshot with complete audit trail
     *
     * @param Subscription $subscription
     * @param array $options
     * @return array
     */
    protected static function buildEventDataSnapshot(Subscription $subscription, array $options): array
    {
        return [
            // Subscription snapshot
            'subscription' => [
                'id' => $subscription->id,
                'uuid' => $subscription->uuid,
                'subscription_name' => $subscription->subscription_name,
                'status' => $subscription->status,
                'billing_cycle' => $subscription->billing_cycle,
                'recurring_amount' => $subscription->recurring_amount,
                'recurring_total' => $subscription->recurring_total,
                'next_billing_date' => $subscription->next_billing_date?->toDateTimeString(),
                'trial_ends_at' => $subscription->trial_ends_at?->toDateTimeString(),
                'expire_at' => $subscription->expire_at?->toDateTimeString(),
                'canceled_at' => $subscription->canceled_at?->toDateTimeString(),
                'billing_total_cycles' => $subscription->billing_total_cycles,
                'bill_count' => $subscription->bill_count,
                'total_paid' => $subscription->total_paid,
                'total_refunded' => $subscription->total_refunded,
                'failed_payment_count' => $subscription->failed_payment_count,
                'dunning_status' => $subscription->dunning_status,
            ],

            // Customer snapshot
            'customer' => [
                'id' => $subscription->customer->id,
                'email' => $subscription->customer->email,
                'first_name' => $subscription->customer->first_name,
                'last_name' => $subscription->customer->last_name,
                'user_id' => $subscription->customer->user_id,
            ],

            // Products snapshot
            'products' => $subscription->subscriptionProducts->map(fn($sp) => [
                'id' => $sp->id,
                'product_id' => $sp->product_id,
                'variation_id' => $sp->variation_id,
                'product_name' => $sp->product_name,
                'variation_name' => $sp->variation_name,
                'price' => $sp->price,
                'quantity' => $sp->quantity,
            ])->toArray(),

            // Licenses snapshot
            'licenses' => $subscription->licenses->map(fn($l) => [
                'id' => $l->id,
                'uuid' => $l->uuid,
                'license_key' => $l->license_key,
                'status' => $l->status,
                'activation_count' => $l->activation_count,
                'activation_limit' => $l->activation_limit,
                'expire_date' => $l->expire_date?->toDateTimeString(),
            ])->toArray(),

            // Changes tracking (for status_changed events)
            'changes' => $options['changes'] ?? [],

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

    /**
     * Extract related model information
     *
     * @param Model|null $relatedModel
     * @return array
     */
    protected static function extractRelatedInfo(?Model $relatedModel): array
    {
        if (!$relatedModel) {
            return [
                'id' => null,
                'type' => null,
            ];
        }

        return [
            'id' => $relatedModel->id,
            'type' => static::detectRelatedType($relatedModel),
        ];
    }
}

