<?php
// app/Models/AnketaRepository.php
// repozitář pro ankety – CRUD, hlasování, automatické uzavírání po 48 hodinách.

namespace App\Models;

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

class AnketaRepository extends BaseRepository
{
    public function __construct(Database $db)
    {
        parent::__construct($db, 'ankety', AnketaEntity::class);
    }

    /**
     * získá všechny ankety pro tým s možnostmi a počtem hlasů
     */
    public function getByTeamId(int $teamId, bool $activeOnly = false): array
    {
        $sql = "SELECT * FROM `ankety` WHERE `tym_id` = ?";
        if ($activeOnly) {
            $sql .= " AND `aktivni` = 1";
        }
        $sql .= " ORDER BY `datum_vytvoreni` DESC";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([$teamId]);
        
        $ankety = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        
        // Pro každou anketu připojí možnosti s počtem hlasů a zkontroluje zda není starší jak 48 hodin
        foreach ($ankety as &$anketa) {
            // Zkontrolovat a uzavřít anketu, pokud je stará více než 48 hodin
            $this->checkAndCloseExpired($anketa['id']);
            
            $optionsStmt = $this->pdo->prepare(
                "SELECT * FROM `anketa_moznosti` WHERE `anketa_id` = ? ORDER BY `id`"
            );
            $optionsStmt->execute([$anketa['id']]);
            $anketa['options'] = $optionsStmt->fetchAll(\PDO::FETCH_ASSOC);
            
            // Počet hlasů pro každou možnost
            foreach ($anketa['options'] as &$option) {
                $votesStmt = $this->pdo->prepare(
                    "SELECT COUNT(*) as total FROM `anketa_hlasy` WHERE `moznost_id` = ?"
                );
                $votesStmt->execute([$option['id']]);
                $result = $votesStmt->fetch(\PDO::FETCH_ASSOC);
                $option['votes_count'] = (int)($result['total'] ?? 0);
            }
        }
        
        return $ankety;
    }

    /**
     * Získá anketu s všemi možnostmi a hlasy
     */
    public function getResults(int $pollId): array
    {
        // zkontroluje zdaje anketa starší než 48 hodin a pří padně ji uzavře
        $this->checkAndCloseExpired($pollId);

        $poll = $this->find($pollId);
        if (!$poll) return [];

        $poll = (array)$poll;
        
        // získá možnosti
        $optionsStmt = $this->pdo->prepare(
            "SELECT * FROM `anketa_moznosti` WHERE `anketa_id` = ? ORDER BY `id`"
        );
        $optionsStmt->execute([$pollId]);
        $poll['options'] = $optionsStmt->fetchAll(\PDO::FETCH_ASSOC);

        // získá hlasy pro každou možnost
        foreach ($poll['options'] as &$option) {
            $votesStmt = $this->pdo->prepare(
                "SELECT COUNT(*) as total FROM `anketa_hlasy` WHERE `moznost_id` = ?"
            );
            $votesStmt->execute([$option['id']]);
            $result = $votesStmt->fetch(\PDO::FETCH_ASSOC);
            $option['votes_count'] = (int)($result['total'] ?? 0);
        }

        return $poll;
    }

    /**
     * Zjistí, jestli uživatel už hlasoval
     */
    public function hasUserVoted(int $pollId, int $userId): bool
    {
        $stmt = $this->pdo->prepare(
            "SELECT COUNT(*) as cnt FROM `anketa_hlasy` WHERE `anketa_id` = ? AND `uzivatel_id` = ?"
        );
        $stmt->execute([$pollId, $userId]);
        $result = $stmt->fetch(\PDO::FETCH_ASSOC);
        return (int)($result['cnt'] ?? 0) > 0;
    }

    /**
     * Uloží hlas uživatele v anketě
     */
    public function vote(int $pollId, int $optionId, int $userId): bool
    {
        // Zkontrolovat, že možnost patří do ankety
        $stmt = $this->pdo->prepare(
            "SELECT COUNT(*) as cnt FROM `anketa_moznosti` 
             WHERE `id` = ? AND `anketa_id` = ?"
        );
        $stmt->execute([$optionId, $pollId]);
        $result = $stmt->fetch(\PDO::FETCH_ASSOC);
        
        if ((int)($result['cnt'] ?? 0) === 0) {
            return false;
        }

        // Odstranit starý hlas
        $deleteStmt = $this->pdo->prepare(
            "DELETE FROM `anketa_hlasy` WHERE `anketa_id` = ? AND `uzivatel_id` = ?"
        );
        $deleteStmt->execute([$pollId, $userId]);

        // Přidat nový hlas
        $voteStmt = $this->pdo->prepare(
            "INSERT INTO `anketa_hlasy` (`anketa_id`, `moznost_id`, `uzivatel_id`) VALUES (?, ?, ?)"
        );
        return $voteStmt->execute([$pollId, $optionId, $userId]);
    }

    /**
     * Vytvoří novou anketu s možnostmi
     */
    public function createWithOptions(
        int $teamId,
        string $title,
        int $creatorId,
        array $options
    ): int {
        try {
            $this->pdo->beginTransaction();

            // Vytvořit anketu
            $stmt = $this->pdo->prepare(
                "INSERT INTO `ankety` (`tym_id`, `nazev`, `vytvoril_uzivatel_id`, `aktivni`)
                 VALUES (?, ?, ?, 1)"
            );
            $stmt->execute([$teamId, $title, $creatorId]);
            $pollId = (int)$this->pdo->lastInsertId();

            // Vytvořit možnosti
            $optStmt = $this->pdo->prepare(
                "INSERT INTO `anketa_moznosti` (`anketa_id`, `text_moznost`) VALUES (?, ?)"
            );
            
            foreach ($options as $option) {
                $optStmt->execute([$pollId, $option]);
            }

            $this->pdo->commit();
            return $pollId;
        } catch (\Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Deaktivuje anketu
     */
    public function deactivate(int $pollId): bool
    {
        $stmt = $this->pdo->prepare("UPDATE `ankety` SET `aktivni` = 0 WHERE `id` = ?");
        return $stmt->execute([$pollId]);
    }

    /**
     * Zjistí, jak uživatel hlasoval v anketě
     */
    public function getUserVote(int $pollId, int $userId): ?int
    {
        $stmt = $this->pdo->prepare(
            "SELECT `moznost_id` FROM `anketa_hlasy` 
             WHERE `anketa_id` = ? AND `uzivatel_id` = ? LIMIT 1"
        );
        $stmt->execute([$pollId, $userId]);
        $result = $stmt->fetch(\PDO::FETCH_ASSOC);
        
        return $result ? (int)$result['moznost_id'] : null;
    }

    /**
     * Zkontroluje, zda je anketa stará více než 48 hodin, a pokud ano, automaticky ji uzavře
     */
    public function checkAndCloseExpired(int $pollId): bool
    {
        $stmt = $this->pdo->prepare(
            "SELECT `datum_vytvoreni`, `aktivni` FROM `ankety` WHERE `id` = ?"
        );
        $stmt->execute([$pollId]);
        $poll = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$poll || !$poll['aktivni']) {
            return false;
        }

        // Zkontrolovat, zda je anketa starší než 48 hodin
        $createdTime = strtotime($poll['datum_vytvoreni']);
        $now = time();
        $ageInHours = ($now - $createdTime) / 3600;

        if ($ageInHours >= 48) {
            $this->deactivate($pollId);
            return true;
        }

        return false;
    }
}
