<?php
class PdoCrud {
    private $pdo;
    private $table;
    private $primaryKey;

    public function __construct($pdo, $table, $primaryKey = 'id') {
        $this->pdo = $pdo;
        $this->table = $table;
        $this->primaryKey = $primaryKey;
    }

    public function create($data) {
        if (empty($data)) {
            throw new Exception("No data provided for creation.");
        }
    
        $fields = array_keys($data);
        $placeholders = array_map(fn($f) => ":$f", $fields);
        $sql = "INSERT INTO {$this->table} (" . implode(',', $fields) . ") VALUES (" . implode(',', $placeholders) . ")";
    
        $stmt = $this->pdo->prepare($sql);
    
        foreach ($data as $k => $v) {
            $stmt->bindValue(":$k", $v);
        }
    
        if (!$stmt->execute()) {
            $errorInfo = $stmt->errorInfo();
            throw new Exception("Database error [{$errorInfo[0]}]: {$errorInfo[2]}");
        }
    
        return $this->pdo->lastInsertId();
    }
    

    public function read($id) {
        $sql = "SELECT * FROM {$this->table} WHERE {$this->primaryKey} = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':id' => $id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    public function update($id, $data) {
        $fields = array_keys($data);
        $set = implode(', ', array_map(fn($f) => "$f = :$f", $fields));
        $sql = "UPDATE {$this->table} SET $set WHERE {$this->primaryKey} = :id";
        $stmt = $this->pdo->prepare($sql);
        $data['id'] = $id;
        foreach ($data as $k => $v) {
            $stmt->bindValue(":$k", $v);
        }
        return $stmt->execute();
    }

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

    public function list($filters = [], $limit = 100, $offset = 0) {
        $sql = "SELECT * FROM {$this->table}";
        $params = [];
        
        // Add WHERE clause if filters exist
        if (!empty($filters)) {
            $where = [];
            foreach ($filters as $field => $value) {
                $where[] = "$field = :$field";
                $params[":$field"] = $value;
            }
            $sql .= " WHERE " . implode(' AND ', $where);
        }
        
        // Add pagination
        $sql .= " LIMIT :offset, :limit";
        $params[':offset'] = (int)$offset;
        $params[':limit'] = (int)$limit;
        
        $stmt = $this->pdo->prepare($sql);
        
        // Bind all parameters
        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
        }
        
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}
