<?php

namespace App\Models;

use App\Support\Authorization\PermissionCatalog;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, HasRoles, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'role',
        'staff_role',
        'organization_id',
        'has_all_mariachi_groups',
        'mariachi_group_id',
        'is_active',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
            'staff_role' => 'string',
            'organization_id' => 'integer',
            'has_all_mariachi_groups' => 'boolean',
            'is_active' => 'boolean',
        ];
    }

    public const ROLE_ADMIN = 'ADMIN';

    public const ROLE_STAFF = 'STAFF';

    public const ROLE_CLIENT = 'CLIENT';

    public const ROLE_OWNER_STAFF = 'OWNER_STAFF';

    public const STAFF_ROLE_SALES = 'SALES';

    public const STAFF_ROLE_OPS = 'OPS';

    public static function accountRoles(): array
    {
        return self::adminRoles();
    }

    public static function adminRoles(): array
    {
        return [
            self::ROLE_ADMIN,
            self::ROLE_STAFF,
        ];
    }

    public static function staffRoles(): array
    {
        $codes = StaffRole::query()
            ->where('is_active', true)
            ->orderBy('name')
            ->pluck('code')
            ->all();

        if (! empty($codes)) {
            return $codes;
        }

        return [self::STAFF_ROLE_SALES, self::STAFF_ROLE_OPS];
    }

    public function isAdmin(): bool
    {
        return $this->role === self::ROLE_ADMIN;
    }

    public function organization()
    {
        return $this->belongsTo(Organization::class);
    }

    public function apiTokens()
    {
        return $this->hasMany(ApiToken::class);
    }

    public function assignedMariachiGroups()
    {
        return $this->belongsToMany(MariachiGroup::class, 'mariachi_group_user')
            ->withTimestamps()
            ->orderByDesc('is_default')
            ->orderBy('sort_order')
            ->orderBy('name');
    }

    public function mariachiGroup()
    {
        return $this->belongsTo(Organization::class, 'organization_id');
    }

    public function platformRoleName(): ?string
    {
        $previousTeamId = getPermissionsTeamId();
        setPermissionsTeamId(PermissionCatalog::GLOBAL_TEAM_ID);
        $roleName = $this->getRoleNames()->first();
        setPermissionsTeamId($previousTeamId);

        return $roleName;
    }

    public function ownerRoleName(?int $organizationId = null): ?string
    {
        $organizationId = $organizationId ?: (int) ($this->organization_id ?? 0);
        if ($organizationId <= 0) {
            return null;
        }

        $previousTeamId = getPermissionsTeamId();
        setPermissionsTeamId($organizationId);
        $roleName = $this->getRoleNames()->first();
        setPermissionsTeamId($previousTeamId);

        return $roleName;
    }

    public function getMariachiGroupIdAttribute(): ?int
    {
        return $this->organization_id;
    }

    public function setMariachiGroupIdAttribute($value): void
    {
        $this->attributes['organization_id'] = $value ?: null;
    }
}
