<?php
/**
 * Configuração da Base de Dados SQLite
 * Este ficheiro contém a lógica para estabelecer conexão com a base de dados SQLite
 */

class Database {
    private $db_path;
    private $pdo;
    
    public function __construct() {
        // Caminho para a base de dados SQLite
        $this->db_path = __DIR__ . '/../database/app.db';
        $this->connect();
        $this->createTables();
    }
    
    /**
     * Estabelece conexão com a base de dados SQLite
     */
    private function connect() {
        try {
            $this->pdo = new PDO('sqlite:' . $this->db_path);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            die('Erro de conexão com a base de dados: ' . $e->getMessage());
        }
    }
    
    /**
     * Cria as tabelas necessárias se não existirem
     */
    private function createTables() {
        $sql = "
            CREATE TABLE IF NOT EXISTS product_exits (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                product_name TEXT NOT NULL,
                quantity INTEGER NOT NULL,
                exit_date DATE NOT NULL,
                exit_time TIME NOT NULL,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP
            );
            
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT NOT NULL UNIQUE,
                password TEXT NOT NULL,
                role TEXT NOT NULL CHECK(role IN ('admin', 'cozinha', 'lanchonete')),
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP
            );
            
            CREATE TABLE IF NOT EXISTS products (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL UNIQUE,
                stock INTEGER NOT NULL DEFAULT 0,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
            );
            
            CREATE TABLE IF NOT EXISTS stock_returns (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                product_id INTEGER NOT NULL,
                quantity INTEGER NOT NULL,
                user_id INTEGER NOT NULL,
                reason TEXT,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY (product_id) REFERENCES products(id),
                FOREIGN KEY (user_id) REFERENCES users(id)
            );
        ";
        
        try {
            $this->pdo->exec($sql);
            
            // Criar utilizador admin padrão se não existir
            $this->createDefaultAdmin();
        } catch (PDOException $e) {
            die('Erro ao criar tabelas: ' . $e->getMessage());
        }
    }
    
    /**
     * Cria utilizador admin padrão se não existir
     */
    private function createDefaultAdmin() {
        $sql = "SELECT COUNT(*) FROM users WHERE role = 'admin'";
        $stmt = $this->pdo->query($sql);
        $adminCount = $stmt->fetchColumn();
        
        if ($adminCount == 0) {
            $this->addUser('admin', 'admin123', 'admin');
        }
    }
    
    // ========== MÉTODOS PARA UTILIZADORES ==========
    
    /**
     * Adiciona um novo utilizador
     */
    public function addUser($username, $password, $role) {
        $sql = "INSERT INTO users (username, password, role) VALUES (:username, :password, :role)";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                ':username' => $username,
                ':password' => password_hash($password, PASSWORD_DEFAULT),
                ':role' => $role
            ]);
            
            return $this->getUserById($this->pdo->lastInsertId());
        } catch (PDOException $e) {
            throw new Exception('Erro ao adicionar utilizador: ' . $e->getMessage());
        }
    }
    
    /**
     * Obtém um utilizador pelo ID
     */
    public function getUserById($id) {
        $sql = "SELECT id, username, role, created_at FROM users WHERE id = :id";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([':id' => $id]);
            return $stmt->fetch();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter utilizador: ' . $e->getMessage());
        }
    }
    
    /**
     * Obtém um utilizador pelo username
     */
    public function getUserByUsername($username) {
        $sql = "SELECT * FROM users WHERE username = :username";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([':username' => $username]);
            return $stmt->fetch();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter utilizador: ' . $e->getMessage());
        }
    }
    
    /**
     * Obtém todos os utilizadores
     */
    public function getAllUsers() {
        $sql = "SELECT id, username, role, created_at FROM users ORDER BY created_at DESC";
        
        try {
            $stmt = $this->pdo->query($sql);
            return $stmt->fetchAll();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter utilizadores: ' . $e->getMessage());
        }
    }
    
    /**
     * Remove um utilizador
     */
    public function deleteUser($id) {
        $sql = "DELETE FROM users WHERE id = :id AND role != 'admin'";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([':id' => $id]);
            return $stmt->rowCount() > 0;
        } catch (PDOException $e) {
            throw new Exception('Erro ao remover utilizador: ' . $e->getMessage());
        }
    }
    
    /**
     * Verifica as credenciais do utilizador
     */
    public function authenticateUser($username, $password) {
        $user = $this->getUserByUsername($username);
        
        if ($user && password_verify($password, $user['password'])) {
            return [
                'id' => $user['id'],
                'username' => $user['username'],
                'role' => $user['role']
            ];
        }
        
        return false;
    }
    
    // ========== MÉTODOS PARA PRODUTOS ==========
    
    /**
     * Adiciona um novo produto
     */
    public function addProduct($name, $stock = 0) {
        $sql = "INSERT INTO products (name, stock) VALUES (:name, :stock)";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                ':name' => $name,
                ':stock' => $stock
            ]);
            
            return $this->getProductById($this->pdo->lastInsertId());
        } catch (PDOException $e) {
            throw new Exception('Erro ao adicionar produto: ' . $e->getMessage());
        }
    }
    
    /**
     * Obtém um produto pelo ID
     */
    public function getProductById($id) {
        $sql = "SELECT * FROM products WHERE id = :id";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([':id' => $id]);
            return $stmt->fetch();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter produto: ' . $e->getMessage());
        }
    }
    
    /**
     * Obtém todos os produtos
     */
    public function getAllProducts() {
        $sql = "SELECT * FROM products ORDER BY name";
        
        try {
            $stmt = $this->pdo->query($sql);
            return $stmt->fetchAll();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter produtos: ' . $e->getMessage());
        }
    }
    
    /**
     * Atualiza um produto
     */
    public function updateProduct($id, $name, $stock) {
        $sql = "UPDATE products SET name = :name, stock = :stock, updated_at = CURRENT_TIMESTAMP WHERE id = :id";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                ':id' => $id,
                ':name' => $name,
                ':stock' => $stock
            ]);
            
            return $this->getProductById($id);
        } catch (PDOException $e) {
            throw new Exception('Erro ao atualizar produto: ' . $e->getMessage());
        }
    }
    
    /**
     * Remove um produto
     */
    public function deleteProduct($id) {
        $sql = "DELETE FROM products WHERE id = :id";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([':id' => $id]);
            return $stmt->rowCount() > 0;
        } catch (PDOException $e) {
            throw new Exception('Erro ao remover produto: ' . $e->getMessage());
        }
    }
    
    /**
     * Atualiza o stock de um produto
     */
    public function updateProductStock($id, $quantity) {
        $sql = "UPDATE products SET stock = stock + :quantity, updated_at = CURRENT_TIMESTAMP WHERE id = :id";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                ':id' => $id,
                ':quantity' => $quantity
            ]);
            
            return $this->getProductById($id);
        } catch (PDOException $e) {
            throw new Exception('Erro ao atualizar stock: ' . $e->getMessage());
        }
    }
    
    /**
     * Regista um retorno de produto ao stock
     */
    public function logStockReturn($product_id, $quantity, $user_id, $reason = null) {
        $sql = "INSERT INTO stock_returns (product_id, quantity, user_id, reason) VALUES (:product_id, :quantity, :user_id, :reason)";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                ':product_id' => $product_id,
                ':quantity' => $quantity,
                ':user_id' => $user_id,
                ':reason' => $reason
            ]);
            
            return $this->pdo->lastInsertId();
        } catch (PDOException $e) {
            throw new Exception('Erro ao registar retorno de stock: ' . $e->getMessage());
        }
    }
    
    /**
     * Obtém histórico de retornos de stock
     */
    public function getStockReturns($product_id = null) {
        $sql = "SELECT sr.*, p.name as product_name, u.username 
                FROM stock_returns sr 
                JOIN products p ON sr.product_id = p.id 
                JOIN users u ON sr.user_id = u.id";
        
        $params = [];
        
        if ($product_id) {
            $sql .= " WHERE sr.product_id = :product_id";
            $params[':product_id'] = $product_id;
        }
        
        $sql .= " ORDER BY sr.created_at DESC";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetchAll();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter retornos de stock: ' . $e->getMessage());
        }
    }
    
    /**
     * Atualiza saída de produto para usar produto da tabela products
     */
    public function addProductExitFromStock($product_id, $quantity, $exit_date = null, $exit_time = null) {
        // Verificar se há stock suficiente
        $product = $this->getProductById($product_id);
        if (!$product) {
            throw new Exception('Produto não encontrado');
        }
        
        if ($product['stock'] < $quantity) {
            throw new Exception('Stock insuficiente. Stock atual: ' . $product['stock']);
        }
        
        // Usar data e hora atuais se não fornecidas
        if ($exit_date === null) {
            $exit_date = date('Y-m-d');
        }
        if ($exit_time === null) {
            $exit_time = date('H:i:s');
        }
        
        try {
            // Iniciar transação
            $this->pdo->beginTransaction();
            
            // Adicionar saída de produto
            $sql = "INSERT INTO product_exits (product_name, quantity, exit_date, exit_time) 
                    VALUES (:product_name, :quantity, :exit_date, :exit_time)";
            
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                ':product_name' => $product['name'],
                ':quantity' => $quantity,
                ':exit_date' => $exit_date,
                ':exit_time' => $exit_time
            ]);
            
            $exit_id = $this->pdo->lastInsertId();
            
            // Reduzir stock do produto
            $this->updateProductStock($product_id, -$quantity);
            
            // Confirmar transação
            $this->pdo->commit();
            
            // Retornar o registo criado
            return $this->getProductExitById($exit_id);
        } catch (Exception $e) {
            // Reverter transação em caso de erro
            $this->pdo->rollBack();
            throw new Exception('Erro ao registar saída de produto: ' . $e->getMessage());
        }
    }
    
    /**
     * Obtém uma saída de produto pelo ID
     */
    public function getProductExitById($id) {
        $sql = "SELECT * FROM product_exits WHERE id = :id";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([':id' => $id]);
            return $stmt->fetch();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter saída de produto: ' . $e->getMessage());
        }
    }
    public function getConnection() {
        return $this->pdo;
    }
    
    /**
     * Adiciona uma nova saída de produto
     */
    public function addProductExit($product_name, $quantity, $exit_date = null, $exit_time = null) {
        // Usar data e hora atuais se não fornecidas
        if ($exit_date === null) {
            $exit_date = date('Y-m-d');
        }
        if ($exit_time === null) {
            $exit_time = date('H:i:s');
        }
        
        $sql = "INSERT INTO product_exits (product_name, quantity, exit_date, exit_time) 
                VALUES (:product_name, :quantity, :exit_date, :exit_time)";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                ':product_name' => $product_name,
                ':quantity' => $quantity,
                ':exit_date' => $exit_date,
                ':exit_time' => $exit_time
            ]);
            
            // Retornar o registo criado
            $id = $this->pdo->lastInsertId();
            return $this->getProductExitById($id);
        } catch (PDOException $e) {
            throw new Exception('Erro ao adicionar saída de produto: ' . $e->getMessage());
        }
    }
    
    
    /**
     * Obtém todas as saídas de produtos ordenadas por data/hora de criação
     */
    public function getAllProductExits() {
        $sql = "SELECT * FROM product_exits ORDER BY created_at DESC";
        
        try {
            $stmt = $this->pdo->query($sql);
            return $stmt->fetchAll();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter saídas de produtos: ' . $e->getMessage());
        }
    }
    
    /**
     * Obtém saídas de produtos por data específica
     */
    public function getProductExitsByDate($date) {
        $sql = "SELECT * FROM product_exits WHERE exit_date = :date ORDER BY exit_time";
        
        try {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([':date' => $date]);
            return $stmt->fetchAll();
        } catch (PDOException $e) {
            throw new Exception('Erro ao obter saídas por data: ' . $e->getMessage());
        }
    }
    
    /**
     * Gera relatório diário de saídas
     */
    public function getDailyReport($date) {
        $exits = $this->getProductExitsByDate($date);
        
        $total_exits = count($exits);
        $total_quantity = 0;
        $products = [];
        
        foreach ($exits as $exit) {
            $total_quantity += $exit['quantity'];
            
            if (isset($products[$exit['product_name']])) {
                $products[$exit['product_name']] += $exit['quantity'];
            } else {
                $products[$exit['product_name']] = $exit['quantity'];
            }
        }
        
        return [
            'date' => $date,
            'total_exits' => $total_exits,
            'total_quantity' => $total_quantity,
            'products' => $products,
            'exits' => $exits
        ];
    }
}
?>

