<?php
namespace Modules\SettingsUI\Controllers;

use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Http\Response;
use Gestoreasy\Core\Tenant\ConnectionManager;
use Gestoreasy\Core\Tenant\TenantContext;
use PDO;

class BackupController {
    private function getTenantId(): string {
        return TenantContext::getTenantId();
    }

    /**
     * Gera backup completo do sistema em JSON
     */
    public function generateJsonBackup(Request $req): Response {
        $pdo = ConnectionManager::forTenant();
        $tenantId = $this->getTenantId();
        
        try {
            $backup = [
                'tenant_id' => $tenantId,
                'generated_at' => date('Y-m-d H:i:s'),
                'version' => '1.0',
                'data' => []
            ];

            // Lista de tabelas principais para backup
            $tables = [
                'clients', 'client_addresses', 'products', 'suppliers', 'purchase_orders',
                'sales_orders', 'sales_order_items', 'inventory_movements',
                'contas_receber', 'contas_pagar', 'users', 'roles', 'permissions',
                'ecommerce_config', 'ecommerce_pedidos', 'ecommerce_pedido_itens',
                'ecommerce_categorias', 'ecommerce_produtos'
            ];

            foreach ($tables as $table) {
                try {
                    // Verificar se tabela existe
                    $check = $pdo->query("SHOW TABLES LIKE '$table'");
                    if ($check->rowCount() === 0) continue;

                    $stmt = $pdo->query("SELECT * FROM $table");
                    $backup['data'][$table] = $stmt->fetchAll(PDO::FETCH_ASSOC);
                } catch (\Throwable $e) {
                    error_log("[Backup] Erro ao fazer backup da tabela $table: " . $e->getMessage());
                    $backup['data'][$table] = [];
                }
            }

            // Adicionar metadados
            $backup['metadata'] = [
                'total_tables' => count($backup['data']),
                'total_records' => array_sum(array_map('count', $backup['data']))
            ];

            $json = json_encode($backup, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
            
            return new Response(200, $json, [
                'Content-Type' => 'application/json; charset=utf-8',
                'Content-Disposition' => 'attachment; filename="backup_' . $tenantId . '_' . date('Y-m-d_His') . '.json"'
            ]);
        } catch (\Throwable $e) {
            error_log("[Backup] Erro ao gerar backup JSON: " . $e->getMessage());
            return new Response(500, ['error' => ['code' => 'backup_failed', 'message' => 'Erro ao gerar backup']]);
        }
    }

    /**
     * Gera backup completo do sistema em CSV (múltiplos arquivos ZIP)
     */
    public function generateCsvBackup(Request $req): Response {
        $pdo = ConnectionManager::forTenant();
        $tenantId = $this->getTenantId();
        
        try {
            // Criar arquivo temporário ZIP
            $zipFile = sys_get_temp_dir() . '/backup_' . $tenantId . '_' . date('Y-m-d_His') . '.zip';
            $zip = new \ZipArchive();
            
            if ($zip->open($zipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== TRUE) {
                return new Response(500, ['error' => ['code' => 'zip_creation_failed', 'message' => 'Erro ao criar arquivo ZIP']]);
            }

            $tables = [
                'clients', 'client_addresses', 'products', 'suppliers', 'purchase_orders',
                'sales_orders', 'sales_order_items', 'inventory_movements',
                'contas_receber', 'contas_pagar', 'users', 'roles', 'permissions',
                'ecommerce_config', 'ecommerce_pedidos', 'ecommerce_pedido_itens',
                'ecommerce_categorias', 'ecommerce_produtos'
            ];

            foreach ($tables as $table) {
                try {
                    $check = $pdo->query("SHOW TABLES LIKE '$table'");
                    if ($check->rowCount() === 0) continue;

                    $stmt = $pdo->query("SELECT * FROM $table");
                    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
                    
                    if (empty($rows)) continue;

                    // Criar CSV em memória
                    $csvContent = '';
                    
                    // Cabeçalho
                    $headers = array_keys($rows[0]);
                    $csvContent .= implode(',', array_map(function($h) {
                        return '"' . str_replace('"', '""', $h) . '"';
                    }, $headers)) . "\n";
                    
                    // Dados
                    foreach ($rows as $row) {
                        $csvContent .= implode(',', array_map(function($v) {
                            if ($v === null) return 'NULL';
                            if (is_array($v) || is_object($v)) return '"' . str_replace('"', '""', json_encode($v)) . '"';
                            return '"' . str_replace('"', '""', (string)$v) . '"';
                        }, $row)) . "\n";
                    }
                    
                    $zip->addFromString("$table.csv", $csvContent);
                } catch (\Throwable $e) {
                    error_log("[Backup] Erro ao fazer backup CSV da tabela $table: " . $e->getMessage());
                }
            }

            // Adicionar arquivo de índice
            $index = [
                'tenant_id' => $tenantId,
                'generated_at' => date('Y-m-d H:i:s'),
                'tables' => $tables
            ];
            $zip->addFromString('index.json', json_encode($index, JSON_PRETTY_PRINT));

            $zip->close();

            // Ler arquivo e enviar
            $content = file_get_contents($zipFile);
            unlink($zipFile);

            return new Response(200, $content, [
                'Content-Type' => 'application/zip',
                'Content-Disposition' => 'attachment; filename="backup_' . $tenantId . '_' . date('Y-m-d_His') . '.zip"'
            ]);
        } catch (\Throwable $e) {
            error_log("[Backup] Erro ao gerar backup CSV: " . $e->getMessage());
            if (isset($zipFile) && file_exists($zipFile)) {
                unlink($zipFile);
            }
            return new Response(500, ['error' => ['code' => 'backup_failed', 'message' => 'Erro ao gerar backup']]);
        }
    }

    /**
     * Lista informações sobre backups disponíveis
     */
    public function getBackupInfo(Request $req): Response {
        $pdo = ConnectionManager::forTenant();
        $tenantId = $this->getTenantId();
        
        try {
            $info = [
                'tenant_id' => $tenantId,
                'tables_count' => 0,
                'total_records' => 0,
                'tables' => []
            ];

            $stmt = $pdo->query("SHOW TABLES");
            $tables = $stmt->fetchAll(PDO::FETCH_COLUMN);

            foreach ($tables as $table) {
                try {
                    $countStmt = $pdo->query("SELECT COUNT(*) as cnt FROM `$table`");
                    $count = (int)$countStmt->fetch()['cnt'];
                    
                    $info['tables'][] = [
                        'name' => $table,
                        'records' => $count
                    ];
                    $info['total_records'] += $count;
                } catch (\Throwable $e) {
                    // Ignorar erros
                }
            }

            $info['tables_count'] = count($info['tables']);

            return Response::json($info);
        } catch (\Throwable $e) {
            error_log("[Backup] Erro ao obter informações: " . $e->getMessage());
            return new Response(500, ['error' => ['code' => 'info_failed', 'message' => 'Erro ao obter informações']]);
        }
    }
}

