<?php
/**
 * Subscription Log class for MTC Subscription Plugin
 *
 * @author: Ashok Basnet <ashok.basnet@mtc.co.uk>
 * @since: 06/06/2025
 */

namespace MtcPharmacy\Subscriptions\Classes;

use Illuminate\Database\Eloquent\Model;
use Mtc\Modules\Members\Models\Member;

use Illuminate\Support\Facades\Log;


use Illuminate\Support\Facades\Request;
use Carbon\Carbon;

class SubscriptionLog extends Model
{
    const ACTION_CREATED = 'created';
    const ACTION_UPDATED = 'updated';
    const ACTION_STATUS_CHANGED = 'status_changed';
    const ACTION_ITEM_ADDED = 'item_added';
    const ACTION_ITEM_REMOVED = 'item_removed';
    const ACTION_ITEM_UPDATED = 'item_updated';
    const ACTION_ORDER_GENERATED = 'order_generated';
    const ACTION_PAYMENT_ATTEMPTED = 'payment_attempted';
    const ACTION_PAYMENT_SUCCEEDED = 'payment_succeeded';
    const ACTION_PAYMENT_FAILED = 'payment_failed';
    const ACTION_EMAIL_SENT = 'email_sent';
    const SOURCE_ADMIN = 'admin';
    const SOURCE_CUSTOMER = 'customer';
    const SOURCE_SYSTEM = 'system';
    const SOURCE_API = 'api';

    protected $table = 'subscription_logs';

    protected $fillable = [
        'subscription_id',
        'member_id',
        'admin_user_id',
        'action_type',
        'action_description',
        'old_values',
        'new_values',
        'metadata',
        'source',
        'ip_address',
        'user_agent',
    ];

    protected $casts = [
        'old_values' => 'array',
        'new_values' => 'array',
        'metadata' => 'array',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Relationships
     */
    public function subscription()
    {
        return $this->belongsTo(Subscription::class);
    }

    public function member()
    {
        return $this->belongsTo(Member::class);
    }

    /**
     * Scopes
     */
    public function scopeForSubscription($query, $subscriptionId)
    {
        return $query->where('subscription_id', $subscriptionId);
    }

    public function scopeByActionType($query, $actionType)
    {
        return $query->where('action_type', $actionType);
    }

    public function scopeBySource($query, $source)
    {
        return $query->where('source', $source);
    }

    public function scopeByMember($query, $memberId)
    {
        return $query->where('member_id', $memberId);
    }

    public function scopeDateRange($query, $startDate, $endDate)
    {
        return $query->whereBetween('created_at', [$startDate, $endDate]);
    }

    public function scopeRecent($query, $days = 30)
    {
        return $query->where('created_at', '>=', Carbon::now()->subDays($days));
    }

    /**
     * Static logging methods
     */
    public static function logAction(
        $subscriptionId,
        $actionType,
        $description,
        $oldValues = null,
        $newValues = null,
        $metadata = [],
        $source = self::SOURCE_SYSTEM
    ) {
        if (empty($actionType)) {
            return false;
        }

        if (empty($subscriptionId)) {
            return false;
        }

        if (empty($description)) {
            return false;
        }

        $logData = [
            'subscription_id' => $subscriptionId,
            'action_type' => $actionType,
            'action_description' => $description,
            'old_values' => $oldValues,
            'new_values' => $newValues,
            'metadata' => $metadata,
            'source' => $source,
        ];

        // Add member and admin user context
        if ($source === self::SOURCE_CUSTOMER) {
            if (isset($_SESSION['member_id'])) {
                $logData['member_id'] = $_SESSION['member_id'];
            }
        } elseif ($source === self::SOURCE_ADMIN) {
            if (isset($_SESSION['adminId'])) {
                $logData['admin_user_id'] = $_SESSION['adminId'];
            }
        }

        // Add request context
        if (Request::ip()) {
            $logData['ip_address'] = Request::ip();
        }
        if (Request::userAgent()) {
            $logData['user_agent'] = Request::userAgent();
        }

        $result = static::create($logData);
        return $result;
    }

    public static function logCreated(Subscription $subscription, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_CREATED,
            "Subscription created for member {$subscription->member_id}",
            null,
            $subscription->toArray(),
            $metadata,
            $source
        );
    }

    public static function logStatusChanged(Subscription $subscription, $oldStatus, $newStatus, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_STATUS_CHANGED,
            "Subscription status changed from '{$oldStatus}' to '{$newStatus}'",
            ['status' => $oldStatus],
            ['status' => $newStatus],
            $metadata,
            $source
        );
    }

    public static function logItemAdded(Subscription $subscription, SubscriptionItem $item, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_ITEM_ADDED,
            "Item added to subscription: {$item->getDisplayName()}",
            null,
            $item->toArray(),
            $metadata,
            $source
        );
    }

    public static function logItemRemoved(Subscription $subscription, SubscriptionItem $item, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_ITEM_REMOVED,
            "Item removed from subscription: {$item->getDisplayName()}",
            $item->toArray(),
            null,
            $metadata,
            $source
        );
    }

    public static function logItemUpdated(Subscription $subscription, SubscriptionItem $item, $oldValues, $newValues, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_ITEM_UPDATED,
            "Subscription item updated: {$item->getDisplayName()}",
            $oldValues,
            $newValues,
            $metadata,
            $source
        );
    }

    public static function logOrderGenerated(Subscription $subscription, $orderId, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_ORDER_GENERATED,
            "Order #{$orderId} generated for subscription",
            null,
            ['order_id' => $orderId],
            $metadata,
            $source
        );
    }

    public static function logPaymentAttempted(Subscription $subscription, $amount, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_PAYMENT_ATTEMPTED,
            "Payment of £{$amount} attempted for subscription",
            null,
            ['amount' => $amount],
            $metadata,
            $source
        );
    }

    public static function logPaymentSucceeded(Subscription $subscription, $amount, $paymentId = null, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_PAYMENT_SUCCEEDED,
            "Payment of £{$amount} succeeded for subscription" . ($paymentId ? " (Payment ID: {$paymentId})" : ''),
            null,
            ['amount' => $amount, 'payment_id' => $paymentId],
            $metadata,
            $source
        );
    }

    public static function logPaymentFailed(Subscription $subscription, $amount, $reason = null, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        $description = "Payment of £{$amount} failed for subscription";
        if ($reason) {
            $description .= " - Reason: {$reason}";
        }

        return static::logAction(
            $subscription->id,
            self::ACTION_PAYMENT_FAILED,
            $description,
            null,
            ['amount' => $amount, 'failure_reason' => $reason],
            $metadata,
            $source
        );
    }

    public static function logEmailSent(Subscription $subscription, $subject, $emailType = null, $source = self::SOURCE_SYSTEM, $metadata = [])
    {
        return static::logAction(
            $subscription->id,
            self::ACTION_EMAIL_SENT,
            "Email sent: {$subject}" . ($emailType ? " (Type: {$emailType})" : ''),
            null,
            ['subject' => $subject, 'email_type' => $emailType],
            $metadata,
            $source
        );
    }

    /**
     * Helper methods
     */
    public function getFormattedDate()
    {
        return $this->created_at->format('d/m/Y H:i:s');
    }

    public function getActorName()
    {
        if ($this->source === self::SOURCE_CUSTOMER && $this->member) {
            return $this->member->full_name . ' (Customer)';
        } elseif ($this->source === self::SOURCE_ADMIN) {
            return 'Admin User';
        } elseif ($this->source === self::SOURCE_SYSTEM) {
            return 'System';
        } elseif ($this->source === self::SOURCE_API) {
            return 'API';
        }

        return 'Unknown';
    }

    public function hasDataChanges()
    {
        return !empty($this->old_values) || !empty($this->new_values);
    }

    public function getChangesSummary()
    {
        if (!$this->hasDataChanges()) {
            return null;
        }

        $changes = [];

        if ($this->old_values && $this->new_values) {
            foreach ($this->new_values as $field => $newValue) {
                if (isset($this->old_values[$field]) && $this->old_values[$field] !== $newValue) {
                    $changes[] = "{$field}: '{$this->old_values[$field]}' → '{$newValue}'";
                }
            }
        }

        return implode(', ', $changes);
    }

    public static function getActionTypes()
    {
        return [
            self::ACTION_CREATED => 'Created',
            self::ACTION_UPDATED => 'Updated',
            self::ACTION_STATUS_CHANGED => 'Status Changed',
            self::ACTION_ITEM_ADDED => 'Item Added',
            self::ACTION_ITEM_REMOVED => 'Item Removed',
            self::ACTION_ITEM_UPDATED => 'Item Updated',
            self::ACTION_ORDER_GENERATED => 'Order Generated',
            self::ACTION_PAYMENT_ATTEMPTED => 'Payment Attempted',
            self::ACTION_PAYMENT_SUCCEEDED => 'Payment Succeeded',
            self::ACTION_PAYMENT_FAILED => 'Payment Failed',
            self::ACTION_EMAIL_SENT => 'Email Sent',
        ];
    }

    public static function getSources()
    {
        return [
            self::SOURCE_ADMIN => 'Admin',
            self::SOURCE_CUSTOMER => 'Customer',
            self::SOURCE_SYSTEM => 'System',
            self::SOURCE_API => 'API',
        ];
    }
}