<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class ShopUser extends Model
{
    /** @use HasFactory<\Database\Factories\ShopUserFactory> */
    use HasFactory;

    protected $table = 'shop_users';

    protected $fillable = [
        'shop_name',
        'phone_number',
        'password',
        'plan_type',
        'plan_expiry_date',
        'plan_status',
    ];

    protected $hidden = [
        'password',
    ];

    protected function casts(): array
    {
        return [
            'password' => 'hashed',
            'plan_expiry_date' => 'date',
            'created_at' => 'datetime',
            'updated_at' => 'datetime',
        ];
    }

    public function unlockOrders(): HasMany
    {
        return $this->hasMany(UnlockOrder::class, 'shop_user_id');
    }

    public function payments(): HasMany
    {
        return $this->hasMany(ShopPayment::class, 'shop_user_id');
    }

    public function subscriptions(): HasMany
    {
        return $this->hasMany(Subscription::class, 'user_id');
    }

    public function currentSubscription(): ?Subscription
    {
        return $this->subscriptions()
            ->latest('expiry_date')
            ->first();
    }

    public function isExpired(): bool
    {
        return $this->plan_expiry_date?->isPast() ?? false;
    }

    public function isFree(): bool
    {
        return $this->plan_type === 'free';
    }

    public function isBasic(): bool
    {
        return $this->plan_type === 'basic';
    }

    public function isPremium(): bool
    {
        return $this->plan_type === 'premium';
    }

    public function remainingFreeOrders(): int
    {
        if (! $this->isFree() || $this->isExpired()) {
            return 0;
        }

        $ordersToday = $this->unlockOrders()
            ->whereDate('date', today())
            ->count();

        return max(0, 5 - $ordersToday);
    }

    public function canCreateOrder(): bool
    {
        if ($this->isExpired()) {
            return false;
        }

        if ($this->isFree()) {
            return $this->remainingFreeOrders() > 0;
        }

        return true;
    }

    public function assignTrialSubscription(): void
    {
        $expiryDate = today()->addDays(7);
        $this->update([
            'plan_type' => 'free',
            'plan_expiry_date' => $expiryDate,
            'plan_status' => 'active',
        ]);

        $this->subscriptions()->create([
            'plan_type' => 'free',
            'expiry_date' => $expiryDate,
            'status' => 'active',
        ]);
    }

    public function renewSubscription(string $planType, \DateTimeInterface $expiryDate): void
    {
        $this->update([
            'plan_type' => $planType,
            'plan_expiry_date' => $expiryDate,
            'plan_status' => $expiryDate->isPast() ? 'expired' : 'active',
        ]);

        $this->subscriptions()->create([
            'plan_type' => $planType,
            'expiry_date' => $expiryDate,
            'status' => $expiryDate->isPast() ? 'expired' : 'active',
        ]);
    }

    public function getBalance(): float
    {
        $totalCharged = $this->unlockOrders()
            ->where('status', 'done')
            ->sum('service_price');

        $totalPaid = $this->payments()
            ->where('status', 'completed')
            ->sum('amount');

        return $totalCharged - $totalPaid;
    }
}
