<?php

namespace App\Models;

use App\Models\Settings\DataSettings\PaymentMethod;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class Subscription extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'subscriptions';
    protected $fillable = [
        'code',
        'customer_id',
        'plan_id',
        'start_date',
        'end_date',
        'amount',
        'discount',
        'net_amount',
        'vat',
        'vat_value',
        'total',
        'amount_paid',
        'remaining_paid',
        'payment_method_id',
        'vat_included',
        'sessions_count',
        'remaining_sessions',
        'status',
        'notes',
        'created_by',
        'renewed_to',
        'is_renewal',

        'transferred_from_customer_id', 'transferred_to_customer_id',
        'transferred_by', 'transferred_at', 'transfer_reason', 'is_transferred'
    ];

    protected $casts = [
        'start_date' => 'date',
        'end_date' => 'date',
        'amount' => 'decimal:2',
        'discount' => 'decimal:2',
        'net_amount' => 'decimal:2',
        'vat' => 'decimal:2',
        'vat_value' => 'decimal:2',
        'total' => 'decimal:2',
        'amount_paid' => 'decimal:2',
        'remaining_paid' => 'decimal:2',
        'vat_included' => 'boolean',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'is_renewal' => 'boolean',

        'transferred_at' => 'datetime',
        'is_transferred' => 'boolean',
    ];

    // العلاقات
    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    public function plan(): BelongsTo
    {
        return $this->belongsTo(Plan::class);
    }

    public function register(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function paymentMethod(): BelongsTo
    {
        return $this->belongsTo(PaymentMethod::class);
    }

    public function receipts(): HasMany
    {
        return $this->hasMany(ReceiptVoucher::class);
    }

    public function refunds(): HasMany
    {
        return $this->hasMany(Refund::class);
    }

    public function attendances(): HasMany
    {
        return $this->hasMany(Attendance::class);
    }

    public function originalCustomer(): BelongsTo
    {
        return $this->belongsTo(Customer::class, 'transferred_from_customer_id');
    }

    public function transferredToCustomer(): BelongsTo
    {
        return $this->belongsTo(Customer::class, 'transferred_to_customer_id');
    }

    public function transferredByUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'transferred_by');
    }


    public function decrementRemainingSessions(): bool
    {
        if (!is_null($this->remaining_sessions) && $this->remaining_sessions > 0) {
            $this->decrement('remaining_sessions');
            return true;
        }
        return false;
    }

    public function canCheckIn(): array
    {
        // تحقق من صلاحية الاشتراك
        if (!$this->isValid) {
            return ['can' => false, 'reason' => 'الاشتراك غير نشط أو منتهي الصلاحية'];
        }

        // تحقق من وجود حصص متبقية
        if (!is_null($this->remaining_sessions) && $this->remaining_sessions <= 0) {
            return ['can' => false, 'reason' => 'لا توجد حصص متبقية في هذا الاشتراك'];
        }

        // تحقق من عدم وجود تسجيل دخول نشط اليوم
        $hasActiveAttendance = $this->attendances()
            ->whereDate('check_in', today())
            ->where('status', 'checked_in')
            ->exists();

        if ($hasActiveAttendance) {
            return ['can' => false, 'reason' => 'تم تسجيل الدخول مسبقاً اليوم'];
        }

        return ['can' => true, 'reason' => null];
    }

    // Scopes
    public function scopeActive($query)
    {
        return $query->where('status', 'active')
            ->whereDate('end_date', '>=', Carbon::today());
    }

    public function scopeExpired($query)
    {
        return $query->where('status', 'expired')
            ->orWhereDate('end_date', '<', Carbon::today());
    }

    public function scopeExpiringSoon($query, $days = 7)
    {
        return $query->where('status', 'active')
            ->whereBetween('end_date', [Carbon::today(), Carbon::today()->addDays($days)]);
    }

    public function scopeByCustomer($query, $customerId)
    {
        return $query->where('customer_id', $customerId);
    }

    public function scopeByPlan($query, $planId)
    {
        return $query->where('plan_id', $planId);
    }

    public function scopeWithRemainingBalance($query)
    {
        return $query->where('remaining_paid', '>', 0);
    }

    // Accessors
    public function getStartDateAttribute(): Carbon
    {
        return $this->created_at;
    }

    public function getDaysRemainingAttribute(): int
    {
        if (!$this->isActive()) {
            return 0;
        }

        return max(0, Carbon::today()->diffInDays($this->end_date, false));
    }

    public function getIsPaidFullyAttribute(): bool
    {
        return $this->remaining_paid <= 0;
    }

    public function getPaymentProgressAttribute(): float
    {
        if ($this->total <= 0) {
            return 0;
        }

        return round(($this->amount_paid / $this->total) * 100, 2);
    }

    public function getStatusTextAttribute(): string
    {
        return match($this->status) {
            'active' => 'نشط',
            'expired' => 'منتهي',
            'canceled' => 'ملغي',
            default => $this->status
        };
    }

    public function calculateRefundAmount(): float
    {
        // مثال: لو الاشتراك شهري
        $daysUsed = now()->diffInDays($this->start_date);
        $totalDays = now()->diffInDays($this->start_date->copy()->addMonth());
        $usedRatio = $daysUsed / $totalDays;

        // المبلغ المسترد = المبلغ المدفوع * النسبة غير المستخدمة
        return round($this->amount * (1 - $usedRatio), 2);
    }

    public function getStatusColorAttribute(): string
    {
        if ($this->status === 'active' && $this->days_remaining <= 3) {
            return 'warning';
        }

        return match($this->status) {
            'active' => 'success',
            'expired' => 'danger',
            'canceled' => 'secondary',
            default => 'light'
        };
    }

    // Methods
    public function isActive(): bool
    {
        return $this->status === 'active' && $this->end_date->isFuture();
    }

    public function cancel(): bool
    {
        return $this->update(['status' => 'canceled']);
    }

    public function renew($newEndDate = null): bool
    {
        $endDate = $newEndDate ?? Carbon::parse($this->end_date)->addDays($this->plan->duration_days);

        return $this->update([
            'end_date' => $endDate,
            'status' => 'active'
        ]);
    }

    public function addPayment($amount, $paymentMethodId = null): bool
    {
        $newAmountPaid = $this->amount_paid + $amount;
        $newRemaining = max(0, $this->total - $newAmountPaid);

        return $this->update([
            'amount_paid' => $newAmountPaid,
            'remaining_paid' => $newRemaining
        ]);
    }

    public function transferToCustomer($newCustomerId, $reason = null, $transferBy = null): SubscriptionTransfer
    {
        $oldCustomerId = $this->customer_id;
        $oldData = $this->toArray();

        $transfer = new SubscriptionTransfer([
            'subscription_id' => $this->id,
            'from_customer_id' => $oldCustomerId,
            'to_customer_id' => $newCustomerId,
            'transferred_by' => $transferBy ?? auth()->id(),
            'transfer_date' => now(),
            'reason' => $reason,
            'old_data' => $oldData,
        ]);

        $this->update([
            'customer_id' => $newCustomerId,
            'transferred_from_customer_id' => $oldCustomerId,
            'transferred_to_customer_id' => $newCustomerId,
            'transferred_by' => $transferBy ?? auth()->id(),
            'transferred_at' => now(),
            'transfer_reason' => $reason,
            'is_transferred' => true,
        ]);

        $transfer->new_data = $this->fresh()->toArray();
        $transfer->save();

        $this->updateRelatedRecords($newCustomerId);

        return $transfer;
    }

    private function updateRelatedRecords($customerId): void
    {
        ReceiptVoucher::where('subscription_id', $this->id)
            ->update(['customer_id' => $customerId]);
    }

    // Boot method
    protected static function boot(): void
    {
        parent::boot();

        static::creating(function ($subscription) {
            if (empty($subscription->code)) {
                $subscription->code = static::generateCode();
            }
        });
    }

    private static function generateCode(): string
    {
        $year = now()->format('Y');
        $month = now()->format('m');
        $lastSubscription = self::whereYear('created_at', $year)
            ->whereMonth('created_at', $month)
            ->latest()
            ->first();

        if ($lastSubscription) {
            $lastNumber = (int) substr($lastSubscription->code, -4);
            $newNumber = str_pad($lastNumber + 1, 4, '0', STR_PAD_LEFT);
        } else {
            $newNumber = '0001';
        }

        $defaultCode = settings('invoice_prefix') ?? 'INV';

        return "{$defaultCode}{$year}{$month}{$newNumber}";
    }

    protected static function booted(): void
    {
        parent::booted();

        static::created(function ($subscription) {
            $paymentMethodId = $subscription->payment_method_id ?? null;
            $amountPaid = $subscription->amount_paid ?? 0; // المبلغ المدفوع فعلياً

            if (!$paymentMethodId || $amountPaid <= 0) {
                return;
            }

            DB::transaction(function () use ($subscription, $amountPaid) {
                $subscription->update([
                    'amount_paid' => $amountPaid,
                    'remaining_paid' => $subscription->total - $amountPaid
                ]);

            });
        });
    }
}
