<?php
/**
 * Auth & User Repository.
 * Tüm kullanıcı işlemleri (kayıt, giriş, sorgu, güncelleme) burada.
 */

class User
{
    /** Kullanıcı kayıt et — başarılı ise yeni user_id döner */
    public static function register(string $name, string $password, string $email, int $race): int
    {
        $hash = hash_password($password);
        DB::execute(
            "INSERT INTO users (name, pass_hash, email, race, gold, hp_now, created_at, last_active)
             VALUES (:name, :pass, :email, :race, :gold, :hp, :now, :now2)",
            [
                ':name'  => $name,
                ':pass'  => $hash,
                ':email' => $email,
                ':race'  => $race,
                ':gold'  => GAME_START_GOLD,
                ':hp'    => GAME_START_HP,
                ':now'   => time(),
                ':now2'  => time(),
            ]
        );
        return DB::lastInsertId();
    }

    /** İsme göre kullanıcı bul */
    public static function findByName(string $name): ?array
    {
        return DB::fetchOne("SELECT * FROM users WHERE name = :n", [':n' => $name]);
    }

    /** E-posta'ya göre kullanıcı bul */
    public static function findByEmail(string $email): ?array
    {
        return DB::fetchOne("SELECT * FROM users WHERE email = :e", [':e' => $email]);
    }

    /** ID'ye göre kullanıcı bul */
    public static function findById(int $id): ?array
    {
        return DB::fetchOne("SELECT * FROM users WHERE id = :i", [':i' => $id]);
    }

    /** Login dener — başarılı ise user array döner, değilse null */
    public static function authenticate(string $name, string $password): ?array
    {
        $user = self::findByName($name);
        if (!$user) return null;
        if (!verify_password($password, $user['pass_hash'])) return null;
        return $user;
    }

    /** Bir kullanıcıyı session'a kaydet (giriş yap) */
    public static function loginSession(array $user): void
    {
        // Session fixation engelle
        session_regenerate_id(true);
        $_SESSION['user_id']  = (int)$user['id'];
        $_SESSION['user_name'] = $user['name'];
        $_SESSION['is_admin'] = (int)($user['is_admin'] ?? 0) === 1;
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));

        // last_active güncelle
        DB::execute(
            "UPDATE users SET last_active = :t WHERE id = :i",
            [':t' => time(), ':i' => $user['id']]
        );
    }

    /** Çıkış yap */
    public static function logout(): void
    {
        $_SESSION = [];
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
        }
        session_destroy();
    }

    /** Mevcut giriş yapmış kullanıcının verilerini DB'den taze çek */
    public static function current(): ?array
    {
        if (!is_logged_in()) return null;
        $user = self::findById((int)$_SESSION['user_id']);
        if ($user) {
            // Hesaplanmış alanlar ekle
            $user['level']    = self::calculateLevel((int)$user['exp']);
            $user['hp_max']   = self::calculateMaxHp($user['level']);
            $user['exp_need'] = self::expForLevel($user['level'] + 1) - $user['exp'];
        }
        return $user;
    }

    /** Tecrübeden seviye hesapla — basit log formülü */
    public static function calculateLevel(int $exp): int
    {
        if ($exp <= 0) return 1;
        // Toplam exp'e karşılık gelen seviye: floor(sqrt(exp/100)) + 1
        return (int) floor(sqrt($exp / 100)) + 1;
    }

    /** Bir seviyeye ulaşmak için gereken toplam tecrübe */
    public static function expForLevel(int $level): int
    {
        if ($level <= 1) return 0;
        return (int) (pow($level - 1, 2) * 100);
    }

    /** Max HP hesapla */
    public static function calculateMaxHp(int $level): int
    {
        return 100 + ($level - 1) * 20;
    }

    /** Kullanıcının kuşandığı + envanterindeki itemleri döner */
    public static function items(int $userId): array
    {
        return DB::fetchAll(
            "SELECT ui.id AS user_item_id, ui.equipped, ui.acquired_at,
                    i.id, i.name, i.category, i.required_level, i.cost_gold, i.cost_hellstones,
                    i.bonus_pow, i.bonus_def, i.bonus_agi, i.bonus_stam, i.bonus_chr
             FROM user_items ui
             JOIN items i ON ui.item_id = i.id
             WHERE ui.user_id = :u
             ORDER BY ui.equipped DESC, ui.acquired_at DESC",
            [':u' => $userId]
        );
    }

    /** Tüm bonusları toplayıp efektif statları hesapla */
    public static function effectiveStats(array $user): array
    {
        $items = self::items((int)$user['id']);
        $stats = [
            'pow'  => (int)$user['ab_pow'],
            'def'  => (int)$user['ab_def'],
            'agi'  => (int)$user['ab_agi'],
            'stam' => (int)$user['ab_stam'],
            'chr'  => (int)$user['ab_chr'],
        ];
        foreach ($items as $it) {
            if ((int)$it['equipped'] !== 1) continue;
            $stats['pow']  += (int)$it['bonus_pow'];
            $stats['def']  += (int)$it['bonus_def'];
            $stats['agi']  += (int)$it['bonus_agi'];
            $stats['stam'] += (int)$it['bonus_stam'];
            $stats['chr']  += (int)$it['bonus_chr'];
        }
        return $stats;
    }
}
