<?php
// File: backup.php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    exit(0);
}

require_once 'data.php';

class DatabaseBackup {
    private $connection;
    private $servername;
    private $username;
    private $password;
    private $dbname;
    
    public function __construct($servername, $username, $password, $dbname) {
        $this->servername = $servername;
        $this->username = $username;
        $this->password = $password;
        $this->dbname = $dbname;
    }
    
    private function connect() {
        try {
            $this->connection = new PDO("mysql:host={$this->servername};dbname={$this->dbname}", 
                                      $this->username, $this->password);
            $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return true;
        } catch(PDOException $e) {
            throw new Exception("Connection failed: " . $e->getMessage());
        }
    }
    
    public function createBackup($options = []) {
        $this->connect();
        
        $backupDir = isset($options['backup_dir']) ? $options['backup_dir'] : './backups/';
        $includeData = isset($options['include_data']) ? $options['include_data'] : true;
        $tables = isset($options['tables']) ? $options['tables'] : [];
        
        // Create backup directory if not exists
        if (!is_dir($backupDir)) {
            mkdir($backupDir, 0755, true);
        }
        
        $filename = $this->dbname . '_backup_' . date('Y-m-d_H-i-s') . '.sql';
        $filepath = $backupDir . $filename;
        
        $sql = "-- Database Backup\n";
        $sql .= "-- Generated on: " . date('Y-m-d H:i:s') . "\n";
        $sql .= "-- Database: {$this->dbname}\n\n";
        
        $sql .= "SET FOREIGN_KEY_CHECKS = 0;\n";
        $sql .= "SET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";\n";
        $sql .= "SET AUTOCOMMIT = 0;\n";
        $sql .= "START TRANSACTION;\n\n";
        
        // Get all tables or specific tables
        if (empty($tables)) {
            $tablesQuery = $this->connection->query("SHOW TABLES");
            $tables = $tablesQuery->fetchAll(PDO::FETCH_COLUMN);
        }
        
        $totalTables = count($tables);
        $processedTables = 0;
        
        foreach ($tables as $table) {
            $sql .= $this->getTableStructure($table);
            
            if ($includeData) {
                $sql .= $this->getTableData($table);
            }
            
            $processedTables++;
        }
        
        $sql .= "\nSET FOREIGN_KEY_CHECKS = 1;\n";
        $sql .= "COMMIT;\n";
        
        // Write to file
        $result = file_put_contents($filepath, $sql);
        
        if ($result === false) {
            throw new Exception("Failed to write backup file");
        }
        
        $fileSize = filesize($filepath);
        
        return [
            'success' => true,
            'filename' => $filename,
            'filepath' => $filepath,
            'size' => $this->formatBytes($fileSize),
            'tables_count' => $totalTables,
            'created_at' => date('Y-m-d H:i:s')
        ];
    }
    
    private function getTableStructure($table) {
        $sql = "\n-- Table structure for table `{$table}`\n";
        $sql .= "DROP TABLE IF EXISTS `{$table}`;\n";
        
        $createTableQuery = $this->connection->query("SHOW CREATE TABLE `{$table}`");
        $createTable = $createTableQuery->fetch(PDO::FETCH_ASSOC);
        
        $sql .= $createTable['Create Table'] . ";\n\n";
        
        return $sql;
    }
    
    private function getTableData($table) {
        $sql = "-- Dumping data for table `{$table}`\n";
        
        $dataQuery = $this->connection->query("SELECT * FROM `{$table}`");
        $rows = $dataQuery->fetchAll(PDO::FETCH_ASSOC);
        
        if (empty($rows)) {
            $sql .= "-- No data found for table `{$table}`\n\n";
            return $sql;
        }
        
        $columns = array_keys($rows[0]);
        $columnsList = '`' . implode('`, `', $columns) . '`';
        
        $sql .= "INSERT INTO `{$table}` ({$columnsList}) VALUES\n";
        
        $values = [];
        foreach ($rows as $row) {
            $rowValues = [];
            foreach ($row as $value) {
                if ($value === null) {
                    $rowValues[] = 'NULL';
                } else {
                    $rowValues[] = "'" . $this->connection->quote($value) . "'";
                }
            }
            $values[] = '(' . implode(', ', $rowValues) . ')';
        }
        
        $sql .= implode(",\n", $values) . ";\n\n";
        
        return $sql;
    }
    
    public function listBackups($backupDir = './backups/') {
        if (!is_dir($backupDir)) {
            return [];
        }
        
        $backups = [];
        $files = scandir($backupDir);
        
        foreach ($files as $file) {
            if (pathinfo($file, PATHINFO_EXTENSION) === 'sql') {
                $filepath = $backupDir . $file;
                $backups[] = [
                    'filename' => $file,
                    'size' => $this->formatBytes(filesize($filepath)),
                    'created_at' => date('Y-m-d H:i:s', filemtime($filepath))
                ];
            }
        }
        
        // Sort by creation time (newest first)
        usort($backups, function($a, $b) {
            return strtotime($b['created_at']) - strtotime($a['created_at']);
        });
        
        return $backups;
    }
    
    public function deleteBackup($filename, $backupDir = './backups/') {
        $filepath = $backupDir . $filename;
        
        if (!file_exists($filepath)) {
            throw new Exception("Backup file not found");
        }
        
        if (pathinfo($filename, PATHINFO_EXTENSION) !== 'sql') {
            throw new Exception("Invalid file type");
        }
        
        $result = unlink($filepath);
        
        if (!$result) {
            throw new Exception("Failed to delete backup file");
        }
        
        return ['success' => true, 'message' => 'Backup deleted successfully'];
    }
    
    private function formatBytes($size, $precision = 2) {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        
        for ($i = 0; $size > 1024 && $i < count($units) - 1; $i++) {
            $size /= 1024;
        }
        
        return round($size, $precision) . ' ' . $units[$i];
    }
}

// Handle API requests
try {
    $action = $_POST['action'] ?? $_GET['action'] ?? '';
    $backup = new DatabaseBackup($servername, $username, $password, $dbname);
    
    switch ($action) {
        case 'create':
            $options = [
                'include_data' => $_POST['include_data'] ?? true,
                'backup_dir' => $_POST['backup_dir'] ?? './backups/',
                'tables' => $_POST['tables'] ?? []
            ];
            
            $result = $backup->createBackup($options);
            echo json_encode($result);
            break;
            
        case 'list':
            $backupDir = $_GET['backup_dir'] ?? './backups/';
            $result = $backup->listBackups($backupDir);
            echo json_encode(['success' => true, 'backups' => $result]);
            break;
            
        case 'delete':
            $filename = $_POST['filename'] ?? '';
            $backupDir = $_POST['backup_dir'] ?? './backups/';
            
            if (empty($filename)) {
                throw new Exception("Filename is required");
            }
            
            $result = $backup->deleteBackup($filename, $backupDir);
            echo json_encode($result);
            break;
            
        case 'download':
            $filename = $_GET['filename'] ?? '';
            $backupDir = $_GET['backup_dir'] ?? './backups/';
            $filepath = $backupDir . $filename;
            
            if (empty($filename) || !file_exists($filepath)) {
                throw new Exception("File not found");
            }
            
            if (pathinfo($filename, PATHINFO_EXTENSION) !== 'sql') {
                throw new Exception("Invalid file type");
            }
            
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . $filename . '"');
            header('Content-Length: ' . filesize($filepath));
            readfile($filepath);
            exit;
            
        default:
            echo json_encode(['success' => false, 'error' => 'Invalid action']);
    }
    
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>