<?php
// app/Models/BaseRepository.php
namespace App\Models;

use App\Core\Database;

/**
 * Základní repository poskytující mapování řádku na entity.
 * Postup: potomci předají do parent konstruktoru název tabulky a třídu entity.
 */
abstract class BaseRepository
{
    protected \PDO $pdo;
    protected string $table;
    protected string $entityClass;

    public function __construct(Database $db, string $table, string $entityClass)
    {
        $this->pdo = $db->pdo();
        $this->table = $table;
        $this->entityClass = $entityClass;
    }

    public function getPdo(): \PDO
    {
        return $this->pdo;
    }

    /**
     * Mapuje asociativní pole (řádek z DB) na instanci entity.
     * Používá metodu fill() v App\Core\Model.
     *
     * @param array $row
     * @return object instance třídy $this->entityClass
     */
    protected function mapRowToEntity(array $row)
    {
        $class = $this->entityClass;
        $entity = new $class();
        if (method_exists($entity, 'fill')) {
            $entity->fill($row);
        } else {
            // fallback: při chybě nastavíme vlastnosti dynamicky
            foreach ($row as $k => $v) {
                $entity->$k = $v;
            }
        }
        return $entity;
    }

    /**
     * Vrátí pole entit.
     *
     * @return array<object>
     */
    public function findAll(): array
    {
        $stmt = $this->pdo->query("SELECT * FROM `" . $this->table . "`");
        $rows = $stmt->fetchAll();
        return array_map(fn($r) => $this->mapRowToEntity($r), $rows);
    }

    /**
     * Najde entitu podle ID, nebo vrátí null.
     *
     * @param int $id
     * @return object|null
     */
    public function find(int $id)
    {
        $stmt = $this->pdo->prepare("SELECT * FROM `" . $this->table . "` WHERE id = :id LIMIT 1");
        $stmt->execute(['id' => $id]);
        $row = $stmt->fetch();
        return $row ? $this->mapRowToEntity($row) : null;
    }

    /**
     * Smaže záznam podle ID.
     */
    public function delete(int $id): bool
    {
        $stmt = $this->pdo->prepare("DELETE FROM `" . $this->table . "` WHERE id = :id");
        return $stmt->execute(['id' => $id]);
    }

    public function insert(array $data): bool
    {
        $columns = array_keys($data);
        $placeholders = array_map(fn($c) => ':' . $c, $columns);

        $sql = sprintf(
            "INSERT INTO %s (%s) VALUES (%s)",
            $this->table,
            implode(', ', $columns),
            implode(', ', $placeholders)
        );

        $stmt = $this->pdo->prepare($sql);

        foreach ($data as $key => $value) {
            $stmt->bindValue(':' . $key, $value);
        }

        return $stmt->execute();
    }
}