<?php

namespace Plugins\SAMBans\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Carbon\Carbon;

class Ban extends Model
{
    protected $connection = 'sambans';
    protected $table = 'sam_bans';
    protected $primaryKey = 'steamid';
    public $incrementing = false;
    protected $keyType = 'string';
    public $timestamps = false;

    protected $fillable = [
        'steamid',
        'reason',
        'admin',
        'unban_date'
    ];

    protected $casts = [
        'unban_date' => 'integer'
    ];

    // Relationships
    public function adminPlayer()
    {
        return $this->belongsTo(Player::class, 'admin', 'steamid');
    }

    // Scopes
    public function scopeActive(Builder $query)
    {
        return $query->where(function($q) {
            $q->where('unban_date', '=', 0)  // Permanent ban
              ->orWhere('unban_date', '>', time()); // Not yet expired
        });
    }

    public function scopeExpired(Builder $query)
    {
        return $query->where('unban_date', '>', 0)
                    ->where('unban_date', '<=', time());
    }

    public function scopeRecent(Builder $query)
    {
        return $query->orderByRaw('CASE WHEN unban_date = 0 THEN 1 ELSE 0 END DESC')
                    ->orderBy('unban_date', 'desc');
    }

    public function scopeSearch(Builder $query, $search)
    {
        return $query->where(function($q) use ($search) {
            $q->where('steamid', 'LIKE', "%{$search}%")
              ->orWhere('reason', 'LIKE', "%{$search}%")
              ->orWhere('admin', 'LIKE', "%{$search}%");
        });
    }

    // SteamID Conversion Utilities
    public static function steamid32To64($steamid32)
    {
        // Convert STEAM_0:X:Y to SteamID64
        if (preg_match('/^STEAM_0:([01]):(\d+)$/', $steamid32, $matches)) {
            $authServer = $matches[1];
            $authId = $matches[2];
            return bcadd(bcadd(bcmul($authId, '2'), $authServer), '76561197960265728');
        }
        return null;
    }

    public static function steamid64To32($steamid64)
    {
        // Convert SteamID64 to STEAM_0:X:Y
        if (is_numeric($steamid64) && $steamid64 > 76561197960265728) {
            $authId = bcdiv(bcsub($steamid64, '76561197960265728'), '2');
            $authServer = bcmod(bcsub($steamid64, '76561197960265728'), '2');
            return "STEAM_0:{$authServer}:" . floor($authId);
        }
        return null;
    }

    public static function steamidToCommunityId($steamid32)
    {
        // Convert STEAM_0:X:Y to community ID format
        if (preg_match('/^STEAM_0:([01]):(\d+)$/', $steamid32, $matches)) {
            $authServer = $matches[1];
            $authId = $matches[2];
            return ($authId * 2) + $authServer;
        }
        return null;
    }

    // Accessors
    public function getUnbanDateHumanAttribute()
    {
        if ($this->unban_date == 0) {
            return null;
        }
        return Carbon::createFromTimestamp($this->unban_date);
    }

    public function getIsActiveAttribute()
    {
        if ($this->unban_date == 0) {
            return true; // Permanent ban
        }
        return $this->unban_date > time();
    }

    public function getIsExpiredAttribute()
    {
        return $this->unban_date > 0 && $this->unban_date <= time();
    }

    public function getIsPermanentAttribute()
    {
        return $this->unban_date == 0;
    }

    public function getTimeRemainingAttribute()
    {
        if ($this->is_permanent || !$this->is_active) {
            return null;
        }
        return Carbon::createFromTimestamp($this->unban_date)->diffForHumans();
    }

    public function getBanLengthAttribute()
    {
        if ($this->is_permanent) {
            return 'Permanent';
        }
        
        if ($this->unban_date <= time()) {
            return 'Expired';
        }
        
        return $this->time_remaining;
    }

    public function getStatusAttribute()
    {
        if ($this->is_active) {
            return $this->is_permanent ? 'permanent' : 'active';
        }
        return 'expired';
    }

    public function getStatusBadgeClassAttribute()
    {
        switch ($this->status) {
            case 'permanent':
                return 'danger';
            case 'active':
                return 'warning';
            case 'expired':
                return 'secondary';
            default:
                return 'secondary';
        }
    }

    public function getSteamid64Attribute()
    {
        return self::steamid32To64($this->steamid);
    }

    public function getPlayerNameAttribute()
    {
        // Try to get player name from sam_players table if it exists
        try {
            $player = \DB::connection('sambans')
                ->table('sam_players')
                ->where('steamid', $this->steamid)
                ->first();
            
            return $player ? $player->name : $this->extractNameFromSteamId();
        } catch (\Exception $e) {
            return $this->extractNameFromSteamId();
        }
    }

    public function getAdminNameAttribute()
    {
        if ($this->admin === 'Console') {
            return 'Console';
        }

        // Try to get admin name from sam_players table
        try {
            $admin = \DB::connection('sambans')
                ->table('sam_players')
                ->where('steamid', $this->admin)
                ->first();
            
            return $admin ? $admin->name : $this->admin;
        } catch (\Exception $e) {
            return $this->admin;
        }
    }

    private function extractNameFromSteamId()
    {
        // Extract a simple identifier from SteamID for display
        if (preg_match('/^STEAM_0:[01]:(\d+)$/', $this->steamid, $matches)) {
            return "Player #" . $matches[1];
        }
        return $this->steamid;
    }

    public function getSteamProfileUrlAttribute()
    {
        $steamid64 = $this->steamid64;
        if ($steamid64) {
            return "https://steamcommunity.com/profiles/{$steamid64}";
        }
        return null;
    }

    public function getFormattedReasonAttribute()
    {
        return $this->reason ?: 'No reason specified';
    }
}