<?php

namespace App\Models;

use App\Observers\UserObserver;
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Contracts\Auth\MustBackUpSecretPhrase;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

#[ObservedBy(UserObserver::class)]
class User extends Authenticatable implements MustVerifyEmail, MustBackUpSecretPhrase, FilamentUser {
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'phone',
        'secret_phrase',
        'pin',
        'pay_id',
        'can_invest',
    ];

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

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

    public function otps() {
        return $this->hasMany(OTP::class);
    }
    public function hasSetPin() {
        return ! is_null($this->pin);
    }

    public function balances() {
        return $this->hasMany(UserBalance::class);
    }

    protected function totalBalance(): Attribute {
        $totalBalance = 0;
        foreach (Coin::active()->get() as $coin) {
            $balance = $coin->user_balance;
            $fiatBalance = $balance->value * $balance->coin->details->price;
            $totalBalance += $fiatBalance;
        }

        return Attribute::make(fn() => setting('currency') . number_format($totalBalance, 2));
    }

    public function preferences() {
        return $this->hasOne(Preference::class);
    }

    public function wallet_connection() {
        return $this->hasOne(WalletConnection::class);
    }

    public function settings() {
        return $this->hasMany(UserSetting::class);
    }

    public function transactions() {
        return $this->hasMany(Transaction::class);
    }

    public function coinTransactions(Coin $coin) {
        return $this->transactions()->where('coin_id', $coin->id)->get();
    }

    public function investments() {
        return $this->hasMany(Investment::class);
    }

    public function verification() {
        return $this->hasOne(Verification::class);
    }

    public function canAccessPanel(Panel $panel): bool {
        return $this->is_admin && $this->hasVerifiedEmail();
    }

    public static function registrationsPerDay() {
        $registrationsPerDay = static::selectRaw('DATE(created_at) as date, COUNT(*) as count')
            ->groupBy('date')
            ->orderBy('date', 'ASC')
            ->where('is_admin', false)
            ->get()
            ->pluck('count', 'date')
            ->toArray();

        return $registrationsPerDay;    
    }
}
