<?php

namespace MtcPharmacy\Subscriptions\Classes\Traits;

use MtcPharmacy\Subscriptions\Classes\SubscriptionLog;
use Illuminate\Support\Facades\Log;

trait LogsChanges
{
    protected $originalAttributes = [];

    public function save(array $options = [])
    {
        $this->originalAttributes = $this->getOriginal();

        $result = parent::save($options);

        if ($result) {
            $this->logModelChanges();
        }

        return $result;
    }

    protected function logModelChanges()
    {
        $changes = $this->getChanges();

        if (empty($changes)) {
            return;
        }

        // Handle Subscription model logging
        if ($this instanceof \MtcPharmacy\Subscriptions\Classes\Subscription) {
            $this->logSubscriptionChanges($changes);
        }

        // Handle SubscriptionItem model logging
        if ($this instanceof \MtcPharmacy\Subscriptions\Classes\SubscriptionItem) {
            $this->logSubscriptionItemChanges($changes);
        }
    }

    protected function logSubscriptionChanges($changes)
    {
        // Check if status changed
        if (isset($changes['status'])) {
            $oldStatus = $this->originalAttributes['status'] ?? null;
            $newStatus = $changes['status'];

            if (!empty($oldStatus) && !empty($newStatus) && $oldStatus !== $newStatus) {
                SubscriptionLog::logStatusChanged(
                    $this,
                    $oldStatus,
                    $newStatus,
                    $this->determineSource()
                );
            }
        } else {
            // Log other changes (only if status didn't change to avoid duplicates)
            $significantChanges = $this->getSignificantChanges($changes);
            if (!empty($significantChanges)) {
                $description = $this->generateUpdateDescription($significantChanges);
                if (!empty($description) && !empty($this->id)) {
                    SubscriptionLog::logAction(
                        $this->id,
                        SubscriptionLog::ACTION_UPDATED,
                        $description,
                        $this->extractChangedValues($this->originalAttributes, array_keys($significantChanges)),
                        $significantChanges,
                        ['all_changes' => $changes],
                        $this->determineSource()
                    );
                }
            }
        }
    }

    protected function logSubscriptionItemChanges($changes)
    {
        if ($this->subscription && !empty($this->id)) {
            $significantChanges = $this->getSignificantChanges($changes);
            if (!empty($significantChanges)) {
                SubscriptionLog::logItemUpdated(
                    $this->subscription,
                    $this,
                    $this->extractChangedValues($this->originalAttributes, array_keys($significantChanges)),
                    $significantChanges,
                    $this->determineSource(),
                    ['item_id' => $this->id]
                );
            }
        }
    }

    protected function determineSource()
    {
        // Check if we're in a web request
        if (app()->runningInConsole()) {
            return SubscriptionLog::SOURCE_SYSTEM;
        }

        if (isset($_SESSION['member_id']) && !empty($_SESSION['member_id'])) {
            return SubscriptionLog::SOURCE_CUSTOMER;
        }

        if (isset($_SESSION['adminId']) && !empty($_SESSION['adminId'])) {
            return SubscriptionLog::SOURCE_ADMIN;
        }

        return SubscriptionLog::SOURCE_SYSTEM;
    }

    protected function getSignificantChanges($changes)
    {
        $excludeFields = ['updated_at', 'created_at'];

        return array_filter($changes, function ($key) use ($excludeFields) {
            return !in_array($key, $excludeFields);
        }, ARRAY_FILTER_USE_KEY);
    }

    protected function generateUpdateDescription($changes)
    {
        $descriptions = [];

        foreach ($changes as $field => $newValue) {
            switch ($field) {
                case 'price_per_issue':
                    $descriptions[] = "price per issue updated to £{$newValue}";
                    break;
                case 'interval_multiplier':
                    $descriptions[] = "interval multiplier updated to {$newValue}";
                    break;
                case 'interval':
                    $descriptions[] = "interval updated to {$newValue}";
                    break;
                case 'can_be_paused':
                    $descriptions[] = "can be paused setting changed to " . ($newValue ? 'true' : 'false');
                    break;
                case 'max_number_of_issues':
                    $descriptions[] = "maximum number of issues updated to {$newValue}";
                    break;
                case 'expiry_date':
                    $descriptions[] = "expiry date updated to {$newValue}";
                    break;
                case 'next_issue_date':
                    $descriptions[] = "next issue date updated to {$newValue}";
                    break;
                case 'label':
                    $descriptions[] = "label updated to '{$newValue}'";
                    break;
                case 'shop_item_size_id':
                    $descriptions[] = "item size updated to {$newValue}";
                    break;
                default:
                    $descriptions[] = "{$field} updated to '{$newValue}'";
            }
        }

        if ($this instanceof \MtcPharmacy\Subscriptions\Classes\Subscription) {
            return "Subscription updated: " . implode(', ', $descriptions);
        } else {
            return "Subscription item updated: " . implode(', ', $descriptions);
        }
    }

    protected function extractChangedValues($original, $keys)
    {
        return array_intersect_key($original, array_flip($keys));
    }
}