<?php

namespace Licenzo\Model;

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

use Licenzo\Framework\Database\Model;

class SubscriptionSchedule extends Model
{
    protected $table = 'licenzo_subscription_schedules';

    // Action type constants
    const ACTION_CANCEL = 'cancel';
    const ACTION_UPGRADE = 'upgrade';
    const ACTION_DOWNGRADE = 'downgrade';
    const ACTION_PRICE_CHANGE = 'price_change';
    const ACTION_PAUSE = 'pause';
    const ACTION_RESUME = 'resume';
    const ACTION_ADD_PRODUCT = 'add_product';
    const ACTION_REMOVE_PRODUCT = 'remove_product';
    const ACTION_RENEWAL_CHARGE = 'renewal_charge';

    // Status constants
    const STATUS_PENDING = 'pending';
    const STATUS_EXECUTED = 'executed';
    const STATUS_CANCELED = 'canceled';
    const STATUS_FAILED = 'failed';

    protected $fillable = [
        'subscription_id', 'customer_id', 'action_type', 'action_data',
        'scheduled_at', 'executed_at', 'status',
        'execution_result', 'failure_reason', 'triggered_by', 'notes'
    ];

    protected $casts = [
        'id' => 'int',
        'subscription_id' => 'int',
        'customer_id' => 'int',
        'triggered_by' => 'int',
        'scheduled_at' => 'datetime',
        'executed_at' => 'datetime',
        'action_data' => 'array',
        'execution_result' => 'array',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];

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

    public function customer()
    {
        return $this->belongsTo(Customer::class);
    }

    public function triggeredBy()
    {
        return $this->belongsTo(User::class, 'triggered_by');
    }

    // Scopes
    public function scopePending($query)
    {
        return $query->where('status', static::STATUS_PENDING);
    }

    public function scopeExecuted($query)
    {
        return $query->where('status', static::STATUS_EXECUTED);
    }

    public function scopeCanceled($query)
    {
        return $query->where('status', static::STATUS_CANCELED);
    }

    public function scopeFailed($query)
    {
        return $query->where('status', static::STATUS_FAILED);
    }

    public function scopeDueForExecution($query)
    {
        return $query->where('status', static::STATUS_PENDING)
                     ->where('scheduled_at', '<=', gmdate('Y-m-d H:i:s'));
    }

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

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

    // Helpers
    public function isPending(): bool
    {
        return $this->status === static::STATUS_PENDING;
    }

    public function isExecuted(): bool
    {
        return $this->status === static::STATUS_EXECUTED;
    }

    public function isCanceled(): bool
    {
        return $this->status === static::STATUS_CANCELED;
    }

    public function isFailed(): bool
    {
        return $this->status === static::STATUS_FAILED;
    }

    public function isDue(): bool
    {
        return $this->isPending() && $this->scheduled_at->isPast();
    }

    public function canExecute(): bool
    {
        return $this->isPending() && $this->isDue();
    }

    public function canCancel(): bool
    {
        return $this->isPending();
    }

    public function markAsExecuted(array $result = []): bool
    {
        $this->status = static::STATUS_EXECUTED;
        $this->executed_at = gmdate('Y-m-d H:i:s');
        $this->execution_result = $result;
        return $this->save();
    }

    public function markAsFailed(string $reason): bool
    {
        $this->status = static::STATUS_FAILED;
        $this->failure_reason = $reason;
        return $this->save();
    }

    public function markAsCanceled(): bool
    {
        $this->status = static::STATUS_CANCELED;
        return $this->save();
    }

    public function getActionDataField(string $key, $default = null)
    {
        return $this->action_data[$key] ?? $default;
    }

    public function setActionDataField(string $key, $value): void
    {
        $data = $this->action_data ?? [];
        $data[$key] = $value;
        $this->action_data = $data;
    }

    public function getExecutionResultField(string $key, $default = null)
    {
        return $this->execution_result[$key] ?? $default;
    }

    // Action type checkers
    public function isCancel(): bool
    {
        return $this->action_type === static::ACTION_CANCEL;
    }

    public function isUpgrade(): bool
    {
        return $this->action_type === static::ACTION_UPGRADE;
    }

    public function isDowngrade(): bool
    {
        return $this->action_type === static::ACTION_DOWNGRADE;
    }

    public function isPriceChange(): bool
    {
        return $this->action_type === static::ACTION_PRICE_CHANGE;
    }

    public function isPause(): bool
    {
        return $this->action_type === static::ACTION_PAUSE;
    }

    public function isResume(): bool
    {
        return $this->action_type === static::ACTION_RESUME;
    }

    public function isAddProduct(): bool
    {
        return $this->action_type === static::ACTION_ADD_PRODUCT;
    }

    public function isRemoveProduct(): bool
    {
        return $this->action_type === static::ACTION_REMOVE_PRODUCT;
    }

    public function isRenewalCharge(): bool
    {
        return $this->action_type === static::ACTION_RENEWAL_CHARGE;
    }
}
