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

header('Content-Type: application/json');

// Check if user is logged in and has admin access
if (!isset($_SESSION['user_id']) || $_SESSION['role_id'] !== 1) {
    http_response_code(403);
    echo json_encode(['success' => false, 'error' => 'Insufficient permissions. Not Authorized.']);
    exit;
}

function handleLogoUpload() {
    if (!isset($_FILES['company_logo']) || $_FILES['company_logo']['error'] === UPLOAD_ERR_NO_FILE) {
        return null;
    }

    $file = $_FILES['company_logo'];
    
    // Validate file
    $allowed = ['image/png', 'image/jpeg', 'image/gif'];
    if (!in_array($file['type'], $allowed)) {
        throw new Exception('Invalid file type. Only PNG, JPG and GIF files are allowed.');
    }

    if ($file['size'] > 2097152) { // 2MB
        throw new Exception('File too large. Maximum size is 2MB.');
    }

    // Create upload directory if it doesn't exist
    $upload_dir = 'uploads/logos/';
    if (!is_dir($upload_dir)) {
        mkdir($upload_dir, 0755, true);
    }

    // Generate unique filename
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    $filename = 'company_logo_' . time() . '.' . $ext;
    $filepath = $upload_dir . $filename;

    // Move uploaded file
    if (!move_uploaded_file($file['tmp_name'], $filepath)) {
        throw new Exception('Failed to save logo file.');
    }

    return $filepath;
}

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

    // Handle logo removal if requested
    if (isset($_POST['action']) && $_POST['action'] === 'remove_logo') {
        $sql = "SELECT setting_value FROM settings WHERE setting_key = 'company_logo'";
        $result = $conn->query($sql);
        if ($row = $result->fetch_assoc()) {
            $old_logo = $row['setting_value'];
            if (file_exists($old_logo)) {
                unlink($old_logo);
            }
        }
        
        $sql = "UPDATE settings SET setting_value = NULL WHERE setting_key = 'company_logo'";
        $conn->query($sql);
        
        $conn->commit();
        echo json_encode(['success' => true]);
        exit;
    }

    // Define required fields and their validation rules
    $settings = [
        'system_name' => ['required' => true],
        'default_currency' => ['required' => true],
        'address' => ['required' => true],
        'tel_1' => ['required' => true],
        'tel_2' => ['required' => false],
        'phcf_percentage' => ['required' => true, 'type' => 'float', 'min' => 0, 'max' => 100],
        'stamp_duty' => ['required' => true, 'type' => 'float', 'min' => 0],
        'training_levy' => ['required' => true, 'type' => 'float', 'min' => 0, 'max' => 100],
        'email_host' => ['required' => true],
        'email_port' => ['required' => true, 'type' => 'int', 'min' => 1, 'max' => 65535],
        'email_username' => ['required' => true],
        'email_password' => ['required' => true],
        'email_sender' => ['required' => true, 'type' => 'email'],
        'dkim_domain' => ['required' => false],
        'dkim_private_key' => ['required' => false]
    ];

    // Get current settings for comparison
    $current_settings = [];
    $sql_current = "SELECT setting_key, setting_value FROM settings";
    $result = $conn->query($sql_current);
    while ($row = $result->fetch_assoc()) {
        $current_settings[$row['setting_key']] = $row['setting_value'];
    }

    // Process logo upload if present
    $logo_path = handleLogoUpload();
    if ($logo_path) {
        // Delete old logo if exists
        if (!empty($current_settings['company_logo']) && file_exists($current_settings['company_logo'])) {
            unlink($current_settings['company_logo']);
        }
        $settings['company_logo'] = ['required' => false];
        $_POST['company_logo'] = $logo_path;
    }

    // Validate and sanitize inputs
    $validated_settings = [];
    $changes = [];

    foreach ($settings as $key => $rules) {
        $value = $_POST[$key] ?? null;
        
        // Check required fields
        if ($rules['required'] && empty($value)) {
            throw new Exception("$key is required");
        }

        // Type validation if value is not empty
        if (!empty($value) && isset($rules['type'])) {
            switch ($rules['type']) {
                case 'float':
                    if (!is_numeric($value)) {
                        throw new Exception("$key must be a valid number");
                    }
                    $value = floatval($value);
                    if (isset($rules['min']) && $value < $rules['min']) {
                        throw new Exception("$key cannot be less than {$rules['min']}");
                    }
                    if (isset($rules['max']) && $value > $rules['max']) {
                        throw new Exception("$key cannot be more than {$rules['max']}");
                    }
                    break;

                case 'int':
                    if (!filter_var($value, FILTER_VALIDATE_INT)) {
                        throw new Exception("$key must be a valid integer");
                    }
                    $value = intval($value);
                    if (isset($rules['min']) && $value < $rules['min']) {
                        throw new Exception("$key cannot be less than {$rules['min']}");
                    }
                    if (isset($rules['max']) && $value > $rules['max']) {
                        throw new Exception("$key cannot be more than {$rules['max']}");
                    }
                    break;

                case 'email':
                    if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
                        throw new Exception("$key must be a valid email address");
                    }
                    break;
            }
        }

        $validated_settings[$key] = $value;

        // Track changes
        if (!isset($current_settings[$key]) || $current_settings[$key] !== $value) {
            // Handle sensitive data
            if (in_array($key, ['email_password', 'dkim_private_key'])) {
                $changes[$key] = [
                    'old' => '********',
                    'new' => '********'
                ];
            } else {
                $changes[$key] = [
                    'old' => $current_settings[$key] ?? null,
                    'new' => $value
                ];
            }
        }
    }

    // Update settings in database
    $stmt = $conn->prepare("INSERT INTO settings (setting_key, setting_value) 
                           VALUES (?, ?) 
                           ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)");

    foreach ($validated_settings as $key => $value) {
        $stmt->bind_param('ss', $key, $value);
        if (!$stmt->execute()) {
            throw new Exception("Failed to save setting: $key");
        }
    }

    // Log changes if any were made
    if (!empty($changes)) {
        $sql = "INSERT INTO activity_log (
                    user_id, 
                    action, 
                    table_name, 
                    record_id,
                    old_values,
                    new_values,
                    ip_address,
                    user_agent,
                    action_date,
                    additional_info
                ) VALUES (?, 'UPDATE', 'settings', 'SYSTEM', ?, ?, ?, ?, NOW(), ?)";
                
        $stmt = $conn->prepare($sql);
        
        $user_id = $_SESSION['user_id'];
        $old_values = json_encode(array_column($changes, 'old'));
        $new_values = json_encode(array_column($changes, 'new'));
        $ip = $_SERVER['REMOTE_ADDR'];
        $user_agent = $_SERVER['HTTP_USER_AGENT'];
        $additional_info = json_encode([
            'modified_settings' => array_keys($changes),
            'total_changes' => count($changes)
        ]);
        
        $stmt->bind_param('ssssss', 
            $user_id,
            $old_values,
            $new_values,
            $ip,
            $user_agent,
            $additional_info
        );
        
        if (!$stmt->execute()) {
            throw new Exception("Failed to log changes");
        }
    }

    // Test email settings if they were changed
    $email_settings = ['email_host', 'email_port', 'email_username', 
                      'email_password', 'email_sender'];
    
    if (array_intersect(array_keys($changes), $email_settings)) {
        require_once 'vendor/phpmailer/src/PHPMailer.php';
        require_once 'vendor/phpmailer/src/SMTP.php';
        require_once 'vendor/phpmailer/src/Exception.php';
        
        $mail = new PHPMailer\PHPMailer\PHPMailer(true);
        
        try {
            $mail->isSMTP();
            $mail->Host = $validated_settings['email_host'];
            $mail->SMTPAuth = true;
            $mail->Username = $validated_settings['email_username'];
            $mail->Password = $validated_settings['email_password'];
            $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
            $mail->Port = $validated_settings['email_port'];
            
            // Test connection only
            $mail->SMTPAuth = true;
            $mail->SMTPDebug = 0;
            $mail->connect();
            $mail->quit();
            
        } catch (Exception $e) {
            throw new Exception("Email settings test failed: " . $e->getMessage());
        }
    }

    // Commit transaction
    $conn->commit();

    echo json_encode([
        'success' => true,
        'message' => 'Settings saved successfully'
    ]);

} catch (Exception $e) {
    // Rollback on error
    if ($conn->inTransaction()) {
        $conn->rollback();
    }
    
    echo json_encode([
        'success' => false,
        'error' => $e->getMessage()
    ]);
}

$conn->close();
?>