<?php
// install_update.php
session_start();
include 'layouts/dbconn.php';

if (!isset($_SESSION['user_id']) || $_SESSION['role_id'] !== 1) {
   http_response_code(403);
   echo json_encode(['error' => 'Unauthorized']);
   exit;
}

try {
   $data = json_decode(file_get_contents('php://input'), true);
   $version = $data['version'];
   
   // Read manifest
   $manifestPath = "app/updates/packages/$version/manifest.json";
   if (!file_exists($manifestPath)) {
       throw new Exception("Manifest not found for version $version");
   }
   
   $manifest = json_decode(file_get_contents($manifestPath), true);
   if (!$manifest) {
       throw new Exception("Invalid manifest file for version $version");
   }

   // Verify version requirements
   $currentVersion = getCurrentVersion($conn);
   if (!checkVersionRequirements($manifest, $currentVersion)) {
       throw new Exception("Version requirement not met. Current version: $currentVersion");
   }

   // Create backup directory
   $backupDir = "app/backups/" . date('Y-m-d_H-i-s') . "_v$version";
   if (!mkdir($backupDir, 0755, true)) {
       throw new Exception("Failed to create backup directory");
   }

   // Start transaction
   $conn->begin_transaction();

   try {
       // Deploy files
       foreach ($manifest['files'] as $file) {
           $sourcePath = "app/updates/packages/$version/files/" . $file['path'];
           $targetPath = $file['path'];
           
           // Verify checksum if provided
           if (!empty($file['checksum']) && file_exists($targetPath)) {
               $currentChecksum = hash_file('sha256', $targetPath);
               if ($currentChecksum !== $file['checksum']) {
                   throw new Exception("File checksum mismatch: {$file['path']}");
               }
           }
           
           // Backup existing file
           if ($file['backup'] && file_exists($targetPath)) {
               $backupPath = $backupDir . '/' . $file['path'];
               $backupDir = dirname($backupPath);
               if (!is_dir($backupDir)) {
                   mkdir($backupDir, 0755, true);
               }
               if (!copy($targetPath, $backupPath)) {
                   throw new Exception("Failed to backup file: {$file['path']}");
               }
           }

           // Deploy new/updated file
           if (!copy($sourcePath, $targetPath)) {
               throw new Exception("Failed to deploy file: {$file['path']}");
           }
       }

       // Run DB changes
       foreach ($manifest['db_changes'] as $query) {
           if (!$conn->query($query)) {
               throw new Exception("Database query failed: " . $conn->error);
           }
       }

       // Update menu items
       if (!empty($manifest['menu_updates'])) {
           foreach ($manifest['menu_updates'] as $menu) {
               if ($menu['action'] === 'add') {
                   $sql = "INSERT INTO menu_items 
                           (menu_name, menu_url, menu_icon, parent_id, menu_order, section_name) 
                           VALUES (?, ?, ?, ?, ?, ?)";
                   $stmt = $conn->prepare($sql);
                   $stmt->bind_param("sssiss", 
                       $menu['name'], 
                       $menu['url'], 
                       $menu['icon'],
                       $menu['parent_id'], 
                       $menu['order'], 
                       $menu['section']
                   );
               } else if ($menu['action'] === 'update') {
                   $sql = "UPDATE menu_items 
                           SET menu_name = ?, menu_url = ?, menu_icon = ?, 
                               parent_id = ?, menu_order = ?, section_name = ? 
                           WHERE menu_id = ?";
                   $stmt = $conn->prepare($sql);
                   $stmt->bind_param("sssissi",
                       $menu['name'],
                       $menu['url'], 
                       $menu['icon'],
                       $menu['parent_id'],
                       $menu['order'],
                       $menu['section'],
                       $menu['id']
                   );
               } else if ($menu['action'] === 'delete') {
                   $sql = "DELETE FROM menu_items WHERE menu_id = ?";
                   $stmt = $conn->prepare($sql);
                   $stmt->bind_param("i", $menu['id']);
               }
               
               if (!$stmt->execute()) {
                   throw new Exception("Failed to update menu: " . $stmt->error);
               }
           }
       }

       // Log successful update
       $sql = "INSERT INTO system_updates 
               (version, description, update_files, db_changes, installed_date, installed_by, status) 
               VALUES (?, ?, ?, ?, NOW(), ?, 'INSTALLED')";
       $stmt = $conn->prepare($sql);
       $filesJson = json_encode($manifest['files']);
       $dbJson = json_encode($manifest['db_changes']);
       $stmt->bind_param("ssssi", 
           $version,
           $manifest['description'],
           $filesJson,
           $dbJson,
           $_SESSION['user_id']
       );
       $stmt->execute();

       // Archive the update
       archiveUpdate($version);

       // Commit transaction
       $conn->commit();
       
       echo json_encode([
           'success' => true,
           'message' => "Successfully installed update $version"
       ]);

   } catch (Exception $e) {
       $conn->rollback();
       logUpdateError($version, $e->getMessage(), $conn);
       throw $e;
   }

} catch (Exception $e) {
   http_response_code(500);
   echo json_encode([
       'error' => $e->getMessage()
   ]);
}

function getCurrentVersion($conn) {
   $sql = "SELECT version FROM system_updates 
           WHERE status = 'INSTALLED' 
           ORDER BY installed_date DESC LIMIT 1";
   $result = $conn->query($sql);
   return $result->fetch_assoc()['version'] ?? '1.0.0';
}

function checkVersionRequirements($manifest, $currentVersion) {
   if (!empty($manifest['requires_version'])) {
       return version_compare($currentVersion, $manifest['requires_version'], '>=');
   }
   return true;
}

function logUpdateError($version, $error, $conn) {
   $sql = "UPDATE system_updates 
           SET status = 'FAILED',
               error_message = ?,
               installed_date = NOW() 
           WHERE version = ?";
   $stmt = $conn->prepare($sql);
   $stmt->bind_param('ss', $error, $version);
   $stmt->execute();
   
   error_log("Update failed for version $version: $error");
}

function archiveUpdate($version) {
   $sourceDir = "app/updates/packages/$version";
   $archiveDir = "app/old_updates/$version";
   
   if (!is_dir("app/old_updates")) {
       mkdir("app/old_updates", 0755, true);
   }

   if (is_dir($sourceDir)) {
       rename($sourceDir, $archiveDir);
   }

   $indexFile = "app/updates/index.json";
   if (file_exists($indexFile)) {
       $index = json_decode(file_get_contents($indexFile), true);
       $index['updates'] = array_filter($index['updates'], function($update) use ($version) {
           return $update['version'] !== $version;
       });
       file_put_contents($indexFile, json_encode($index, JSON_PRETTY_PRINT));
   }
}
?>