<?php
/**
 * Base Model Class
 * Provides common CRUD operations and multi-tenant isolation
 */
abstract class BaseModel {
    protected $db;
    protected $tableName;
    protected $primaryKey = 'id';
    protected $tenantColumn = null; // Column name for multi-tenant isolation (e.g., 'property_id', 'owner_id')
    
    public function __construct() {
        $this->db = Database::getInstance();
    }
    
    /**
     * Get all records with optional filters and tenant isolation
     */
    public function getAll($filters = [], $tenantId = null) {
        $sql = "SELECT * FROM {$this->tableName} WHERE 1=1";
        $params = [];
        
        // Apply tenant isolation if tenant column is set
        if ($this->tenantColumn && $tenantId !== null) {
            $sql .= " AND {$this->tenantColumn} = ?";
            $params[] = $tenantId;
        }
        
        // Apply additional filters
        foreach ($filters as $column => $value) {
            $sql .= " AND {$column} = ?";
            $params[] = $value;
        }
        
        $sql .= " ORDER BY created_at DESC";
        
        $result = $this->db->query($sql, $params);
        $data = [];
        
        while ($row = $result->fetch_assoc()) {
            $data[] = $row;
        }
        
        return $data;
    }
    
    /**
     * Get single record by ID with tenant isolation
     */
    public function getById($id, $tenantId = null) {
        $sql = "SELECT * FROM {$this->tableName} WHERE {$this->primaryKey} = ?";
        $params = [$id];
        
        if ($this->tenantColumn && $tenantId !== null) {
            $sql .= " AND {$this->tenantColumn} = ?";
            $params[] = $tenantId;
        }
        
        $result = $this->db->query($sql, $params);
        return $result->fetch_assoc();
    }
    
    /**
     * Create new record
     */
    public function create($data) {
        $columns = implode(', ', array_keys($data));
        $placeholders = implode(', ', array_fill(0, count($data), '?'));
        $values = array_values($data);
        
        $sql = "INSERT INTO {$this->tableName} ({$columns}) VALUES ({$placeholders})";
        
        $this->db->execute($sql, $values);
        return $this->db->getLastInsertId();
    }
    
    /**
     * Update record by ID
     */
    public function update($id, $data, $tenantId = null) {
        $setClause = [];
        $values = [];
        
        foreach ($data as $column => $value) {
            $setClause[] = "{$column} = ?";
            $values[] = $value;
        }
        
        $sql = "UPDATE {$this->tableName} SET " . implode(', ', $setClause) . " WHERE {$this->primaryKey} = ?";
        $values[] = $id;
        
        if ($this->tenantColumn && $tenantId !== null) {
            $sql .= " AND {$this->tenantColumn} = ?";
            $values[] = $tenantId;
        }
        
        return $this->db->execute($sql, $values);
    }
    
    /**
     * Delete record by ID with tenant isolation
     */
    public function delete($id, $tenantId = null) {
        $sql = "DELETE FROM {$this->tableName} WHERE {$this->primaryKey} = ?";
        $params = [$id];
        
        if ($this->tenantColumn && $tenantId !== null) {
            $sql .= " AND {$this->tenantColumn} = ?";
            $params[] = $tenantId;
        }
        
        return $this->db->execute($sql, $params);
    }
    
    /**
     * Count records with filters
     */
    public function count($filters = [], $tenantId = null) {
        $sql = "SELECT COUNT(*) as total FROM {$this->tableName} WHERE 1=1";
        $params = [];
        
        if ($this->tenantColumn && $tenantId !== null) {
            $sql .= " AND {$this->tenantColumn} = ?";
            $params[] = $tenantId;
        }
        
        foreach ($filters as $column => $value) {
            $sql .= " AND {$column} = ?";
            $params[] = $value;
        }
        
        $result = $this->db->query($sql, $params);
        $row = $result->fetch_assoc();
        return (int)$row['total'];
    }
    
    /**
     * Custom query execution
     */
    protected function customQuery($sql, $params = []) {
        return $this->db->query($sql, $params);
    }
    
    /**
     * Custom execute
     */
    protected function customExecute($sql, $params = []) {
        return $this->db->execute($sql, $params);
    }
}
?>
