<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;
use Assada\Achievements\Achiever;
use App\Helpers\SteamHelper;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, HasRoles, Achiever;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'steamid',
        'avatar',
        'banner',
        'slug',
    ];

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

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'last_active_at' => 'datetime',
    ];

    /**
     * Boot the model and add slug generation.
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($user) {
            $user->slug = static::generateUniqueSlug($user->name);
            $user->avatar = str_replace('medium', 'full', $user->avatar);
        });

        static::updating(function ($user) {
            if ($user->isDirty('name')) {
                $user->slug = static::generateUniqueSlug($user->name, $user->id);
            }
            $user->avatar = str_replace('medium', 'full', $user->avatar);
        });

        // Delete the old banner when updating with a new one
        static::updating(function ($user) {
            if ($user->isDirty('banner') && $user->getOriginal('banner')) {
                Storage::disk('public')->delete('user_banners/' . basename($user->getOriginal('banner')));
            }
        });

        // Delete the banner when deleting the user
        static::deleting(function ($user) {
            if ($user->banner) {
                Storage::disk('public')->delete('user_banners/' . basename($user->banner));
            }
        });
    }

    /**
     * Generate a unique slug from the name.
     *
     * @param string $name
     * @param int|null $ignoreId
     * @return string
     */
    protected static function generateUniqueSlug(string $name, int $ignoreId = null): string
    {
        $slug = Str::slug($name);
        $originalSlug = $slug;
        $i = 1;

        while (static::where('slug', $slug)
            ->when($ignoreId, fn($q) => $q->where('id', '!=', $ignoreId))
            ->exists()) {
            $slug = $originalSlug . '-' . $i++;
        }

        return $slug;
    }

    /**
     * Find or create a user by SteamID
     *
     * @param array $steamData
     * @return User
     */
    public static function findOrCreateBySteamId(array $steamData): User
    {
        return self::updateOrCreate(
            ['steamid' => $steamData['steamid']],
            [
                'name' => $steamData['name'],
                'avatar' => $steamData['avatar'],
            ]
        );
    }

    /**
     * Get the Steam profile URL for the user.
     *
     * @return string
     */
    public function getSteamProfileUrl(): string
    {
        return SteamHelper::getProfileUrl($this->steamid);
    }

    /**
     * Get the legacy SteamID format.
     *
     * @return string
     */
    public function getLegacySteamId(): string
    {
        return SteamHelper::steamId64ToLegacy($this->steamid);
    }

    /**
     * Use slug for route model binding instead of ID.
     *
     * @return string
    */
    public function getRouteKeyName(): string
    {
        return 'slug';
    }

    /**
     * Get the banner URL for the user.
     *
     * @return string|null
     */
    public function getBannerUrl()
    {
        if (!$this->banner) {
            return null;
        }
        
        return Storage::url('user_banners/' . basename($this->banner));
    }

    /**
     * Upload a new banner for the user.
     *
     * @param \Illuminate\Http\UploadedFile $file
     * @return void
     */
    public function uploadBanner($file)
    {
        // Delete old banner if exists
        if ($this->banner) {
            Storage::disk('public')->delete('user_banners/' . basename($this->banner));
        }

        // Generate a unique filename
        $filename = $this->id . '-' . Str::random(10) . '.' . $file->getClientOriginalExtension();
        
        // Store the file
        $path = $file->storeAs('user_banners', $filename, 'public');
        
        // Update user model
        $this->update([
            'banner' => $filename
        ]);
    }
}