<?php
header('Content-Type: application/json');
require_once '../../config/config.php';
require_once '../../config/middleware.php';

// require_api_permission('shipment', 'is_add');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['status' => 'error', 'message' => 'Invalid request method']);
    exit;
}

try {
    $currentUser = get_current_user_info();
    $createdBy = $currentUser['id'] ?? ($_SESSION['user_id'] ?? 1);

    // Required base fields
    $courierId = isset($_POST['courier_id']) ? (int) $_POST['courier_id'] : 0;
    $pickupPointId = isset($_POST['pickup_point_id']) ? (int) $_POST['pickup_point_id'] : 0;
    $bookingRefId = !empty($_POST['booking_ref_id']) ? sanitizeText($_POST['booking_ref_id']) : 'ORD-' . time();

    // Consignee
    $consigneeName = sanitizeText($_POST['consignee_name'] ?? '');
    $consigneePhone = sanitizeText($_POST['consignee_phone'] ?? '');
    $consigneeAddress = sanitizeText($_POST['consignee_address'] ?? '');
    $consigneePin = sanitizeText($_POST['consignee_pin'] ?? '');
    $consigneeCity = sanitizeText($_POST['consignee_city'] ?? '');
    $consigneeState = sanitizeText($_POST['consignee_state'] ?? '');
    $consigneeCountry = sanitizeText($_POST['consignee_country'] ?? 'India');
    $consigneeEmail = sanitizeText($_POST['consignee_email'] ?? '');
    $consigneeGst = sanitizeText($_POST['consignee_gst'] ?? '');

    // Consignor
    $shipperName = sanitizeText($_POST['shipper_name'] ?? '');
    $shipperPhone = sanitizeText($_POST['shipper_phone'] ?? '');
    $shipperAddress = sanitizeText($_POST['shipper_address'] ?? '');
    $shipperPin = sanitizeText($_POST['shipper_pin'] ?? '');
    $shipperCity = sanitizeText($_POST['shipper_city'] ?? '');
    $shipperState = sanitizeText($_POST['shipper_state'] ?? '');

    // Invoice & RTO
    $invoiceNo = sanitizeText($_POST['invoice_no'] ?? '');
    $invoiceValue = (float) ($_POST['invoice_value'] ?? 0);
    $ewaybillNo = sanitizeText($_POST['ewaybill_no'] ?? '');

    $rtoName = sanitizeText($_POST['rto_name'] ?? '');
    $rtoPhone = sanitizeText($_POST['rto_phone'] ?? '');
    $rtoAddress = sanitizeText($_POST['rto_address'] ?? '');
    if ($rtoName === '' && $rtoPhone === '' && $rtoAddress === '') {
        $rtoName = $shipperName;
        $rtoPhone = $shipperPhone;
        $rtoAddress = $shipperAddress;
    }

    // Shipment details
    $paymentMode = sanitizeText($_POST['payment_mode'] ?? 'Prepaid');
    $codAmount = (float) ($_POST['cod_amount'] ?? 0);
    $shippingMode = sanitizeText($_POST['shipping_mode'] ?? 'Surface');
    $productDesc = sanitizeText($_POST['product_desc'] ?? '');

    // Package arrays
    $lengths = $_POST['length'] ?? [];
    $widths = $_POST['width'] ?? [];
    $heights = $_POST['height'] ?? [];
    $boxes = $_POST['boxes'] ?? [];
    $actualWeights = $_POST['actual_weight'] ?? [];
    $chargedWeights = $_POST['charged_weight'] ?? [];

    if ($courierId <= 0 || $pickupPointId <= 0 || $consigneeName === '' || $consigneePhone === '' || $consigneeAddress === '' || $consigneePin === '') {
        throw new Exception('Missing required fields (Courier, Pickup Point, Consignee details)');
    }

    if (empty($lengths) || count($lengths) !== count($widths) || count($lengths) !== count($heights) || count($lengths) !== count($boxes) || count($lengths) !== count($actualWeights) || count($lengths) !== count($chargedWeights)) {
        throw new Exception('Package rows are missing or incomplete');
    }

    // Prepare package payload
    $packageDetails = [];
    $totalActualWeight = 0.0;
    $totalChargedWeight = 0.0;
    $totalBoxes = 0;
    $maxL = 0.0;
    $maxW = 0.0;
    $maxH = 0.0;

    for ($i = 0; $i < count($lengths); $i++) {
        $qty = max(1, (int) ($boxes[$i] ?? 1));
        $actWt = max(0, (float) ($actualWeights[$i] ?? 0));
        $chgWt = max(0, (float) ($chargedWeights[$i] ?? 0));
        $len = max(0, (float) ($lengths[$i] ?? 0));
        $wid = max(0, (float) ($widths[$i] ?? 0));
        $hei = max(0, (float) ($heights[$i] ?? 0));

        $totalBoxes += $qty;
        $totalActualWeight += ($actWt * $qty);
        $totalChargedWeight += $chgWt;

        $packageDetails[] = [
            'length' => $len,
            'width' => $wid,
            'height' => $hei,
            'boxes' => $qty,
            'actual_weight' => $actWt,
            'charged_weight' => $chgWt
        ];

        if ($len > $maxL) {
            $maxL = $len;
        }
        if ($wid > $maxW) {
            $maxW = $wid;
        }
        if ($hei > $maxH) {
            $maxH = $hei;
        }
    }

    if ($totalBoxes <= 0) {
        throw new Exception('At least one valid package is required');
    }

    $packageDetailsJson = json_encode($packageDetails);
    $weightGrams = $totalActualWeight > 0 ? round($totalActualWeight * 1000, 2) : round($totalChargedWeight * 1000, 2);

    // Fetch courier config
    $courierStmt = $pdo->prepare("SELECT id, partner_name, partner_code, api_key, api_url FROM tbl_courier_partner WHERE id = :id");
    $courierStmt->execute([':id' => $courierId]);
    $courierData = $courierStmt->fetch(PDO::FETCH_ASSOC);
    if (!$courierData) {
        throw new Exception('Invalid Courier Partner ID');
    }

    // Fetch pickup point
    $pickupStmt = $pdo->prepare("SELECT id, name FROM tbl_pickup_points WHERE id = :id");
    $pickupStmt->execute([':id' => $pickupPointId]);
    $pickupPoint = $pickupStmt->fetch(PDO::FETCH_ASSOC);
    if (!$pickupPoint) {
        throw new Exception('Invalid Pickup Point ID');
    }

    $shipmentData = [
        'booking_ref_id' => $bookingRefId,
        'consignee_name' => $consigneeName,
        'consignee_phone' => $consigneePhone,
        'consignee_address' => $consigneeAddress,
        'consignee_pin' => $consigneePin,
        'consignee_city' => $consigneeCity,
        'consignee_state' => $consigneeState,
        'consignee_country' => $consigneeCountry,
        'payment_mode' => $paymentMode,
        'cod_amount' => $codAmount,
        'product_desc' => $productDesc,
        'quantity' => $totalBoxes,
        'weight' => $weightGrams,
        'length' => $maxL,
        'width' => $maxW,
        'height' => $maxH,
        'shipping_mode' => $shippingMode,
        'pickup_location_name' => $pickupPoint['name'],
        'invoice_no' => $invoiceNo,
        'invoice_date' => date('Y-m-d'),
        'invoice_value' => $invoiceValue,
        'ewaybill_no' => $ewaybillNo,
        'package_details' => $packageDetails
    ];

    // Courier sync via router (same flow as api/pickuppoint/services/courier_service.php)
    require_once __DIR__ . '/services/courier_service.php';
    $syncResult = syncBookingWithCourier($pdo, $courierData, $shipmentData);

    if (empty($syncResult['success'])) {
        throw new Exception($syncResult['message'] ?? 'Courier sync failed');
    }

    $waybillNo = $syncResult['waybill'] ?? null;
    $apiResponseRaw = $syncResult['api_response'] ?? null;
    $apiResponseJson = is_array($apiResponseRaw) ? json_encode($apiResponseRaw) : $apiResponseRaw;

    $sql = "INSERT INTO tbl_bookings (
        booking_ref_id, waybill_no, courier_id, pickup_point_id,
        consignee_name, consignee_phone, consignee_email, consignee_gst, consignee_address, consignee_pin,
        consignee_city, consignee_state, consignee_country,
        shipper_name, shipper_phone, shipper_address, shipper_pin, shipper_city, shipper_state,
        payment_mode, cod_amount, weight, length, width, height,
        shipping_mode, product_desc, package_details, quantity, is_mps,
        invoice_no, invoice_value, ewaybill_no,
        rto_name, rto_phone, rto_address,
        api_response, last_status, created_by, created_at
    ) VALUES (
        :ref_id, :waybill, :c_id, :p_id,
        :c_name, :c_phone, :c_email, :c_gst, :c_add, :c_pin,
        :c_city, :c_state, :c_country,
        :s_name, :s_phone, :s_add, :s_pin, :s_city, :s_state,
        :pay_mode, :cod, :w, :l, :wi, :h,
        :ship_mode, :prod_desc, :pkg_details, :qty, :mps,
        :inv_no, :inv_val, :eway,
        :rto_name, :rto_phone, :rto_add,
        :api_resp, 'Created', :user_id, NOW()
    )";

    $stmt = $pdo->prepare($sql);
    $stmt->execute([
        ':ref_id' => $bookingRefId,
        ':waybill' => $waybillNo,
        ':c_id' => $courierId,
        ':p_id' => $pickupPointId,
        ':c_name' => $consigneeName,
        ':c_phone' => $consigneePhone,
        ':c_email' => $consigneeEmail,
        ':c_gst' => $consigneeGst,
        ':c_add' => $consigneeAddress,
        ':c_pin' => $consigneePin,
        ':c_city' => $consigneeCity,
        ':c_state' => $consigneeState,
        ':c_country' => $consigneeCountry,
        ':s_name' => $shipperName,
        ':s_phone' => $shipperPhone,
        ':s_add' => $shipperAddress,
        ':s_pin' => $shipperPin,
        ':s_city' => $shipperCity,
        ':s_state' => $shipperState,
        ':pay_mode' => $paymentMode,
        ':cod' => $codAmount,
        ':w' => $weightGrams,
        ':l' => $maxL,
        ':wi' => $maxW,
        ':h' => $maxH,
        ':ship_mode' => $shippingMode,
        ':prod_desc' => $productDesc,
        ':pkg_details' => $packageDetailsJson,
        ':qty' => $totalBoxes,
        ':mps' => ($totalBoxes > 1 ? 1 : 0),
        ':inv_no' => $invoiceNo,
        ':inv_val' => $invoiceValue,
        ':eway' => $ewaybillNo,
        ':rto_name' => $rtoName,
        ':rto_phone' => $rtoPhone,
        ':rto_add' => $rtoAddress,
        ':api_resp' => $apiResponseJson,
        ':user_id' => $createdBy
    ]);

    $bookingId = $pdo->lastInsertId();

    // For "Own Courier" (ID 2), insert detailed initial tracking record with structured raw_response
    if ($courierId == 2 && !empty($waybillNo)) {
        $initialTrackingRaw = json_encode([
            'awb_no' => $waybillNo,
            'shipment_details' => [
                'booking_ref_id' => $bookingRefId,
                'consignee_name' => $consigneeName,
                'consignee_phone' => $consigneePhone,
                'payment_mode' => $paymentMode,
                'cod_amount' => $codAmount
            ],
            'current_status' => 'Created',
            'scan_details' => [
                'status' => 'Booking Created',
                'location' => $shipperCity,
                'datetime' => date('Y-m-d H:i:s'),
                'remarks' => 'Shipment created locally via Own Booking'
            ]
        ]);

        $trackSql = "INSERT INTO tbl_tracking (booking_id, waybill_no, scan_type, status_code, scan_location, scan_datetime, remarks, raw_response) 
                     VALUES (:bid, :wn, 'Booking Created', 'Created', :sl, NOW(), 'Shipment created locally', :raw)";

        $pdo->prepare($trackSql)->execute([
            ':bid' => $bookingId,
            ':wn' => $waybillNo,
            ':sl' => $shipperCity,
            ':raw' => $initialTrackingRaw
        ]);
    } else if (!empty($waybillNo)) {
        // Standard brief tracking for other couriers (like Delhivery)
        $trackSql = "INSERT INTO tbl_tracking (booking_id, waybill_no, scan_type, status_code, scan_datetime, remarks) 
                     VALUES (:bid, :wn, 'Booking Created', 'Created', NOW(), 'Shipment created and synced with carrier')";
        $pdo->prepare($trackSql)->execute([':bid' => $bookingId, ':wn' => $waybillNo]);
    }

    if (!empty($waybillNo) && $courierId == 1) {
        // Trigger Delhivery Tracking Update immediately so UI shows "Manifested" or real status
        try {
            if (!defined('IN_CREATION'))
                define('IN_CREATION', true);
            // We call it via include but mock $_GET['waybill']
            $_GET['waybill'] = $waybillNo;
            ob_start(); // Capture output to avoid breaking API JSON response
            include __DIR__ . '/../../cron-delhivery.php';
            ob_end_clean();
        } catch (Exception $e) {
            // Ignore tracking trigger errors to not break booking creation
        }
    }

    $message = !empty($syncResult['synced']) ? 'Shipment Booked!' : 'Shipment saved locally (courier sync not configured)';
    echo json_encode([
        'status' => 'success',
        'message' => $message,
        'waybill' => $waybillNo,
        'booking_id' => $bookingId,
        'synced' => !empty($syncResult['synced'])
    ]);

} catch (Exception $e) {
    echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
}
?>