<?php
/**
 * AUTO TESTER - File Storage System
 * Comprehensive file management for images and reports
 * Created: 2026-04-22
 */

require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../database/functions/Database.php';

class FileStorage {
    private $db;
    private $uploadDir;
    private $allowedImageTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
    private $allowedReportTypes = ['pdf', 'doc', 'docx', 'xls', 'xlsx'];
    private $maxFileSize = 10485760; // 10MB
    
    public function __construct() {
        $this->db = Database::getInstance();
        $this->uploadDir = $_SERVER['DOCUMENT_ROOT'] . '/uploads/';
        $this->ensureUploadDirectories();
    }
    
    /**
     * Ensure upload directories exist
     */
    private function ensureUploadDirectories() {
        $directories = [
            $this->uploadDir,
            $this->uploadDir . 'images/',
            $this->uploadDir . 'reports/',
            $this->uploadDir . 'vehicles/',
            $this->uploadDir . 'inspections/',
            $this->uploadDir . 'temp/',
            $this->uploadDir . 'backups/'
        ];
        
        foreach ($directories as $dir) {
            if (!file_exists($dir)) {
                mkdir($dir, 0755, true);
            }
        }
    }
    
    /**
     * Upload file
     */
    public function uploadFile($file, $category, $referenceId = null, $description = '') {
        try {
            // Validate file
            $validation = $this->validateFile($file, $category);
            if (!$validation['valid']) {
                return ['success' => false, 'message' => $validation['message']];
            }
            
            // Generate unique filename
            $fileName = $this->generateUniqueFileName($file['name'], $category);
            $filePath = $this->getUploadPath($category) . $fileName;
            
            // Move file
            if (!move_uploaded_file($file['tmp_name'], $filePath)) {
                return ['success' => false, 'message' => 'Failed to move uploaded file'];
            }
            
            // Save file record to database
            $fileRecord = $this->saveFileRecord([
                'original_name' => $file['name'],
                'file_name' => $fileName,
                'file_path' => str_replace($_SERVER['DOCUMENT_ROOT'], '', $filePath),
                'file_size' => $file['size'],
                'file_type' => $file['type'],
                'category' => $category,
                'reference_id' => $referenceId,
                'description' => $description,
                'uploaded_by' => $_SESSION['user_id'] ?? null
            ]);
            
            if (!$fileRecord) {
                unlink($filePath); // Clean up file if database save fails
                return ['success' => false, 'message' => 'Failed to save file record'];
            }
            
            return [
                'success' => true,
                'message' => 'File uploaded successfully',
                'file_id' => $fileRecord['id'],
                'file_url' => $fileRecord['file_path'],
                'file_name' => $fileName
            ];
            
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Upload error: ' . $e->getMessage()];
        }
    }
    
    /**
     * Validate file
     */
    private function validateFile($file, $category) {
        // Check if file was uploaded
        if (!isset($file['tmp_name']) || !is_uploaded_file($file['tmp_name'])) {
            return ['valid' => false, 'message' => 'Invalid file upload'];
        }
        
        // Check file size
        if ($file['size'] > $this->maxFileSize) {
            return ['valid' => false, 'message' => 'File size exceeds maximum limit'];
        }
        
        // Check file extension based on category
        $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        $allowedTypes = $category === 'image' ? $this->allowedImageTypes : $this->allowedReportTypes;
        
        if (!in_array($extension, $allowedTypes)) {
            return ['valid' => false, 'message' => 'File type not allowed for this category'];
        }
        
        // Additional image validation
        if ($category === 'image') {
            $imageInfo = getimagesize($file['tmp_name']);
            if (!$imageInfo) {
                return ['valid' => false, 'message' => 'Invalid image file'];
            }
        }
        
        return ['valid' => true];
    }
    
    /**
     * Generate unique filename
     */
    private function generateUniqueFileName($originalName, $category) {
        $extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
        $baseName = pathinfo($originalName, PATHINFO_FILENAME);
        $timestamp = time();
        $random = bin2hex(random_bytes(4));
        
        // Sanitize base name
        $baseName = preg_replace('/[^a-zA-Z0-9_-]/', '_', $baseName);
        $baseName = substr($baseName, 0, 50); // Limit length
        
        return sprintf('%s_%s_%s_%s.%s', 
            $category, 
            $baseName, 
            $timestamp, 
            $random, 
            $extension
        );
    }
    
    /**
     * Get upload path for category
     */
    private function getUploadPath($category) {
        switch ($category) {
            case 'image':
                return $this->uploadDir . 'images/';
            case 'report':
                return $this->uploadDir . 'reports/';
            case 'vehicle':
                return $this->uploadDir . 'vehicles/';
            case 'inspection':
                return $this->uploadDir . 'inspections/';
            default:
                return $this->uploadDir . 'temp/';
        }
    }
    
    /**
     * Save file record to database
     */
    private function saveFileRecord($data) {
        try {
            $stmt = $this->db->prepare("
                INSERT INTO file_storage (
                    original_name, file_name, file_path, file_size, 
                    file_type, category, reference_id, description, 
                    uploaded_by, created_at
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
            ");
            
            $result = $stmt->execute([
                $data['original_name'],
                $data['file_name'],
                $data['file_path'],
                $data['file_size'],
                $data['file_type'],
                $data['category'],
                $data['reference_id'],
                $data['description'],
                $data['uploaded_by']
            ]);
            
            if ($result) {
                $data['id'] = $this->db->lastInsertId();
                return $data;
            }
            
            return false;
            
        } catch (Exception $e) {
            error_log("Failed to save file record: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get file by ID
     */
    public function getFile($fileId) {
        try {
            $stmt = $this->db->prepare("
                SELECT * FROM file_storage 
                WHERE id = ? AND deleted_at IS NULL
            ");
            
            $stmt->execute([$fileId]);
            return $stmt->fetch(PDO::FETCH_ASSOC);
            
        } catch (Exception $e) {
            error_log("Failed to get file: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get files by category and reference
     */
    public function getFiles($category = null, $referenceId = null, $limit = 50, $offset = 0) {
        try {
            $sql = "SELECT * FROM file_storage WHERE deleted_at IS NULL";
            $params = [];
            
            if ($category) {
                $sql .= " AND category = ?";
                $params[] = $category;
            }
            
            if ($referenceId) {
                $sql .= " AND reference_id = ?";
                $params[] = $referenceId;
            }
            
            $sql .= " ORDER BY created_at DESC LIMIT ? OFFSET ?";
            $params[] = $limit;
            $params[] = $offset;
            
            $stmt = $this->db->prepare($sql);
            $stmt->execute($params);
            
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
            
        } catch (Exception $e) {
            error_log("Failed to get files: " . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Delete file
     */
    public function deleteFile($fileId) {
        try {
            // Get file info
            $file = $this->getFile($fileId);
            if (!$file) {
                return ['success' => false, 'message' => 'File not found'];
            }
            
            // Delete physical file
            $filePath = $_SERVER['DOCUMENT_ROOT'] . $file['file_path'];
            if (file_exists($filePath)) {
                unlink($filePath);
            }
            
            // Mark as deleted in database
            $stmt = $this->db->prepare("
                UPDATE file_storage 
                SET deleted_at = NOW(), deleted_by = ?
                WHERE id = ?
            ");
            
            $result = $stmt->execute([$_SESSION['user_id'] ?? null, $fileId]);
            
            if ($result) {
                return ['success' => true, 'message' => 'File deleted successfully'];
            }
            
            return ['success' => false, 'message' => 'Failed to delete file record'];
            
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Delete error: ' . $e->getMessage()];
        }
    }
    
    /**
     * Generate report PDF
     */
    public function generateReportPDF($inspectionId, $data) {
        try {
            require_once __DIR__ . '/../vendor/autoload.php';
            
            // Create new PDF
            $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
            
            // Set document information
            $pdf->SetCreator('AUTO TESTER');
            $pdf->SetAuthor('AUTO TESTER System');
            $pdf->SetTitle('Vehicle Inspection Report - ' . $inspectionId);
            
            // Add a page
            $pdf->AddPage();
            
            // Set font
            $pdf->SetFont('dejavusans', '', 12);
            
            // Build HTML content
            $html = $this->buildReportHTML($data);
            
            // Write HTML content
            $pdf->writeHTML($html, true, false, true, false, '');
            
            // Generate filename
            $fileName = 'report_' . $inspectionId . '_' . date('Y-m-d') . '.pdf';
            $filePath = $this->getUploadPath('report') . $fileName;
            
            // Save PDF
            $pdf->Output($filePath, 'F');
            
            // Save file record
            $fileRecord = $this->saveFileRecord([
                'original_name' => $fileName,
                'file_name' => $fileName,
                'file_path' => str_replace($_SERVER['DOCUMENT_ROOT'], '', $filePath),
                'file_size' => filesize($filePath),
                'file_type' => 'application/pdf',
                'category' => 'report',
                'reference_id' => $inspectionId,
                'description' => 'Vehicle inspection report',
                'uploaded_by' => $_SESSION['user_id'] ?? null
            ]);
            
            if ($fileRecord) {
                return [
                    'success' => true,
                    'file_id' => $fileRecord['id'],
                    'file_url' => $fileRecord['file_path'],
                    'file_name' => $fileName
                ];
            }
            
            return ['success' => false, 'message' => 'Failed to save report record'];
            
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'PDF generation error: ' . $e->getMessage()];
        }
    }
    
    /**
     * Build report HTML
     */
    private function buildReportHTML($data) {
        $html = '
        <h1 style="text-align: center; color: #002b5c;">Vehicle Inspection Report</h1>
        <table style="width: 100%; border-collapse: collapse;">
            <tr style="background-color: #f0f0f0;">
                <th style="border: 1px solid #ddd; padding: 8px;">Inspection ID</th>
                <td style="border: 1px solid #ddd; padding: 8px;">' . htmlspecialchars($data['inspection_id'] ?? '') . '</td>
            </tr>
            <tr style="background-color: #f9f9f9;">
                <th style="border: 1px solid #ddd; padding: 8px;">Vehicle</th>
                <td style="border: 1px solid #ddd; padding: 8px;">' . htmlspecialchars($data['vehicle_info'] ?? '') . '</td>
            </tr>
            <tr style="background-color: #f0f0f0;">
                <th style="border: 1px solid #ddd; padding: 8px;">Date</th>
                <td style="border: 1px solid #ddd; padding: 8px;">' . date('Y-m-d H:i:s') . '</td>
            </tr>
        </table>';
        
        if (isset($data['inspection_points']) && is_array($data['inspection_points'])) {
            $html .= '<h2>Inspection Results</h2>';
            $html .= '<table style="width: 100%; border-collapse: collapse; margin-top: 20px;">';
            $html .= '<tr style="background-color: #002b5c; color: white;">
                        <th style="border: 1px solid #ddd; padding: 8px;">Point</th>
                        <th style="border: 1px solid #ddd; padding: 8px;">Status</th>
                        <th style="border: 1px solid #ddd; padding: 8px;">Notes</th>
                      </tr>';
            
            foreach ($data['inspection_points'] as $point) {
                $statusColor = $point['status'] === 'pass' ? '#28a745' : '#dc3545';
                $html .= '<tr>
                            <td style="border: 1px solid #ddd; padding: 8px;">' . htmlspecialchars($point['name'] ?? '') . '</td>
                            <td style="border: 1px solid #ddd; padding: 8px; color: ' . $statusColor . '; font-weight: bold;">' . htmlspecialchars($point['status'] ?? '') . '</td>
                            <td style="border: 1px solid #ddd; padding: 8px;">' . htmlspecialchars($point['notes'] ?? '') . '</td>
                          </tr>';
            }
            
            $html .= '</table>';
        }
        
        if (isset($data['valuation'])) {
            $html .= '<h2>Vehicle Valuation</h2>';
            $html .= '<table style="width: 100%; border-collapse: collapse; margin-top: 20px;">';
            $html .= '<tr style="background-color: #002b5c; color: white;">
                        <th style="border: 1px solid #ddd; padding: 8px;">Valuation Item</th>
                        <th style="border: 1px solid #ddd; padding: 8px;">Value</th>
                      </tr>';
            
            foreach ($data['valuation'] as $key => $value) {
                $html .= '<tr>
                            <td style="border: 1px solid #ddd; padding: 8px;">' . htmlspecialchars(ucfirst(str_replace('_', ' ', $key))) . '</td>
                            <td style="border: 1px solid #ddd; padding: 8px;">' . htmlspecialchars($value) . '</td>
                          </tr>';
            }
            
            $html .= '</table>';
        }
        
        return $html;
    }
    
    /**
     * Get storage statistics
     */
    public function getStorageStats() {
        try {
            $stats = [];
            
            // Total files
            $stmt = $this->db->prepare("SELECT COUNT(*) as total FROM file_storage WHERE deleted_at IS NULL");
            $stmt->execute();
            $stats['total_files'] = $stmt->fetch()['total_files'];
            
            // Files by category
            $stmt = $this->db->prepare("
                SELECT category, COUNT(*) as count, SUM(file_size) as size 
                FROM file_storage 
                WHERE deleted_at IS NULL 
                GROUP BY category
            ");
            $stmt->execute();
            $stats['by_category'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // Storage usage
            $stmt = $this->db->prepare("SELECT SUM(file_size) as total_size FROM file_storage WHERE deleted_at IS NULL");
            $stmt->execute();
            $totalSize = $stmt->fetch()['total_size'];
            $stats['total_size'] = $totalSize;
            $stats['total_size_mb'] = round($totalSize / 1048576, 2);
            
            // Recent uploads
            $stmt = $this->db->prepare("
                SELECT * FROM file_storage 
                WHERE deleted_at IS NULL 
                ORDER BY created_at DESC 
                LIMIT 10
            ");
            $stmt->execute();
            $stats['recent_files'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            return ['success' => true, 'data' => $stats];
            
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Stats error: ' . $e->getMessage()];
        }
    }
    
    /**
     * Clean up temporary files
     */
    public function cleanupTempFiles($olderThanHours = 24) {
        try {
            $tempDir = $this->uploadDir . 'temp/';
            $cutoffTime = time() - ($olderThanHours * 3600);
            
            $files = glob($tempDir . '*');
            $deletedCount = 0;
            
            foreach ($files as $file) {
                if (filemtime($file) < $cutoffTime) {
                    if (unlink($file)) {
                        $deletedCount++;
                    }
                }
            }
            
            return [
                'success' => true,
                'message' => "Cleaned up {$deletedCount} temporary files"
            ];
            
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Cleanup error: ' . $e->getMessage()];
        }
    }
    
    /**
     * Create backup of files
     */
    public function createBackup($category = null) {
        try {
            $backupDir = $this->uploadDir . 'backups/' . date('Y-m-d_H-i-s') . '/';
            mkdir($backupDir, 0755, true);
            
            $sourceDir = $category ? $this->getUploadPath($category) : $this->uploadDir;
            
            // Copy files
            $this->copyDirectory($sourceDir, $backupDir);
            
            // Create backup record
            $backupRecord = $this->saveFileRecord([
                'original_name' => 'backup_' . ($category ?? 'all') . '_' . date('Y-m-d_H-i-s'),
                'file_name' => 'backup_' . ($category ?? 'all') . '_' . date('Y-m-d_H-i-s'),
                'file_path' => str_replace($_SERVER['DOCUMENT_ROOT'], '', $backupDir),
                'file_size' => $this->getDirectorySize($backupDir),
                'file_type' => 'application/zip',
                'category' => 'backup',
                'reference_id' => null,
                'description' => 'System backup - ' . ($category ?? 'all files'),
                'uploaded_by' => $_SESSION['user_id'] ?? null
            ]);
            
            return [
                'success' => true,
                'message' => 'Backup created successfully',
                'backup_path' => $backupDir
            ];
            
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Backup error: ' . $e->getMessage()];
        }
    }
    
    /**
     * Helper: Copy directory
     */
    private function copyDirectory($source, $destination) {
        if (!is_dir($destination)) {
            mkdir($destination, 0755, true);
        }
        
        $files = scandir($source);
        foreach ($files as $file) {
            if ($file !== '.' && $file !== '..') {
                $sourcePath = $source . '/' . $file;
                $destPath = $destination . '/' . $file;
                
                if (is_dir($sourcePath)) {
                    $this->copyDirectory($sourcePath, $destPath);
                } else {
                    copy($sourcePath, $destPath);
                }
            }
        }
    }
    
    /**
     * Helper: Get directory size
     */
    private function getDirectorySize($dir) {
        $size = 0;
        $files = glob(rtrim($dir, '/') . '/*', GLOB_MARK);
        
        foreach ($files as $file) {
            if (is_dir($file)) {
                $size += $this->getDirectorySize($file);
            } else {
                $size += filesize($file);
            }
        }
        
        return $size;
    }
}

// API Endpoints
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

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

$fileStorage = new FileStorage();
$endpoint = $_GET['endpoint'] ?? 'upload';

switch ($endpoint) {
    case 'upload':
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $category = $_POST['category'] ?? 'temp';
            $referenceId = $_POST['reference_id'] ?? null;
            $description = $_POST['description'] ?? '';
            
            if (isset($_FILES['file'])) {
                $result = $fileStorage->uploadFile($_FILES['file'], $category, $referenceId, $description);
                echo json_encode($result);
            } else {
                echo json_encode(['success' => false, 'message' => 'No file uploaded']);
            }
        }
        break;
        
    case 'get':
        if ($_SERVER['REQUEST_METHOD'] === 'GET') {
            $category = $_GET['category'] ?? null;
            $referenceId = $_GET['reference_id'] ?? null;
            $limit = $_GET['limit'] ?? 50;
            $offset = $_GET['offset'] ?? 0;
            
            $files = $fileStorage->getFiles($category, $referenceId, $limit, $offset);
            echo json_encode(['success' => true, 'data' => $files]);
        }
        break;
        
    case 'delete':
        if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
            $fileId = $_GET['file_id'] ?? null;
            if ($fileId) {
                $result = $fileStorage->deleteFile($fileId);
                echo json_encode($result);
            } else {
                echo json_encode(['success' => false, 'message' => 'File ID required']);
            }
        }
        break;
        
    case 'generate_report':
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $inspectionId = $_POST['inspection_id'] ?? null;
            $data = json_decode($_POST['data'] ?? '{}', true);
            
            if ($inspectionId && $data) {
                $result = $fileStorage->generateReportPDF($inspectionId, $data);
                echo json_encode($result);
            } else {
                echo json_encode(['success' => false, 'message' => 'Inspection ID and data required']);
            }
        }
        break;
        
    case 'stats':
        if ($_SERVER['REQUEST_METHOD'] === 'GET') {
            $stats = $fileStorage->getStorageStats();
            echo json_encode($stats);
        }
        break;
        
    case 'cleanup':
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $olderThan = $_POST['older_than_hours'] ?? 24;
            $result = $fileStorage->cleanupTempFiles($olderThan);
            echo json_encode($result);
        }
        break;
        
    case 'backup':
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $category = $_POST['category'] ?? null;
            $result = $fileStorage->createBackup($category);
            echo json_encode($result);
        }
        break;
        
    default:
        echo json_encode(['success' => false, 'message' => 'Invalid endpoint']);
}
?>
