<?php

namespace App\Models\Sma\Order;

use App\Models\User;
use App\Models\Model;
use App\Tec\Casts\AppDate;
use App\Tec\Scopes\OfStore;
use App\Models\Sma\Pos\Register;
use App\Models\Sma\Setting\Store;
use App\Tec\Policies\UpdatePolicy;
use App\Tec\Traits\HasAttachments;
use App\Tec\Traits\SupplierRecord;
use App\Models\Sma\People\Supplier;
use App\Models\Sma\Accounting\Account;
use App\Tec\Observers\ExpenseObserver;
use App\Tec\Traits\HasSchemalessAttributes;
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
use Illuminate\Database\Eloquent\Attributes\UsePolicy;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;

#[ScopedBy(OfStore::class)]
#[UsePolicy(UpdatePolicy::class)]
#[ObservedBy(ExpenseObserver::class)]
class Expense extends Model
{
    use HasAttachments;
    use HasFactory;
    use HasSchemalessAttributes;
    use SupplierRecord;

    public static $hasUser = true;

    public static $hasStore = true;

    public static $hasRegister = true;

    public static $userRecords = true;

    public static $hasReference = true;

    protected $setHash = true;

    protected function casts(): array
    {
        return [
            'extra_attributes' => 'array',
            'date'             => AppDate::class,
            'created_at'       => AppDate::class . ':time',
            'updated_at'       => AppDate::class . ':time',
        ];
    }

    public function account()
    {
        return $this->belongsTo(Account::class);
    }

    public function register()
    {
        return $this->belongsTo(Register::class);
    }

    public function store()
    {
        return $this->belongsTo(Store::class);
    }

    public function supplier()
    {
        return $this->belongsTo(Supplier::class);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function forceDelete()
    {
        log_activity(__('{record} has permanently deleted.', ['record' => 'Expense']), $this, $this, 'Expense');

        return parent::forceDelete();
    }

    public function scopeFilter($query, array $filters)
    {
        $query->when($filters['trashed'] ?? 'with', fn ($q, $t) => $q->trashed($t))
            ->when($filters['search'] ?? null, fn ($query, $search) => $query->search($search))
            ->when($filters['end'] ?? null, fn ($query, $end) => $query->where('date', '<=', $end))
            ->when($filters['start'] ?? null, fn ($query, $start) => $query->where('date', '>=', $start))
            ->when($filters['user_id'] ?? null, fn ($query, $user_id) => $query->ofUser($user_id))
            ->when($filters['store_id'] ?? null, fn ($query, $store_id) => $query->ofStore($store_id))
            ->when($filters['reference'] ?? null, fn ($query, $reference) => $query->where('reference', 'like', "%{$reference}%"))
            ->when($filters['start_date'] ?? null, fn ($query, $date) => $query->where('date', '>=', $date))
            ->when($filters['end_date'] ?? null, fn ($query, $date) => $query->where('date', '<=', $date))
            ->when($filters['sort'] ?? null, fn ($query, $sort) => $query->sort($sort));
    }

    public function scopeOfStore($query, $store_id = null)
    {
        $query->where('store_id', $store_id ?: session('selected_store_id'));
    }

    public function scopeOfUser($query, $user_id = null)
    {
        $query->where('user_id', $user_id ?: auth()->id());
    }

    public function scopeSearch($query, $s)
    {
        $query->where(fn ($q) => $q->where('date', 'like', "%{$s}%")
            ->orWhere('details', 'like', "%{$s}%")
            ->orWhere('reference', 'like', "%{$s}%")
            ->orWhereHas('supplier', fn ($q) => $q->search($s)),
        );
    }
}
