<?php

/**
 * Multi-Tenant Database Helper
 * Ensures all database queries are scoped to the current workspace
 */
class TenantDB {
    
    private static $companyId = null;
    
    /**
     * Set the current tenant (company) context
     */
    public static function setTenant(int $companyId): void {
        self::$companyId = $companyId;
    }
    
    /**
     * Get current tenant ID
     */
    public static function getTenant(): ?int {
        if (self::$companyId === null) {
            // Try to get from session
            self::$companyId = $_SESSION['current_company_id'] ?? null;
        }
        return self::$companyId;
    }
    
    /**
     * Execute query with tenant filtering
     */
    public static function query(string $query, array $params = [], bool $returnFirst = false): array {
        $pdo = getPDO();
        $companyId = self::getTenant();
        
        error_log("TenantDB Query: Original = $query");
        error_log("TenantDB Query: Company ID = " . ($companyId ?: 'NULL'));
        
        if (!$companyId) {
            throw new Exception("No tenant context set");
        }
        
        // Add company_id filter to queries
        $modifiedQuery = self::addTenantFilter($query, $companyId);
        
        error_log("TenantDB Query: Modified = $modifiedQuery");
        
        try {
            $stmt = $pdo->prepare($modifiedQuery);
            $stmt->execute($params);
            
            if ($returnFirst) {
                $result = $stmt->fetch() ?: [];
                error_log("TenantDB Query: Result (first) = " . json_encode($result));
                return $result;
            }
            
            $result = $stmt->fetchAll() ?: [];
            error_log("TenantDB Query: Result count = " . count($result));
            return $result;
        } catch (PDOException $e) {
            error_log("TenantDB Query Error: " . $e->getMessage() . " | Query: " . $modifiedQuery);
            return [];
        }
    }
    
    /**
     * Execute insert with tenant context
     */
    public static function insert(string $table, array $data): int {
        $pdo = getPDO();
        $companyId = self::getTenant();
        
        error_log("TenantDB Insert: Company ID = " . ($companyId ?: 'NULL'));
        error_log("TenantDB Insert: Table = $table");
        error_log("TenantDB Insert: Data = " . json_encode($data));
        
        if (!$companyId) {
            throw new Exception("No tenant context set");
        }
        
        // Add company_id to data
        $data['company_id'] = $companyId;
        $data['created_at'] = date('Y-m-d H:i:s');
        
        $columns = implode(', ', array_keys($data));
        $placeholders = implode(', ', array_fill(0, count($data), '?'));
        
        $query = "INSERT INTO $table ($columns) VALUES ($placeholders)";
        
        error_log("TenantDB Insert: Query = $query");
        
        try {
            $stmt = $pdo->prepare($query);
            $stmt->execute(array_values($data));
            return (int) $pdo->lastInsertId();
        } catch (PDOException $e) {
            error_log("TenantDB Insert Error: " . $e->getMessage());
            throw new Exception("Failed to insert data");
        }
    }
    
    /**
     * Get next sequence number for tenant
     */
    public static function getNextSequence(string $type): int {
        $companyId = self::getTenant();
        
        if (!$companyId) {
            throw new Exception("No tenant context set");
        }
        
        $pdo = getPDO();
        
        // Create sequences table if it doesn't exist
        $pdo->exec("CREATE TABLE IF NOT EXISTS tenant_sequences (
            company_id INT,
            sequence_type VARCHAR(50),
            next_number INT DEFAULT 1,
            PRIMARY KEY (company_id, sequence_type)
        )");
        
        // Get and increment sequence
        $stmt = $pdo->prepare("SELECT next_number FROM tenant_sequences WHERE company_id = ? AND sequence_type = ? FOR UPDATE");
        $stmt->execute([$companyId, $type]);
        $result = $stmt->fetch();
        
        if ($result) {
            $nextNumber = $result['next_number'];
            $updateStmt = $pdo->prepare("UPDATE tenant_sequences SET next_number = next_number + 1 WHERE company_id = ? AND sequence_type = ?");
            $updateStmt->execute([$companyId, $type]);
        } else {
            $nextNumber = 1;
            $insertStmt = $pdo->prepare("INSERT INTO tenant_sequences (company_id, sequence_type, next_number) VALUES (?, ?, ?)");
            $insertStmt->execute([$companyId, $type, 2]);
        }
        
        return $nextNumber;
    }
    
    /**
     * Add tenant filter to WHERE clause
     */
    private static function addTenantFilter(string $query, int $companyId): string {
        // Don't modify if it's already filtered or doesn't need filtering
        if (strpos($query, 'company_id') !== false || 
            strpos($query, 'INSERT INTO') === 0 ||
            strpos($query, 'UPDATE') === 0 ||
            strpos($query, 'DELETE FROM') === 0) {
            return $query;
        }
        
        // Add company_id filter to SELECT queries
        if (strpos($query, 'SELECT') === 0) {
            if (strpos($query, 'WHERE') !== false) {
                return $query . " AND company_id = $companyId";
            } else {
                return $query . " WHERE company_id = $companyId";
            }
        }
        
        return $query;
    }
    
    /**
     * Get tenant-specific file path
     */
    public static function getFilePath(string $relativePath): string {
        $companyId = self::getTenant();
        
        if (!$companyId) {
            throw new Exception("No tenant context set");
        }
        
        return __DIR__ . "/../storage/companies/$companyId/" . $relativePath;
    }
    
    /**
     * Ensure tenant directory exists
     */
    public static function ensureDirectory(string $relativePath): string {
        $fullPath = self::getFilePath($relativePath);
        
        if (!is_dir($fullPath)) {
            mkdir($fullPath, 0755, true);
        }
        
        return $fullPath;
    }
}
