<?php
// app/Models/TeamRepository.php
// Repozitář pro správu týmů a jejich členů – CRUD na tabulkách tymy a clenove_tymu.

namespace App\Models;

use App\Core\Database;
use App\Models\Entities\TeamEntity;

/**
 * Poskytuje metody pro čtení a zápis týmů a členství.
 * Dědí základní find/findAll/delete z BaseRepository.
 */
class TeamRepository extends BaseRepository
{
    public function __construct(Database $db)
    {
        parent::__construct($db, 'tymy', TeamEntity::class);
    }

    /**
     * Vytvoří nový tým a automaticky přidá tvůrce jako trenéra.
     * Vrátí ID nového týmu.
     */
    public function create(array $data, ?int $userId = null): int
    {
        $stmt = $this->pdo->prepare(
            "INSERT INTO tymy (nazev, popis)
             VALUES (:nazev, :popis)"
        );

        $stmt->execute([
            'nazev' => $data['nazev'],
            'popis' => $data['popis'] ?? null
        ]);

        $teamId = (int)$this->pdo->lastInsertId();

        // Přidej tvůrce jako trenéra do týmu
        if ($userId !== null) {
            $this->addMember($teamId, $userId, 'trener');
        }

        return $teamId;
    }

    /** Aktualizuje název a/nebo popis týmu. Přeskočí pole, která nejsou v $data. */
    public function update(int $id, array $data): bool
    {
        $fields = [];
        $bindings = ['id' => $id];

        foreach (['nazev', 'popis'] as $field) {
            if (isset($data[$field])) {
                $fields[] = "$field = :$field";
                $bindings[$field] = $data[$field];
            }
        }

        if (empty($fields)) {
            return true;
        }

        $sql = "UPDATE tymy SET " . implode(', ', $fields) . " WHERE id = :id";
        return $this->pdo->prepare($sql)->execute($bindings);
    }

    /** Smaže tým. Cascade v DB se postará o smazání členů a dalších navázaných záznamů. */
    public function delete(int $id): bool
    {
        $stmt = $this->pdo->prepare("DELETE FROM tymy WHERE id = :id");
        return $stmt->execute(['id' => $id]);
    }

    /** Vrátí všechny členy týmu seřazené trenéři první, pak abecedně. */
    public function getMembers(int $teamId): array
    {
        $stmt = $this->pdo->prepare(
            "SELECT u.id, u.uzivatelske_jmeno, u.jmeno, u.prijmeni, u.role, ct.role_v_tymu, ct.id as clenstvo_id
             FROM uzivatele u
             JOIN clenove_tymu ct ON u.id = ct.uzivatel_id
             WHERE ct.tym_id = :tym_id
             ORDER BY ct.role_v_tymu DESC, u.jmeno ASC"
        );
        $stmt->execute(['tym_id' => $teamId]);
        return $stmt->fetchAll();
    }

    /** Přidá uživatele do týmu s danou rolí (hrac / trener / asistent). */
    public function addMember(int $teamId, int $userId, string $roleInTeam = 'hrac'): bool
    {
        $stmt = $this->pdo->prepare(
            "INSERT INTO clenove_tymu (tym_id, uzivatel_id, role_v_tymu)
             VALUES (:tym_id, :uzivatel_id, :role_v_tymu)"
        );
        return $stmt->execute([
            'tym_id' => $teamId,
            'uzivatel_id' => $userId,
            'role_v_tymu' => $roleInTeam
        ]);
    }

    /** Odebere člena z týmu podle ID záznamu v clenove_tymu (ne ID uživatele). */
    public function removeMember(int $membershipId): bool
    {
        $stmt = $this->pdo->prepare("DELETE FROM clenove_tymu WHERE id = :id");
        return $stmt->execute(['id' => $membershipId]);
    }

    /** Vrátí uživatele, kteří ještě nejsou členy daného týmu. */
    public function getAvailableUsers(int $teamId): array
    {
        $stmt = $this->pdo->prepare(
            "SELECT id, uzivatelske_jmeno, jmeno, prijmeni, role 
             FROM uzivatele 
             WHERE id NOT IN (
                 SELECT uzivatel_id FROM clenove_tymu WHERE tym_id = :tym_id
             )
             ORDER BY jmeno ASC"
        );
        $stmt->execute(['tym_id' => $teamId]);
        return $stmt->fetchAll();
    }

    /** Vrátí týmy, ve kterých je uživatel členem (jako entity). */
    public function getTeamsForUser(int $userId): array
    {
        $stmt = $this->pdo->prepare(
            "SELECT DISTINCT t.* FROM tymy t
             JOIN clenove_tymu ct ON t.id = ct.tym_id
             WHERE ct.uzivatel_id = :uzivatel_id
             ORDER BY t.nazev ASC"
        );
        $stmt->execute(['uzivatel_id' => $userId]);
        return $this->mapRowsToEntities($stmt->fetchAll());
    }

    /** Vrátí týmy uživatele i s jeho rolí v každém týmu (jako pole, ne entity). */
    public function getTeamsForUserWithRole(int $userId): array
    {
        $stmt = $this->pdo->prepare(
            "SELECT t.id, t.nazev, t.popis, ct.role_v_tymu
             FROM tymy t
             JOIN clenove_tymu ct ON t.id = ct.tym_id
             WHERE ct.uzivatel_id = :uzivatel_id
             ORDER BY t.nazev ASC"
        );
        $stmt->execute(['uzivatel_id' => $userId]);
        return $stmt->fetchAll(\PDO::FETCH_ASSOC);
    }

    /** Interní pomocník – převede pole řádků z DB na pole entit. */
    private function mapRowsToEntities(array $rows): array
    {
        return array_map(fn($row) => $this->mapRowToEntity($row), $rows);
    }

    /** Vrátí true, pokud je uživatel členem týmu (v jakékoli roli). */
    public function isUserMember(int $teamId, int $userId): bool
    {
        $stmt = $this->pdo->prepare(
            "SELECT COUNT(*) as cnt FROM clenove_tymu WHERE tym_id = :tym_id AND uzivatel_id = :uzivatel_id"
        );
        $stmt->execute(['tym_id' => $teamId, 'uzivatel_id' => $userId]);
        $result = $stmt->fetch(\PDO::FETCH_ASSOC);
        return (int)($result['cnt'] ?? 0) > 0;
    }

    /**
     * Vrátí roli uživatele v týmu, nebo null pokud není členem
     */
    public function getUserTeamRole(int $teamId, int $userId): ?string
    {
        $stmt = $this->pdo->prepare(
            "SELECT role_v_tymu FROM clenove_tymu WHERE tym_id = :tym_id AND uzivatel_id = :uzivatel_id"
        );
        $stmt->execute(['tym_id' => $teamId, 'uzivatel_id' => $userId]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
        return $row ? $row['role_v_tymu'] : null;
    }

    /**
     * Vrátí počet členů v týmu
     */
    public function getMemberCount(int $teamId): int
    {
        $stmt = $this->pdo->prepare(
            "SELECT COUNT(*) as cnt FROM clenove_tymu WHERE tym_id = :tym_id"
        );
        $stmt->execute(['tym_id' => $teamId]);
        $result = $stmt->fetch(\PDO::FETCH_ASSOC);
        return (int)($result['cnt'] ?? 0);
    }
}
