<?php
// process_request.php
session_start();
require_once '../config/database.php';
require_once '../config/location_validator.php';
require_once '../includes/app_helpers.php';
require_once '../includes/chat_helper.php';

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

$response = ['success' => false, 'message' => '', 'data' => null];

function cx_request_post_value(string $key, $default = '') {
    return isset($_POST[$key]) ? trim((string)$_POST[$key]) : $default;
}

function cx_request_date_or_null($value) {
    $value = trim((string)$value);
    if ($value === '') {
        return null;
    }
    $dt = DateTime::createFromFormat('Y-m-d', $value);
    return ($dt && $dt->format('Y-m-d') === $value) ? $value : null;
}


// Add a unique token to prevent duplicate submissions
if (!isset($_POST['submit_token'])) {
    $_POST['submit_token'] = uniqid('', true);
}

// Check if this token has been processed before (optional - requires session storage)
if (isset($_SESSION['processed_tokens']) && in_array($_POST['submit_token'], $_SESSION['processed_tokens'])) {
    $response['message'] = "This form has already been submitted.";
    echo json_encode($response);
    exit;
}

// Log received data for debugging
error_log("=== New Request Submission ===");
error_log("Submit Token: " . ($_POST['submit_token'] ?? 'none'));
error_log("Received POST data: " . print_r($_POST, true));
error_log("Received FILES data: " . print_r($_FILES, true));

if($_SERVER['REQUEST_METHOD'] == 'POST') {
    try {
        $database = new Database();
        $db = $database->getConnection();
        $validator = new LocationValidator($db);
        ensureOperationalTables($db);
        ensureAddressAndCallQueueTables($db);
        ensureUnifiedTicketWorkflow($db);
        
        // CX submissions are tied to the logged-in customer when available.
        $customer_id = isset($_SESSION['customer_id']) ? (int)$_SESSION['customer_id'] : null;
        $customer_defaults = [];
        if ($customer_id) {
            try {
                $customer_stmt = $db->prepare("SELECT c.*, ci.city_name AS registered_city_name, ci.state AS registered_city_state, ci.region AS registered_city_region
                                               FROM customers c
                                               LEFT JOIN cities ci ON ci.id = c.city_id
                                               WHERE c.id = :id
                                               LIMIT 1");
                $customer_stmt->execute([':id' => $customer_id]);
                $customer_defaults = $customer_stmt->fetch(PDO::FETCH_ASSOC) ?: [];
            } catch (Throwable $e) {
                error_log('CX request process prefill fallback warning: ' . $e->getMessage());
            }
        }

        $default_full_name = trim(($customer_defaults['first_name'] ?? '') . ' ' . ($customer_defaults['last_name'] ?? ''));
        $full_name = cx_request_post_value('full_name', '') ?: $default_full_name;
        $phone_number = cx_request_post_value('phone_number', '') ?: trim((string)($customer_defaults['phone_number'] ?? ''));
        $secondary_phone = cx_request_post_value('secondary_phone', '');
        $customer_email = cx_request_post_value('customer_email', cx_request_post_value('email', '')) ?: trim((string)($customer_defaults['email'] ?? ''));
        $service_address = cx_request_post_value('service_address', '') ?: trim((string)($customer_defaults['address'] ?? ''));
        $address_note = cx_request_post_value('service_address_2', cx_request_post_value('address_note', ''));
        $zip_code = cx_request_post_value('zip_code', '') ?: trim((string)($customer_defaults['zip_code'] ?? ''));
        $city_id = isset($_POST['city_id']) && $_POST['city_id'] !== '' ? (int)$_POST['city_id'] : (int)($customer_defaults['city_id'] ?? 0);
        $product_model_version = cx_request_post_value('product_model_version', '');
        $purchase_date = cx_request_date_or_null(cx_request_post_value('purchase_date', ''));
        $warranty_type = cx_request_post_value('warranty_type', '');
        $preferred_date = cx_request_date_or_null(cx_request_post_value('preferred_date', ''));
        // Preferred time is intentionally not collected on the CX form.
        $preferred_time = null;
        $issue_description = cx_request_post_value('issue_description', '');
        $special_request = cx_request_post_value('special_request', '');

        // Validate required fields
        if(empty($zip_code)) {
            $response['message'] = "ZIP code is required.";
            echo json_encode($response);
            exit;
        }
        if($customer_email !== '' && !filter_var($customer_email, FILTER_VALIDATE_EMAIL)) {
            $response['message'] = "Please enter a valid customer email.";
            echo json_encode($response);
            exit;
        }
        
        // Validate zip code from the service_areas master coverage table.
        $location_data = $validator->validateZipCode($zip_code);
        
        if(!$location_data) {
            $response['message'] = "Sorry, we don't service this zip code yet. Please check our serviceable areas.";
            echo json_encode($response);
            exit;
        }
        
        $zip_meta = getZipAddressMeta($db, $zip_code);
        if ($zip_meta) {
            $city_id = (int)($zip_meta['city_id'] ?? 0);
        }
        if(empty($city_id)) {
            $city_id = (int)($location_data['city_id'] ?? 0);
        }
        if(empty($city_id)) {
            $response['message'] = "City could not be resolved for this ZIP code. Please contact admin to check service coverage.";
            echo json_encode($response);
            exit;
        }
        $address_region = $zip_meta['region'] ?? ($_POST['region'] ?? null);
        $address_state = $zip_meta['state'] ?? ($_POST['state'] ?? null);

        // Generate unique request number
        $request_number = 'SRV-' . date('Ymd') . '-' . rand(1000, 9999);
        
        // Handle manual brand/appliance type entries
        $brand_id = null;
        if(isset($_POST['brand_id']) && !empty($_POST['brand_id'])) {
            $brand_id = intval($_POST['brand_id']);
        }
        
        $appliance_type_id = null;
        if(isset($_POST['appliance_type_id']) && !empty($_POST['appliance_type_id'])) {
            $appliance_type_id = intval($_POST['appliance_type_id']);
        }
        
        $manual_brand = cx_request_post_value('manual_brand', '');
        $manual_appliance_type = cx_request_post_value('manual_appliance_type', '');

        if (!$brand_id && $manual_brand === '') {
            $response['message'] = "Brand is required.";
            echo json_encode($response);
            exit;
        }
        if (!$appliance_type_id && $manual_appliance_type === '') {
            $response['message'] = "Product category is required.";
            echo json_encode($response);
            exit;
        }

        // Insert service request. Source is forced by the backend so CX cannot accidentally submit as CSR/manual.
        $query = "INSERT INTO service_requests (
            customer_id, request_number, ticket_source, source_system, origin_type,
            brand_id, appliance_type_id, model_number, serial_number, product_model_version,
            full_name, phone_number, secondary_phone, customer_email,
            service_address, service_address_2, region, city_id, state, zip_code, landmark,
            urgency_level_id, job_status_id, issue_description, special_request,
            purchase_date, warranty_type, call_received_date, preferred_date, preferred_time,
            location_id, is_serviceable, manual_brand, manual_appliance_type, last_updated_at, verification_status
        ) VALUES (
            :customer_id, :request_number, :ticket_source, :source_system, :origin_type,
            :brand_id, :appliance_type_id, :model_number, :serial_number, :product_model_version,
            :full_name, :phone_number, :secondary_phone, :customer_email,
            :service_address, :service_address_2, :region, :city_id, :state, :zip_code, :landmark,
            :urgency_level_id, 1, :issue_description, :special_request,
            :purchase_date, :warranty_type, :call_received_date, :preferred_date, :preferred_time,
            :location_id, 1, :manual_brand, :manual_appliance_type, NOW(), 'pending'
        )";
        
        $stmt = $db->prepare($query);
        
        $params = [
            ':customer_id' => $customer_id,
            ':request_number' => $request_number,
            ':ticket_source' => 'cx_online',
            ':source_system' => 'php_cx',
            ':origin_type' => 'CX Submission',
            ':brand_id' => $brand_id,
            ':appliance_type_id' => $appliance_type_id,
            ':model_number' => cx_request_post_value('model_number', '') ?: null,
            ':serial_number' => cx_request_post_value('serial_number', '') ?: null,
            ':product_model_version' => $product_model_version ?: null,
            ':full_name' => $full_name,
            ':phone_number' => $phone_number,
            ':secondary_phone' => $secondary_phone ?: null,
            ':customer_email' => $customer_email,
            ':service_address' => $service_address,
            ':service_address_2' => $address_note ?: null,
            ':region' => $address_region,
            ':city_id' => $city_id,
            ':state' => $address_state,
            ':zip_code' => $zip_code,
            ':landmark' => $address_note ?: null,
            // CX side no longer asks for urgency; keep backend default as Normal for dashboard compatibility.
            ':urgency_level_id' => 1,
            ':issue_description' => $issue_description,
            ':special_request' => $special_request ?: null,
            ':purchase_date' => $purchase_date,
            ':warranty_type' => $warranty_type,
            ':call_received_date' => date('Y-m-d'),
            ':preferred_date' => $preferred_date,
            ':preferred_time' => null,
            ':location_id' => $zip_meta['location_id'] ?? ($location_data['location_id'] ?? null),
            ':manual_brand' => $manual_brand ?: null,
            ':manual_appliance_type' => $manual_appliance_type ?: null
        ];
        
        // Check if all required fields are present
        $required_values = [
            'Name' => $params[':full_name'],
            'Primary Phone' => $params[':phone_number'],
            'Email' => $params[':customer_email'],
            'Address' => $params[':service_address'],
            'Model' => $params[':model_number'],
            'Serial' => $params[':serial_number'],
            'Warranty Type' => $params[':warranty_type'],
            'Problem Description' => $params[':issue_description'],
            'Cx Preferred Date' => $params[':preferred_date']
        ];
        foreach($required_values as $label => $value) {
            if($value === null || $value === '' || $value === 0) {
                $response['message'] = $label . " is required.";
                echo json_encode($response);
                exit;
            }
        }
        
        // Start transaction only after all server-side validation passes.
        $db->beginTransaction();
        
        if($stmt->execute($params)) {
            $request_id = $db->lastInsertId();
            
            // ============================================
            // IMAGE UPLOAD HANDLING - FIXED TO PREVENT DUPLICATES
            // ============================================
            $uploaded_count = 0;
            $failed_count = 0;
            $processed_files = []; // Track processed files to prevent duplicates
            
            if(isset($_FILES['images']) && !empty($_FILES['images']['name'][0])) {
                
                // Check if files were already processed for this request
                $check_duplicate = $db->prepare("SELECT COUNT(*) as count FROM request_images WHERE request_id = ?");
                $check_duplicate->execute([$request_id]);
                $existing_count = $check_duplicate->fetch(PDO::FETCH_ASSOC)['count'];
                
                // Only process if no images exist yet for this request
                if($existing_count == 0) {
                    $upload_base_dir = '../uploads/requests/';
                    $upload_dir = $upload_base_dir . $request_id . '/';
                    
                    // Create safe upload directories
                    safeUploadDirectory($upload_base_dir);
                    safeUploadDirectory($upload_dir);
                    
                    // Process each uploaded file
                    foreach($_FILES['images']['tmp_name'] as $key => $tmp_name) {
                        // Skip if no file
                        if(empty($tmp_name) || $_FILES['images']['error'][$key] != 0) {
                            continue;
                        }
                        
                        $file_name = $_FILES['images']['name'][$key];
                        $file_size = $_FILES['images']['size'][$key];
                        
                        // Create a unique file identifier to prevent duplicates
                        $file_identifier = $file_name . '_' . $file_size;
                        
                        // Skip if we've already processed this file in this session
                        if(in_array($file_identifier, $processed_files)) {
                            error_log("Skipping duplicate file: $file_name");
                            continue;
                        }
                        
                        $processed_files[] = $file_identifier;
                        
                        $validation = validateUploadedImage($tmp_name, $file_name, $file_size);
                        
                        if($validation['success']) {
                            // File is a real image, valid MIME type, and 5MB or smaller
                            $file_ext = $validation['extension'];
                            $new_file_name = time() . '_' . bin2hex(random_bytes(8)) . '.' . $file_ext;
                            $relative_path = 'uploads/requests/' . $request_id . '/' . $new_file_name;
                            $full_path = $upload_dir . $new_file_name;
                                
                                // Double-check if this exact file already exists in database
                                $check_file = $db->prepare("SELECT id FROM request_images WHERE request_id = ? AND original_name = ? AND file_size = ?");
                                $check_file->execute([$request_id, $file_name, $file_size]);
                                
                                if($check_file->rowCount() == 0) {
                                    if(move_uploaded_file($tmp_name, $full_path)) {
                                        // Save to request_images table
                                        $image_query = "INSERT INTO request_images (request_id, image_path, original_name, file_size, mime_type) 
                                                        VALUES (:request_id, :image_path, :original_name, :file_size, :mime_type)";
                                        $image_stmt = $db->prepare($image_query);
                                        
                                        $mime_type = $validation['mime'];
                                        
                                        if($image_stmt->execute([
                                            ':request_id' => $request_id,
                                            ':image_path' => $relative_path,
                                            ':original_name' => $file_name,
                                            ':file_size' => $file_size,
                                            ':mime_type' => $mime_type
                                        ])) {
                                            $uploaded_count++;
                                            error_log("Successfully uploaded and saved image: $file_name for request #$request_id");
                                        } else {
                                            $failed_count++;
                                            error_log("Failed to save image record for: $file_name");
                                        }
                                    } else {
                                        $failed_count++;
                                        error_log("Failed to move uploaded file: $file_name");
                                    }
                                } else {
                                    $failed_count++;
                                    error_log("File already exists in database: $file_name");
                                }
                        } else {
                            $failed_count++;
                            error_log("Invalid upload for $file_name: " . ($validation['message'] ?? 'unknown reason'));
                        }
                    }
                } else {
                    error_log("Images already exist for request #$request_id. Skipping upload.");
                }
            }
            
            // Add to status history
            $history_query = "INSERT INTO request_status_history (request_id, job_status_id, notes) 
                              VALUES (:request_id, 1, 'Request submitted successfully')";
            $history_stmt = $db->prepare($history_query);
            $history_stmt->execute([':request_id' => $request_id]);
            
            // ============================================
            // NOTIFICATION HANDLING - FIXED TO PREVENT DUPLICATES
            // ============================================
            // If customer is logged in, create notification ONLY if it doesn't already exist
            if($customer_id) {
                // Check if a notification already exists for this request
                $check_notif = $db->prepare("SELECT id FROM notifications WHERE customer_id = ? AND link LIKE ?");
                $check_notif->execute([$customer_id, "%request_id=$request_id%"]);
                
                if($check_notif->rowCount() == 0) {
                    $notif_query = "INSERT INTO notifications (customer_id, title, message, type, link) 
                                    VALUES (:customer_id, :title, :message, 'success', :link)";
                    $notif_stmt = $db->prepare($notif_query);
                    $notif_stmt->execute([
                        ':customer_id' => $customer_id,
                        ':title' => 'Service Request Received',
                        ':message' => "Your service request #$request_number has been received and is waiting for verification by our support team.",
                        ':link' => "my_requests.php?request_id=$request_id"
                    ]);
                    error_log("Notification created for customer #$customer_id, request #$request_id");
                } else {
                    error_log("Notification already exists for customer #$customer_id, request #$request_id. Skipping.");
                }
            }
            
            // Commit transaction
            $db->commit();

            // Notify CSR users that this customer submission needs verification first.
            try {
                $csrNotif = $db->prepare("INSERT INTO csr_notifications (csr_id, title, message, type, link, reference_id, reference_type, created_at)
                                         SELECT id, :title, :message, 'warning', :link, :request_id, 'verification', NOW()
                                         FROM csr_users
                                         WHERE is_active = 1");
                $csrNotif->execute([
                    ':title' => 'New Request Needs Verification',
                    ':message' => 'Customer request #' . $request_number . ' is waiting in the Verification Queue.',
                    ':link' => 'verification_queue.php?request_id=' . (int)$request_id,
                    ':request_id' => (int)$request_id
                ]);
            } catch (Throwable $verificationNotifError) {
                error_log('CX request verification notification warning: ' . $verificationNotifError->getMessage());
            }

            // Chat room will be created only after CSR approves the request.
            
            // Store processed token to prevent double submission
            if (!isset($_SESSION['processed_tokens'])) {
                $_SESSION['processed_tokens'] = [];
            }
            $_SESSION['processed_tokens'][] = $_POST['submit_token'];
            // Keep only last 10 tokens to prevent session bloat
            if (count($_SESSION['processed_tokens']) > 10) {
                array_shift($_SESSION['processed_tokens']);
            }
            
            $response['success'] = true;
            $response['message'] = "Request submitted successfully and is now waiting for CSR verification. Request number: " . $request_number;
            $response['data'] = [
                'request_number' => $request_number,
                'request_id' => $request_id,
                'city' => $location_data['city_name'],
                'location' => $location_data['location_name'],
                'is_logged_in' => $customer_id ? true : false,
                'images_uploaded' => $uploaded_count,
                'images_failed' => $failed_count
            ];
            
            // If user is logged in, add redirect to customer dashboard
            if($customer_id) {
                $response['data']['redirect'] = '/customer/dashboard.php';
            }
        } else {
            // Rollback transaction on error
            $db->rollBack();
            $errorInfo = $stmt->errorInfo();
            $response['message'] = "Error submitting request: " . $errorInfo[2];
            error_log("SQL Error in process_request.php: " . print_r($errorInfo, true));
        }
        
    } catch(PDOException $e) {
        // Rollback transaction on error
        if(isset($db) && $db->inTransaction()) {
            $db->rollBack();
        }
        $response['message'] = "Database error: " . $e->getMessage();
        error_log("Database error in process_request.php: " . $e->getMessage());
    } catch(Exception $e) {
        // Rollback transaction on error
        if(isset($db) && $db->inTransaction()) {
            $db->rollBack();
        }
        $response['message'] = "Error: " . $e->getMessage();
        error_log("General error in process_request.php: " . $e->getMessage());
    }
}

echo json_encode($response);
?>