<?php

abstract class Model {
    protected PDO $db;
    protected string $table;

    public function __construct() {
        $this->db = Database::getInstance();
    }

    public function findAll(string $orderBy = 'id DESC'): array {
        $stmt = $this->db->prepare("SELECT * FROM {$this->table} ORDER BY {$orderBy}");
        $stmt->execute();
        return $stmt->fetchAll();
    }

    public function findById(int $id): ?array {
        $stmt = $this->db->prepare("SELECT * FROM {$this->table} WHERE id = :id LIMIT 1");
        $stmt->execute(['id' => $id]);
        $result = $stmt->fetch();
        return $result ?: null;
    }

    public function findWhere(array $conditions, string $orderBy = 'id DESC'): array {
        $whereClauses = [];
        $params = [];
        foreach ($conditions as $col => $val) {
            $whereClauses[] = "{$col} = :{$col}";
            $params[$col] = $val;
        }
        $whereSql = implode(' AND ', $whereClauses);
        $stmt = $this->db->prepare("SELECT * FROM {$this->table} WHERE {$whereSql} ORDER BY {$orderBy}");
        $stmt->execute($params);
        return $stmt->fetchAll();
    }

    public function findOneWhere(array $conditions): ?array {
        $whereClauses = [];
        $params = [];
        foreach ($conditions as $col => $val) {
            $whereClauses[] = "{$col} = :{$col}";
            $params[$col] = $val;
        }
        $whereSql = implode(' AND ', $whereClauses);
        $stmt = $this->db->prepare("SELECT * FROM {$this->table} WHERE {$whereSql} LIMIT 1");
        $stmt->execute($params);
        $result = $stmt->fetch();
        return $result ?: null;
    }

    public function create(array $data): int {
        $fields = array_keys($data);
        $placeholders = array_map(fn($f) => ":{$f}", $fields);

        $sql = "INSERT INTO {$this->table} (" . implode(', ', $fields) . ") VALUES (" . implode(', ', $placeholders) . ")";
        $stmt = $this->db->prepare($sql);
        $stmt->execute($data);
        return (int)$this->db->lastInsertId();
    }

    public function update(int $id, array $data): bool {
        $setClauses = [];
        foreach ($data as $col => $val) {
            $setClauses[] = "{$col} = :{$col}";
        }
        $data['id'] = $id;
        $sql = "UPDATE {$this->table} SET " . implode(', ', $setClauses) . " WHERE id = :id";
        $stmt = $this->db->prepare($sql);
        return $stmt->execute($data);
    }

    public function delete(int $id): bool {
        $stmt = $this->db->prepare("DELETE FROM {$this->table} WHERE id = :id");
        return $stmt->execute(['id' => $id]);
    }
}
