<?php
namespace App\Controllers;

use PDO;
use Exception;

class SystemFiles
{
    private $conn;
    private $systemPath;
    
    public function __construct()
    {
        global $conn;
        $this->conn = $conn;
        $this->systemPath = realpath(__DIR__ . '/../../system/');
    }
    
    public function index()
    {
        $files = $this->getSystemFiles();
        include realpath(__DIR__ . '/../views/system_files.php');
    }
    
    public function upload()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            try {
                if (!isset($_FILES['system_file']) || $_FILES['system_file']['error'] !== UPLOAD_ERR_OK) {
                    throw new Exception('No file uploaded or upload error occurred');
                }
                
                $uploadedFile = $_FILES['system_file'];
                $fileName = $uploadedFile['name'];
                $tempPath = $uploadedFile['tmp_name'];
                
                // Validate file name - must be exactly phpnuxbill.sql or phpnuxbill.zip
                if (!in_array($fileName, ['phpnuxbill.sql', 'phpnuxbill.zip'])) {
                    throw new Exception('Invalid file name. Only phpnuxbill.sql and phpnuxbill.zip are allowed.');
                }
                
                // Validate file extension
                $extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
                if (!in_array($extension, ['sql', 'zip'])) {
                    throw new Exception('Invalid file type. Only .sql and .zip files are allowed.');
                }
                
                // Additional validation for SQL files
                if ($extension === 'sql') {
                    $fileContent = file_get_contents($tempPath);
                    if (strpos($fileContent, 'CREATE TABLE') === false && strpos($fileContent, 'INSERT INTO') === false) {
                        throw new Exception('Invalid SQL file. Must contain CREATE TABLE or INSERT INTO statements.');
                    }
                }
                
                // Additional validation for ZIP files
                if ($extension === 'zip') {
                    $zip = new \ZipArchive();
                    if ($zip->open($tempPath) !== TRUE) {
                        throw new Exception('Invalid ZIP file or corrupted archive.');
                    }
                    $zip->close();
                }
                
                $destinationPath = $this->systemPath . '/' . $fileName;
                
                // Backup existing file if it exists
                if (file_exists($destinationPath)) {
                    $backupPath = $this->systemPath . '/' . pathinfo($fileName, PATHINFO_FILENAME) . '_backup_' . date('Y-m-d_H-i-s') . '.' . $extension;
                    if (!copy($destinationPath, $backupPath)) {
                        throw new Exception('Failed to create backup of existing file');
                    }
                }
                
                // Move uploaded file
                if (!move_uploaded_file($tempPath, $destinationPath)) {
                    throw new Exception('Failed to move uploaded file to system directory');
                }
                
                // Log the upload
                $this->logFileOperation('upload', $fileName, $_SESSION['user']['username'] ?? 'Unknown');
                
                $_SESSION['success'] = "File '{$fileName}' uploaded successfully!";
                
            } catch (Exception $e) {
                $_SESSION['error'] = 'Upload failed: ' . $e->getMessage();
            }
        }
        
        header('Location: ?app_route=system_files');
        exit;
    }
    
    public function delete()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            try {
                $fileName = $_POST['file_name'] ?? '';
                
                // Validate file name
                if (!in_array($fileName, ['phpnuxbill.sql', 'phpnuxbill.zip'])) {
                    throw new Exception('Invalid file name. Only phpnuxbill.sql and phpnuxbill.zip can be deleted.');
                }
                
                $filePath = $this->systemPath . '/' . $fileName;
                
                if (!file_exists($filePath)) {
                    throw new Exception('File not found');
                }
                
                // Create backup before deletion
                $extension = pathinfo($fileName, PATHINFO_EXTENSION);
                $backupPath = $this->systemPath . '/' . pathinfo($fileName, PATHINFO_FILENAME) . '_deleted_' . date('Y-m-d_H-i-s') . '.' . $extension;
                
                if (!copy($filePath, $backupPath)) {
                    throw new Exception('Failed to create backup before deletion');
                }
                
                // Delete the file
                if (!unlink($filePath)) {
                    throw new Exception('Failed to delete file');
                }
                
                // Log the deletion
                $this->logFileOperation('delete', $fileName, $_SESSION['user']['username'] ?? 'Unknown');
                
                $_SESSION['success'] = "File '{$fileName}' deleted successfully! Backup created: " . basename($backupPath);
                
            } catch (Exception $e) {
                $_SESSION['error'] = 'Deletion failed: ' . $e->getMessage();
            }
        }
        
        header('Location: ?app_route=system_files');
        exit;
    }
    
    public function download()
    {
        try {
            $fileName = $_GET['file'] ?? '';
            
            // Validate file name
            if (!in_array($fileName, ['phpnuxbill.sql', 'phpnuxbill.zip'])) {
                throw new Exception('Invalid file name');
            }
            
            $filePath = $this->systemPath . '/' . $fileName;
            
            if (!file_exists($filePath)) {
                throw new Exception('File not found');
            }
            
            // Log the download
            $this->logFileOperation('download', $fileName, $_SESSION['user']['username'] ?? 'Unknown');
            
            // Set headers for file download
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . $fileName . '"');
            header('Content-Length: ' . filesize($filePath));
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            
            // Output file content
            readfile($filePath);
            exit;
            
        } catch (Exception $e) {
            $_SESSION['error'] = 'Download failed: ' . $e->getMessage();
            header('Location: ?app_route=system_files');
            exit;
        }
    }
    
    private function getSystemFiles()
    {
        $files = [];
        $allowedFiles = ['phpnuxbill.sql', 'phpnuxbill.zip'];
        
        if (!is_dir($this->systemPath)) {
            return $files;
        }
        
        foreach ($allowedFiles as $fileName) {
            $filePath = $this->systemPath . '/' . $fileName;
            
            if (file_exists($filePath)) {
                $files[] = [
                    'name' => $fileName,
                    'size' => filesize($filePath),
                    'modified' => filemtime($filePath),
                    'path' => $filePath
                ];
            }
        }
        
        // Get backup files
        $backupFiles = glob($this->systemPath . '/phpnuxbill_*.*');
        foreach ($backupFiles as $backupFile) {
            $fileName = basename($backupFile);
            if (preg_match('/phpnuxbill_(backup|deleted)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.(sql|zip)$/', $fileName)) {
                $files[] = [
                    'name' => $fileName,
                    'size' => filesize($backupFile),
                    'modified' => filemtime($backupFile),
                    'path' => $backupFile,
                    'is_backup' => true
                ];
            }
        }
        
        return $files;
    }
    
    private function logFileOperation($operation, $fileName, $username)
    {
        try {
            $sql = "INSERT INTO system_file_logs (operation, file_name, username, ip_address, user_agent, created_at) 
                    VALUES (?, ?, ?, ?, ?, NOW())";
            $stmt = $this->conn->prepare($sql);
            $stmt->execute([
                $operation,
                $fileName,
                $username,
                $_SERVER['REMOTE_ADDR'] ?? 'Unknown',
                $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'
            ]);
        } catch (Exception $e) {
            error_log("Failed to log file operation: " . $e->getMessage());
        }
    }
    
    public function getLogs()
    {
        try {
            $sql = "SELECT * FROM system_file_logs ORDER BY created_at DESC LIMIT 50";
            $stmt = $this->conn->query($sql);
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Failed to get file logs: " . $e->getMessage());
            return [];
        }
    }
}
