<?php

abstract class AbstractPdo {

    protected $pdo;
    protected $table;
    protected $primaryKey = 'id';
    protected $env = 'dev';



    public function __construct() {

        if($this->env == "dev"){
            $host = "localhost";
            $dbname = "est";
            $username = "root";
            $password = "";
        }else  if($this->env == "prod"){
            $host = "127.0.0.1";
            $dbname = "azurmini_est";
            $username = "azurmini_est";
            $password = "Tky+pF4W}tV,j;yd";
        }

        try {
            $this->pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            // Bach n-choufo l'erreur exact ila kant f l'ecran
            die("Erreur de connexion à la base de données : " . $e->getMessage());
        }
    }

    // --- Les méthodes de base pour que le Service fonctionne ---
    public function findOne($id) {
        $stmt = $this->pdo->prepare("SELECT * FROM {$this->table} WHERE {$this->primaryKey} = ?");
        $stmt->execute([$id]);
        return $stmt->fetch();
    }

    public function findOneBy($criteria) {
        $where = [];
        $params = [];
        foreach ($criteria as $key => $value) {
            $where[] = "$key = ?";
            $params[] = $value;
        }
        $sql = "SELECT * FROM {$this->table} WHERE " . implode(' AND ', $where);
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetch();
    }

    public function findAllBy($criteria = [], $orderBy = null) {
        $sql = "SELECT * FROM {$this->table}";
        $params = [];

        if (!empty($criteria)) {
            $where = [];
            foreach ($criteria as $field => $value) {
                $where[] = "$field = ?";
                $params[] = $value;
            }
            $sql .= " WHERE " . implode(' AND ', $where);
        }

        if ($orderBy) {
            $sql .= " ORDER BY $orderBy";
        }

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll();
    }

    public function findMultiple($filters = [], $orderBy = null, $limit = null, $offset = null) {
        $sql = "SELECT * FROM {$this->table}";
        $params = [];

        if (!empty($filters)) {
            $where = [];
            foreach ($filters as $field => $config) {
                if (is_array($config) && isset($config['like'])) {
                    $where[] = "$field LIKE ?";
                    $params[] = "%" . $config['value'] . "%";
                } else {
                    $where[] = "$field = ?";
                    $params[] = $config;
                }
            }
            $sql .= " WHERE " . implode(' AND ', $where);
        }

        if ($orderBy) { $sql .= " ORDER BY $orderBy"; }
        if ($limit) { $sql .= " LIMIT $limit"; }
        if ($offset) { $sql .= " OFFSET $offset"; }

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll();
    }

    /**
     * Find all records
     */
    public function findAll($orderBy = null) {
        return $this->findMultiple([], $orderBy);
    }

    /**
     * Execute a query (INSERT, UPDATE, DELETE)
     */
    public function execute($sql, $params = []) {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt;
    }

    /**
     * Insert a record
     */
    public function insert($data) {
        $keys = array_keys($data);
        $fields = implode(', ', $keys);
        $placeholders = ':' . implode(', :', $keys);
        $sql = "INSERT INTO {$this->table} ({$fields}) VALUES ({$placeholders})";

        $params = [];
        foreach ($data as $key => $value) {
            $params[":{$key}"] = $value;
        }

        $this->execute($sql, $params);
        return $this->pdo->lastInsertId();
    }

    /**
     * Update a record
     */
    public function update($id, $data) {
        $sets = [];
        $params = [];
        foreach ($data as $key => $value) {
            $sets[] = "{$key} = :{$key}";
            $params[":{$key}"] = $value;
        }
        $params[":id"] = $id;
        $sql = "UPDATE {$this->table} SET " . implode(', ', $sets) . " WHERE {$this->primaryKey} = :id";
        return $this->execute($sql, $params);
    }

    /**
     * Delete a record
     */
    public function delete($id) {
        $sql = "DELETE FROM {$this->table} WHERE {$this->primaryKey} = :id";
        return $this->execute($sql, [':id' => $id]);
    }


    /**
     * Count records with optional filters
     */
    public function count($filters = []) {
        $sql = "SELECT COUNT(*) FROM {$this->table}";
        $params = [];

        if (!empty($filters)) {
            $where = [];
            foreach ($filters as $field => $config) {
                if (is_array($config) && isset($config['like'])) {
                    $where[] = "$field LIKE ?";
                    $params[] = "%" . $config['value'] . "%";
                } else {
                    $where[] = "$field = ?";
                    $params[] = $config;
                }
            }
            $sql .= " WHERE " . implode(' AND ', $where);
        }

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return (int)$stmt->fetchColumn();
    }

}
