<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;

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

    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     *
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        'phone',
        'role',
        'module_permissions',
        'password',
        'gender',
        'dob',
        'profile_image',
        'customer_group',
        'status',
        'phone_verified_at',
        'last_login_at',
    ];

    /**
     * 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',
            'module_permissions' => 'array',
            'dob' => 'date',
            'phone_verified_at' => 'datetime',
            'last_login_at' => 'datetime',
        ];
    }

    public static function availableModules(): array
    {
        return [
            'dashboard' => ['label' => 'Dashboard', 'description' => 'Business overview and summary metrics'],
            'products' => ['label' => 'Products', 'description' => 'Products, categories, and subcategories'],
            'orders' => ['label' => 'Orders', 'description' => 'Orders and fulfillment status'],
            'payments' => ['label' => 'Payments', 'description' => 'Transactions and payment methods'],
            'content' => ['label' => 'Content', 'description' => 'CMS pages, slides, and FAQs'],
            'reports' => ['label' => 'Reports', 'description' => 'Sales and product reports'],
            'customers' => ['label' => 'Customers', 'description' => 'Customer records'],
            'staff' => ['label' => 'Staff and permissions', 'description' => 'Staff accounts and module access'],
            'settings' => ['label' => 'Settings', 'description' => 'Website and API settings'],
        ];
    }

    public function canAccessModule(string $module): bool
    {
        if ($this->role === 'super_admin' || $this->hasRole('Super Admin')) {
            return true;
        }

        // Map module names to Spatie permissions
        $mapping = [
            'dashboard' => ['dashboard.view'],
            'products' => ['products.view', 'categories.view', 'brands.view', 'units.view', 'attributes.view'],
            'orders' => ['orders.view'],
            'payments' => ['payments.view'],
            'content' => ['cms.pages.view'],
            'customers' => ['customers.view'],
            'staff' => ['users.view', 'roles.view'],
            'reports' => ['reports.sales', 'reports.orders', 'reports.payments', 'reports.products', 'reports.customers'],
            'settings' => ['settings.view', 'shipping-methods.view'],
        ];

        // Check if Spatie roles/permissions are assigned
        $hasSpatieConfig = false;
        try {
            $hasSpatieConfig = $this->roles()->exists() || $this->permissions()->exists();
        } catch (\Exception $e) {
            // Database not migrated or seeded
        }

        if ($hasSpatieConfig) {
            if (array_key_exists($module, $mapping)) {
                try {
                    foreach ($mapping[$module] as $perm) {
                        if ($this->hasPermissionTo($perm)) {
                            return true;
                        }
                    }
                } catch (\Exception $e) {
                    // Fallback
                }
            }
            return false; // If they have Spatie config but no matching permission, deny access
        }

        // Legacy module check fallback (only if no Spatie config is assigned)
        if ($this->module_permissions === null) {
            return true;
        }

        return is_array($this->module_permissions) && in_array($module, $this->module_permissions, true);
    }

    /**
     * Get the orders for the user.
     */
    public function orders()
    {
        return $this->hasMany(Order::class);
    }

    /**
     * Get the products in the user's wishlist.
     */
    public function wishlistProducts()
    {
        return $this->belongsToMany(Product::class, 'wishlists', 'user_id', 'product_id')->withTimestamps();
    }

    /**
     * Get the wishlist items for the user.
     */
    public function wishlists()
    {
        return $this->hasMany(Wishlist::class);
    }

    /**
     * Get the cart items for the user.
     */
    public function carts()
    {
        return $this->hasMany(Cart::class);
    }

    /**
     * Get the products in the user's cart.
     */
    public function cartProducts()
    {
        return $this->belongsToMany(Product::class, 'carts', 'user_id', 'product_id')
            ->withPivot('quantity')
            ->withTimestamps();
    }

    public function setAttribute($key, $value)
    {
        if ($key === 'permissions') {
            $key = 'module_permissions';
        }
        return parent::setAttribute($key, $value);
    }

    public function getAttribute($key)
    {
        if ($key === 'permissions') {
            if ($this->relationLoaded('permissions') || array_key_exists('permissions', $this->relations)) {
                return $this->getRelationValue('permissions');
            }
            return $this->getAttributeValue('module_permissions');
        }
        return parent::getAttribute($key);
    }

    /**
     * Get the customer saved addresses.
     */
    public function addresses()
    {
        return $this->hasMany(CustomerAddress::class, 'user_id');
    }
}
