<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Filament\Models\Contracts\FilamentUser;
use Filament\Models\Contracts\HasAvatar;
use Filament\Panel;
use Laravel\Sanctum\HasApiTokens;

#[Fillable(['name', 'email', 'avatar', 'phone', 'birthday', 'password', 'role', 'reseller_status', 'reseller_package_id', 'reseller_expires_at', 'reseller_bkash_number', 'reseller_nagad_number', 'reseller_rocket_number', 'reseller_bank_details', 'reseller_nid_front', 'reseller_nid_back', 'reseller_passport_photo', 'reseller_store_name', 'reseller_fb_profile', 'reseller_fb_page', 'reseller_website', 'reseller_whatsapp', 'reseller_telegram', 'reseller_code'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable implements FilamentUser, HasAvatar
{
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($user) {
            if ($user->role === 'reseller') {
                if (!$user->reseller_code) {
                    $user->reseller_code = self::generateUniqueResellerCode();
                }
                if ($user->reseller_status === 'active' && !$user->reseller_expires_at) {
                    $days = 365;
                    if ($user->reseller_package_id) {
                        $package = \App\Models\ResellerPackage::find($user->reseller_package_id);
                        if ($package) {
                            $days = $package->validity_days;
                        }
                    }
                    $user->reseller_expires_at = now()->addDays($days);
                }
            }
        });

        static::updating(function ($user) {
            $actorId = auth()->id() ?? $user->id;

            if ($user->role === 'reseller') {
                if (!$user->reseller_code) {
                    $user->reseller_code = self::generateUniqueResellerCode();
                }
                if ($user->reseller_status === 'active' && !$user->reseller_expires_at) {
                    $days = 365;
                    if ($user->reseller_package_id) {
                        $package = \App\Models\ResellerPackage::find($user->reseller_package_id);
                        if ($package) {
                            $days = $package->validity_days;
                        }
                    }
                    $user->reseller_expires_at = now()->addDays($days);
                }
            }

            if ($user->isDirty('password')) {
                \App\Services\AuditLogger::log(
                    'password_changed',
                    'Password updated for: ' . $user->name . ' (' . $user->email . ')',
                    ['password' => '********'],
                    ['password' => '********'],
                    $actorId
                );
            }

            if ($user->isDirty('role')) {
                \App\Services\AuditLogger::log(
                    'user_role_changed',
                    'Role updated for: ' . $user->name . ' (' . $user->email . ')',
                    ['role' => $user->getOriginal('role')],
                    ['role' => $user->role],
                    $actorId
                );
            }
        });
    }

    /** @use HasFactory<UserFactory> */
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * Get the user's avatar URL for Filament.
     */
    public function getFilamentAvatarUrl(): ?string
    {
        return $this->avatar ? asset('storage/' . $this->avatar) : null;
    }

    /**
     * Check if user can access a specific Filament panel.
     */
    public function canAccessPanel(Panel $panel): bool
    {
        if ($panel->getId() === 'reseller') {
            return $this->role === 'reseller' && $this->reseller_status === 'active';
        }
        return $this->isAdmin() || $this->isStaff();
    }

    /**
     * Check if the user is an administrator.
     */
    public function isAdmin(): bool
    {
        return $this->role === 'admin';
    }

    /**
     * Check if the user is a staff member.
     */
    public function isStaff(): bool
    {
        return $this->role === 'staff';
    }

    /**
     * Check if the user is a customer.
     */
    public function isCustomer(): bool
    {
        return $this->role === 'customer';
    }

    /**
     * Check if the user is an active reseller.
     */
    public function isReseller(): bool
    {
        return $this->role === 'reseller' && $this->reseller_status === 'active';
    }

    /**
     * Get reseller wallet balance.
     */
    public function getWalletBalance(): float
    {
        return (float) $this->walletTransactions()
            ->where('status', 'completed')
            ->sum(\Illuminate\Support\Facades\DB::raw("CASE WHEN type = 'credit' THEN amount ELSE -amount END"));
    }

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
            'birthday' => 'date',
            'reseller_expires_at' => 'datetime',
        ];
    }

    /**
     * Get the customer's addresses.
     */
    public function addresses(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(CustomerAddress::class, 'customer_id');
    }

    /**
     * Get the customer's orders.
     */
    public function orders(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(Order::class, 'user_id');
    }

    /**
     * Get the customer's payment transactions.
     */
    public function transactions(): \Illuminate\Database\Eloquent\Relations\HasManyThrough
    {
        return $this->hasManyThrough(Transaction::class, Order::class, 'user_id', 'order_id');
    }

    /**
     * Get the customer's wishlist items.
     */
    public function wishlist(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(Wishlist::class);
    }

    /**
     * Get the customer's wishlist products.
     */
    public function wishlistProducts(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
    {
        return $this->belongsToMany(Product::class, 'wishlists');
    }

    /**
     * Get the reseller's package.
     */
    public function resellerPackage(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(ResellerPackage::class, 'reseller_package_id');
    }

    /**
     * Get the reseller's wallet transactions.
     */
    public function walletTransactions(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(ResellerWalletTransaction::class, 'user_id');
    }

    /**
     * Get the reseller's withdrawal requests.
     */
    public function withdrawRequests(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(ResellerWithdrawRequest::class, 'user_id');
    }

    /**
     * Get the customer orders placed by this user as a reseller.
     */
    public function resellerOrders(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(Order::class, 'reseller_id');
    }

    /**
     * Generate a unique 4-digit numeric code.
     */
    public static function generateUniqueResellerCode()
    {
        do {
            $code = strval(rand(1000, 9999));
        } while (self::where('reseller_code', $code)->exists());

        return $code;
    }
}
