<?php

namespace App\Models;

use App\Enums\Role;
use App\Models\Concerns\InteractsWithActivityLog;
use Illuminate\Database\Eloquent\Attributes\Appends;
use Illuminate\Database\Eloquent\Attributes\Guarded;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Activitylog\Models\Concerns\CausesActivity;
use Spatie\Permission\Traits\HasRoles;

#[Guarded(['id'])]
#[Hidden(['password', 'remember_token'])]
#[Appends(['role_label'])]
class User extends Authenticatable
{
    // 1. Use Trait
    use CausesActivity, HasFactory, HasRoles, InteractsWithActivityLog, Notifiable, SoftDeletes;

    // 2. Casting
    protected function casts(): array
    {
        return [
            'is_active' => 'boolean',
            'last_login_at' => 'datetime',
            'password' => 'hashed',
        ];
    }

    // 3. Scope (grouped by column, then alphabetical)
    // Column Group: is_active
    #[Scope]
    protected function active(Builder $query): void
    {
        $query->where('is_active', true);
    }

    #[Scope]
    protected function inactive(Builder $query): void
    {
        $query->where('is_active', false);
    }

    // 4. Attribute
    public function roleLabel(): Attribute
    {
        return Attribute::make(
            get: function () {
                $role = $this->roles->first();

                if (! $role) {
                    return null;
                }

                $enum = Role::tryFrom($role->name);

                return $enum ? $enum->label() : ucwords(str_replace('-', ' ', $role->name));
            },
        );
    }

    // 5. Relation
    public function cashTransactions(): HasMany
    {
        return $this->hasMany(CashTransaction::class, 'created_by_id');
    }

    public function closedPayrollPeriods(): HasMany
    {
        return $this->hasMany(PayrollPeriod::class, 'closed_by_id');
    }

    public function createdCuttings(): HasMany
    {
        return $this->hasMany(Cutting::class, 'created_by_id');
    }

    public function createdPayrollAdjustments(): HasMany
    {
        return $this->hasMany(PayrollAdjustment::class, 'created_by_id');
    }

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

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

    public function employee(): HasOne
    {
        return $this->hasOne(Employee::class);
    }

    public function expenses(): HasMany
    {
        return $this->hasMany(Expense::class, 'created_by_id');
    }

    public function marketingOrders(): HasMany
    {
        return $this->hasMany(Order::class, 'marketing_id');
    }

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

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

    public function orders(): HasMany
    {
        return $this->hasMany(Order::class, 'created_by_id');
    }

    public function paidPayrolls(): HasMany
    {
        return $this->hasMany(Payroll::class, 'paid_by_id');
    }

    public function profile(): HasOne
    {
        return $this->hasOne(UserProfile::class);
    }

    public function purchases(): HasMany
    {
        return $this->hasMany(Purchase::class, 'created_by_id');
    }

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

    public function submittedCuttings(): HasMany
    {
        return $this->hasMany(Cutting::class, 'submitted_by_id');
    }

    public function verifiedLeaveRequests(): HasMany
    {
        return $this->hasMany(LeaveRequest::class, 'verified_by_id');
    }
}
