<?php
header("Content-Type: application/json");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    exit;
}

$shop_url = "nzafrihair.myshopify.com";
$access_token = "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";
$db_host = "localhost";
$db_user = "afrihair_wh";
$db_pass = "wXZ@YMO[ue5efq~b";
$db_name = "order_locks";

$db = new mysqli($db_host, $db_user, $db_pass, $db_name);

if ($db->connect_error) {
    echo json_encode(["error" => "DB connection failed"]);
    exit;
}

// ====================================================================
// UNIVERSAL ROUTER
// ====================================================================
if (php_sapi_name() === 'cli') {
    $action = $argv[1] ?? 'default';
    $arg_oid = $argv[2] ?? null;
    $arg_staff = $argv[3] ?? 'Staff';
    $arg_stock = $argv[4] ?? 'none';
    $arg_rate = $argv[5] ?? 'none';
    $arg_w = $argv[6] ?? 0;
    $arg_l = $argv[7] ?? 0;
    $arg_h = $argv[8] ?? 0;
    $arg_weight = $argv[9] ?? 0;
} else {
    $input = json_decode(file_get_contents("php://input"), true);
    $action = $_GET['action'] ?? $input['action'] ?? $_GET['cron'] ?? 'get_orders';
}

function shopify_call($method, $endpoint, $data = []) {
    global $shop_url, $access_token;

    $url = "https://{$shop_url}/admin/api/2024-01/{$endpoint}";
    $curl = curl_init();
    $headers = [
        "X-Shopify-Access-Token: $access_token",
        "Content-Type: application/json"
    ];

    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    if ($method === 'POST' || $method === 'PUT') {
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
    }

    $response = curl_exec($curl);
    curl_close($curl);

    return json_decode($response, true);
}

function shopify_graphql($query, $variables = []) {
    global $shop_url, $access_token;

    $url = "https://{$shop_url}/admin/api/2024-01/graphql.json";

    $payload = json_encode([
        'query' => $query,
        'variables' => $variables
    ]);

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HTTPHEADER, [
        "X-Shopify-Access-Token: $access_token",
        "Content-Type: application/json"
    ]);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);

    $response = curl_exec($curl);
    curl_close($curl);

    return json_decode($response, true);
}

function get_packie_token() {
    $token_file = __DIR__ . '/packie_token.txt';
    if (!file_exists($token_file)) return null;
    return trim(file_get_contents($token_file));
}

function get_packie_headers() {
    $token = get_packie_token();
    if (!$token) return null;

    return [
        'Content-Type: application/json',
        'Accept: application/json',
        'Authorization: Bearer ' . $token
    ];
}

function detect_packie_status($street, $suburb, $city, $postcode, $country = "NZ") {
    $headers = get_packie_headers();
    if (!$headers) return 'READY'; // Don't block if token is missing

    $street = trim((string)$street);
    $suburb = trim((string)$suburb);
    $city = trim((string)$city);
    $postcode = trim((string)$postcode);
    
    // Standardize country to 2-letter code for the API
    $country = (strlen($country) > 2) ? 'NZ' : strtoupper($country);

    // If address1 is empty but suburb has the street (common in Shopify), swap them for the check
    if ($street === '' && $suburb !== '') {
        $street = $suburb;
        $suburb = '';
    }

    if ($street === '' || $city === '') {
        return 'INVALID';
    }

    $payload = [
        "consignmentParcels" => [["id" => "4", "height" => "1", "width" => "1", "length" => "1", "weight" => "0.1", "quantity" => "1", "serviceType" => 4]],
        "hasDangerousGoods" => false,
        "integrationType" => 1,
        "isInternational" => ($country !== 'NZ'),
        "receiver" => ["suburb" => $suburb, "city" => $city, "country" => $country, "streetAddress" => $street, "postCode" => $postcode],
        "sender" => ["contactName" => "Daniel", "company" => "Afrihair", "streetAddress" => "247 Cuba Street", "city" => "Palmerston North", "postCode" => "4410", "country" => "NZ"]
    ];

    $ch = curl_init("https://www.packie.co.nz/api/Consignments/calculate");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5); // Don't hang the app
    $raw = curl_exec($ch);
    curl_close($ch);

    $res = json_decode($raw, true);
    if (!isset($res['result']['rates']) || empty($res['result']['rates'])) {
        // If API fails but we have a street/city, default to READY so we can still work
        return 'READY'; 
    }

    foreach ($res['result']['rates'] as $rate) {
        if (!empty($rate['rural_rate']) && (float)$rate['rural_rate'] > 0) return 'RURAL';
        if (!empty($rate['is_rural']) && $rate['is_rural'] == true) return 'RURAL';
    }

    return 'READY';
}

// ====================================================================
// 1. BACKGROUND / CRON ACTIONS
// ====================================================================

if ($action == 'cron_auth') {
    $login_url = "https://www.packie.co.nz/api/users/login";
    $credentials = [
        "username" => "Afrihair",
        "password" => "Y9jJFb5*S",
        "remember" => true,
        "shopify" => null
    ];

    $ch = curl_init($login_url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($credentials));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Accept: application/json']);
    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($http_code == 200 || $http_code == 201) {
        $data = json_decode($response, true);
        $token = $data['result']['token'] ?? null;
        if ($token) {
            file_put_contents(__DIR__ . '/packie_token.txt', $token);
            echo "Token Refreshed\n";
        }
    }
    exit;
}

if ($action == 'cron_sync') {
    // Start Logging
    $log_file = __DIR__ . '/sync_log.txt';
    $timestamp = date('Y-m-d H:i:s');
    file_put_contents($log_file, "--- Sync Started: $timestamp ---\n", FILE_APPEND);

    $orders_res = shopify_call('GET', 'orders.json?status=open&fulfillment_status=unfulfilled&limit=50');
    $shopify_raw = $orders_res['orders'] ?? [];

    $headers = get_packie_headers();
    if (!$headers) {
        file_put_contents($log_file, "ERROR: Missing Packie Headers/Token\n", FILE_APPEND);
        exit;
    }

    $ch2 = curl_init("https://www.packie.co.nz/api/Orders/get-orders?status=1&search=&integrationId=0&page=1&perPage=100");
    curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch2, CURLOPT_HTTPHEADER, $headers);
    $data = json_decode(curl_exec($ch2), true);
    curl_close($ch2);

    if (isset($data['result']['orders'])) {
        // --- DEBUG: SEE THE WHOLE STRUCTURE ONCE ---
        //if (!empty($data['result']['orders'])) {
        //    file_put_contents($log_file, "DEBUG RAW ORDER DATA:\n" . print_r($data['result']['orders'][0], true) . "\n", FILE_APPEND);
        //}
        // --- END DEBUG ---

        $insert_stmt = $db->prepare("
            INSERT INTO packie_cache (shopify_order_number, packie_id, packie_status, original_shopify_address)
            VALUES (?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE
                packie_id = VALUES(packie_id),
                packie_status = VALUES(packie_status)
        ");

        foreach ($data['result']['orders'] as $order) {
            $shopify_num = (string)($order['orderNumber'] ?? '');
            if ($shopify_num === '') continue;

            // 1. EXACT MAPPING FROM YOUR DEBUG DUMP
            $r = $order['receiver'] ?? [];
            
            // Map the keys exactly as seen in your print_r output
            $p_street   = $r['street']   ?? '';
            $p_suburb   = $r['suburb']   ?? '';
            $p_city     = $r['city']     ?? '';
            $p_postcode = $r['postCode'] ?? ''; // Note the capital C
            $p_country  = $r['country']  ?? 'NZ';

            // 2. Fetch the raw Shopify address string for the "Source of Truth"
            $raw_addr_string = "";
            foreach ($shopify_raw as $so) {
                if (str_replace('#', '', $so['name'] ?? '') === $shopify_num) {
                    $sa = $so['shipping_address'] ?? [];
                    $parts = array_filter([
                        $sa['address1'] ?? '',
                        $sa['address2'] ?? '',
                        $sa['city'] ?? '',
                        $sa['zip'] ?? ''
                    ]);
                    $raw_addr_string = implode(', ', $parts);
                    break;
                }
            }

            // Fallback
            if ($raw_addr_string === '') {
                $raw_addr_string = trim(implode(', ', array_filter([$p_street, $p_suburb, $p_city, $p_postcode])));
            }

            $packie_id = (string)($order['id'] ?? '');

            // 3. Status Detection
            $status = detect_packie_status($p_street, $p_suburb, $p_city, $p_postcode, $p_country);

            // LOGGING: Now showing the verified street
            $log_entry = "Order #$shopify_num | Status: $status | Full Addr: $p_street, $p_suburb, $p_city\n";
            file_put_contents($log_file, $log_entry, FILE_APPEND);

            // 4. Bind and Execute
            $insert_stmt->bind_param("ssss", $shopify_num, $packie_id, $status, $raw_addr_string);
            $insert_stmt->execute();
        }
    }

    file_put_contents($log_file, "--- Sync Complete ---\n\n", FILE_APPEND);
    echo json_encode(["success" => true, "message" => "Sync complete using Shopify Source of Truth"]);
    exit;
}

if ($action == 'print_label') {
    $order_id = $arg_oid;
    $staff = $arg_staff;
    $stock_id = $arg_stock;
    $rate_id = $arg_rate;

    $get = shopify_call('GET', "orders/{$order_id}.json?fields=tags,name");
    if (!isset($get['order'])) exit;

    $shopify_num = str_replace('#', '', $get['order']['name']);
    $tags = $get['order']['tags'] ?? '';

    if ($stock_id !== 'none' || $rate_id !== 'none') {
        $headers = get_packie_headers();
        if ($headers) {
            $packie_order = null;
            foreach ([1, 2, 3, 4, 5, 0, 99] as $st) {
                $ch = curl_init("https://www.packie.co.nz/api/Orders/get-orders?status={$st}&search={$shopify_num}&integrationId=0&page=1&perPage=5");
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                $res = json_decode(curl_exec($ch), true);
                curl_close($ch);

                if (!empty($res['result']['orders'])) {
                    foreach ($res['result']['orders'] as $po) {
                        if ($po['orderNumber'] === $shopify_num) {
                            $packie_order = $po;
                            break 2;
                        }
                    }
                }
            }

            if ($packie_order) {
                $payload = [
                    "hasDangerousGoods" => false,
                    "integratedOrderId" => $packie_order['id'],
                    "integrationType" => 1,
                    "isInternational" => false,
                    "receiver" => $packie_order['receiver'],
                    "sender" => $packie_order['sender'],
                    "shippingDescription" => "Fastest Delivery",
                    "shippingMethod" => "Fastest Delivery",
                    "signatureRequired" => false
                ];

                if ($stock_id === 'custom') {
                    $payload["shippingDescription"] = "Custom Box";
                    $payload["consignmentParcels"] = [[
                        "id" => "0",
                        "height" => (string)$arg_h,
                        "width" => (string)$arg_w,
                        "length" => (string)$arg_l,
                        "weight" => (string)$arg_weight,
                        "quantity" => "1",
                        "serviceType" => 1
                    ]];
                    $url = "https://www.packie.co.nz/api/Consignments/create/" . str_replace(' ', '%20', $rate_id);
                } else {
                    $stock_id_safe = (int)$stock_id;
                    $s = $db->query("SELECT * FROM packie_stocks WHERE id = $stock_id_safe")->fetch_assoc();
                    if ($s) {
                        $payload["consignmentParcels"] = [[
                            "id" => (string)$s['id'],
                            "height" => (string)$s['height'],
                            "width" => (string)$s['width'],
                            "length" => (string)$s['length'],
                            "weight" => (string)$s['weight'],
                            "quantity" => "1",
                            "serviceType" => (int)$s['serviceType']
                        ]];

                        $ch = curl_init("https://www.packie.co.nz/api/Consignments/calculate");
                        curl_setopt($ch, CURLOPT_POST, true);
                        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                        $c_res = json_decode(curl_exec($ch), true);
                        curl_close($ch);

                        $rate_id_final = $c_res['result']['rates'][0]['id'] ?? null;
                        $url = $rate_id_final
                            ? "https://www.packie.co.nz/api/Consignments/create/" . str_replace(' ', '%20', $rate_id_final)
                            : null;
                    } else {
                        $url = null;
                    }
                }

                if (!empty($url)) {
                    $ch = curl_init($url);
                    curl_setopt($ch, CURLOPT_POST, true);
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                    curl_exec($ch);
                    curl_close($ch);
                }
            }
        }
    }

    $updated_tags = $tags ? "$tags, Packed, Packed by $staff" : "Packed, Packed by $staff";
    shopify_call('PUT', "orders/{$order_id}.json", ['order' => ['id' => $order_id, 'tags' => $updated_tags]]);
    exit;
}

// ====================================================================
// 2. APP API ENDPOINTS
// ====================================================================

if ($action == 'update_pick') {
    $order_id = $input['order_id'];
    $sku = $input['sku'];
    $qty = (int)$input['qty'];
    $staff = $input['staff'];

    $stmt = $db->prepare("
        INSERT INTO picked_items (order_id, sku, picked_qty, picked_by)
        VALUES (?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE picked_qty = ?, picked_by = ?
    ");
    $stmt->bind_param("ssisis", $order_id, $sku, $qty, $staff, $qty, $staff);
    $stmt->execute();

    echo json_encode(['success' => true]);
    exit;
}

if ($action == 'get_picks') {
    $res = $db->query("SELECT order_id, sku, picked_qty, picked_by FROM picked_items");
    $picks = [];

    while ($row = $res->fetch_assoc()) {
        if (!isset($picks[$row['order_id']])) $picks[$row['order_id']] = [];
        $picks[$row['order_id']][$row['sku']] = [
            'qty' => (int)$row['picked_qty'],
            'by' => $row['picked_by']
        ];
    }

    echo json_encode($picks);
    exit;
}

if ($action == 'add_note') {
    $order_id = $input['order_id'];
    $note_text = trim(preg_replace('/[^\pL\pN\s\-\#\.\,\:\(\)\/]/u', '', $input['note'] ?? ''));

    $get = shopify_call('GET', "orders/{$order_id}.json?fields=tags");
    $tags = explode(',', $get['order']['tags'] ?? '');

    $clean_tags = [];
    foreach ($tags as $t) {
        if (trim($t) && stripos(trim($t), 'Note:') !== 0) {
            $clean_tags[] = trim($t);
        }
    }

    if (!empty($note_text)) $clean_tags[] = "Note: $note_text";

    shopify_call('PUT', "orders/{$order_id}.json", [
        'order' => [
            'id' => $order_id,
            'tags' => implode(',', $clean_tags)
        ]
    ]);

    echo json_encode(['success' => true]);
    exit;
}

if ($action == 'check_lock') {
    $order_id = $_GET['order_id'];
    $staff = $_GET['staff'];

    $stmt = $db->prepare("SELECT staff_name FROM order_locks WHERE order_id = ? AND staff_name != ?");
    $stmt->bind_param("ss", $order_id, $staff);
    $stmt->execute();
    $res = $stmt->get_result()->fetch_assoc();

    if ($res) {
        echo json_encode(["locked_by" => $res['staff_name']]);
    } else {
        $stmt = $db->prepare("
            INSERT INTO order_locks (order_id, staff_name)
            VALUES (?, ?)
            ON DUPLICATE KEY UPDATE staff_name = ?, last_seen = NOW()
        ");
        $stmt->bind_param("sss", $order_id, $staff, $staff);
        $stmt->execute();
        echo json_encode(["status" => "locked", "locked_by" => null]);
    }
    exit;
}

if ($action == 'release_lock') {
    $order_id = $_GET['order_id'];
    $staff = $_GET['staff'];

    $stmt = $db->prepare("DELETE FROM order_locks WHERE order_id = ? AND staff_name = ?");
    $stmt->bind_param("ss", $order_id, $staff);
    $stmt->execute();

    echo json_encode(["status" => "released"]);
    exit;
}

if ($action == 'get_stocks') {
    $res = $db->query("SELECT * FROM packie_stocks");
    $stocks = [];

    while ($row = $res->fetch_assoc()) {
        $stocks[] = [
            'id' => (int)$row['id'],
            'name' => $row['name'],
            'serviceType' => (int)$row['serviceType'],
            'height' => (float)$row['height'],
            'width' => (float)$row['width'],
            'length' => (float)$row['length'],
            'weight' => (float)$row['weight']
        ];
    }

    echo json_encode($stocks);
    exit;
}

if ($action == 'check_status') {
    $order_name = $_GET['order_name'] ?? $input['order_name'] ?? '';
    $clean_num = str_replace('#', '', $order_name);

    $stmt = $db->prepare("SELECT packie_status FROM packie_cache WHERE shopify_order_number = ?");
    $stmt->bind_param("s", $clean_num);
    $stmt->execute();
    $res = $stmt->get_result()->fetch_assoc();

    echo json_encode(['packie_status' => $res ? $res['packie_status'] : 'PENDING']);
    exit;
}

if ($action == 'get_custom_quote') {
    $order_name = $_GET['order_name'] ?? '';
    $w = $_GET['w'] ?? 0;
    $l = $_GET['l'] ?? 0;
    $h = $_GET['h'] ?? 0;
    $weight = $_GET['weight'] ?? 0;

    $shopify_num = str_replace('#', '', $order_name);
    $headers = get_packie_headers();

    if (!$headers) {
        echo json_encode([]);
        exit;
    }

    $ch_search = curl_init("https://www.packie.co.nz/api/Orders/get-orders?status=1&search={$shopify_num}&integrationId=0&page=1&perPage=5");
    curl_setopt($ch_search, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch_search, CURLOPT_HTTPHEADER, $headers);
    $search_res = json_decode(curl_exec($ch_search), true);
    curl_close($ch_search);

    if (isset($search_res['result']['orders'][0])) {
        $po = $search_res['result']['orders'][0];
        $payload = [
            "consignmentParcels" => [[
                "id" => "0",
                "height" => (string)$h,
                "width" => (string)$w,
                "length" => (string)$l,
                "weight" => (string)$weight,
                "quantity" => "1",
                "serviceType" => 1
            ]],
            "hasDangerousGoods" => false,
            "integratedOrderId" => $po['id'],
            "integrationType" => 1,
            "isInternational" => false,
            "receiver" => $po['receiver'],
            "sender" => $po['sender']
        ];

        $ch = curl_init("https://www.packie.co.nz/api/Consignments/calculate");
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        $res = json_decode(curl_exec($ch), true);
        curl_close($ch);

        echo json_encode($res['result']['rates'] ?? []);
    } else {
        echo json_encode([]);
    }
    exit;
}

if ($action == 'mark_packed') {
    $order_id = $input['order_id'];
    $order_name = $input['order_name'] ?? '';
    $shopify_num = str_replace('#', '', $order_name);

    $stmt1 = $db->prepare("DELETE FROM order_locks WHERE order_id = ?");
    $stmt1->bind_param("s", $order_id);
    $stmt1->execute();

    $stmt2 = $db->prepare("DELETE FROM picked_items WHERE order_id = ?");
    $stmt2->bind_param("s", $order_id);
    $stmt2->execute();

    $stmt3 = $db->prepare("UPDATE packie_cache SET packie_status = 'PRINTED' WHERE shopify_order_number = ?");
    $stmt3->bind_param("s", $shopify_num);
    $stmt3->execute();

    $args = escapeshellarg($order_id) . " "
        . escapeshellarg($input['staff'] ?? 'Staff') . " "
        . escapeshellarg($input['stock_id'] ?? 'none') . " "
        . escapeshellarg($input['rate_id'] ?? 'none') . " "
        . escapeshellarg($input['w'] ?? 0) . " "
        . escapeshellarg($input['l'] ?? 0) . " "
        . escapeshellarg($input['h'] ?? 0) . " "
        . escapeshellarg($input['weight'] ?? 0);

    exec("/usr/local/bin/php " . __DIR__ . "/api.php print_label $args > /dev/null 2>&1 &");

    echo json_encode(['success' => true]);
    exit;
}

if ($action == 'update_address') {
    $order_id = $input['order_id'] ?? null;
    $get_res = shopify_call('GET', "orders/{$order_id}.json?fields=tags,name,email,phone,shipping_address");
    $order_name = str_replace('#', '', $get_res['order']['name'] ?? '');
    $ship = $get_res['order']['shipping_address'] ?? [];

    $full_street = trim(($input['unit'] ? $input['unit'] . ' ' : '') . ($input['address1'] ?? ''));
    $tags_array = array_map('trim', explode(',', $get_res['order']['tags'] ?? ''));
    $clean_tags = array_filter($tags_array, function ($t) {
        return !in_array(strtolower(trim($t)), ['check address', 'risk warning', 'rural', 'rural delivery', 'rd', 'rd address']);
    });

    shopify_call('PUT', "orders/{$order_id}.json", [
        "order" => [
            "id" => $order_id,
            "tags" => implode(', ', $clean_tags),
            "shipping_address" => [
                "address1" => $full_street,
                "address2" => $input['address2'] ?? '',
                "city" => $input['city'] ?? '',
                "zip" => $input['zip'] ?? ''
            ]
        ]
    ]);

    $headers = get_packie_headers();
    $packie_order_id = null;

    if ($headers) {
        foreach ([1, 2, 3, 4, 5, 0, 99] as $stat) {
            $ch = curl_init("https://www.packie.co.nz/api/Orders/get-orders?status={$stat}&search={$order_name}&integrationId=0&page=1&perPage=5");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            $res = json_decode(curl_exec($ch), true);
            curl_close($ch);

            if (!empty($res['result']['orders'])) {
                foreach ($res['result']['orders'] as $po) {
                    if ($po['orderNumber'] === $order_name) {
                        $packie_order_id = $po['id'];
                        break 2;
                    }
                }
            }
        }
    }

    $new_status = detect_packie_status(
        $full_street,
        $input['address2'] ?? '',
        $input['city'] ?? '',
        $input['zip'] ?? '',
        'NZ'
    );

    if ($packie_order_id && $headers) {
        $p_payload = [
            "contactName" => $ship['name'] ?? 'Customer',
            "email" => $get_res['order']['email'] ?? '',
            "phone" => $ship['phone'] ?? '',
            "address1" => $input['address1'] ?? "",
            "city" => $input['city'] ?? "",
            "country" => "NZ",
            "unit" => $input['unit'] ?? "",
            "notes" => $input['notes'] ?? "",
            "postcode" => $input['zip'] ?? "",
            "street" => $input['address1'] ?? "",
            "suburb" => $input['address2'] ?? ""
        ];

        $ch = curl_init("https://www.packie.co.nz/api/Orders/EditReceiver/" . $packie_order_id);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($p_payload));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_exec($ch);
        curl_close($ch);
    }

    $stmt = $db->prepare("UPDATE packie_cache SET packie_status = ? WHERE shopify_order_number = ?");
    $stmt->bind_param("ss", $new_status, $order_name);
    $stmt->execute();

    echo json_encode(["success" => true, "new_status" => $new_status]);
    exit;
}

if ($action == 'address_autocomplete') {
    $term = $_GET['term'] ?? '';
    if (strlen($term) < 3) {
        echo json_encode(["result" => []]);
        exit;
    }

    $headers = get_packie_headers();
    if (!$headers) {
        echo json_encode(["result" => []]);
        exit;
    }

    $ch = curl_init("https://www.packie.co.nz/api/Address/search-domestic-address?term=" . urlencode($term));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Accept: application/json',
        $headers[2]
    ]);
    echo curl_exec($ch);
    curl_close($ch);
    exit;
}

if ($action == 'get_orders') {
    $res = shopify_call('GET', 'orders.json?status=open&fulfillment_status=unfulfilled&limit=50');
    $raw_orders = $res['orders'] ?? [];

    $packie_data = [];
    $res_cache = $db->query("SELECT shopify_order_number, packie_id, packie_status, original_shopify_address FROM packie_cache");
    while ($row = $res_cache->fetch_assoc()) {
        $packie_data[$row['shopify_order_number']] = [
            'packie_id' => $row['packie_id'],
            'status' => $row['packie_status'],
            'original' => $row['original_shopify_address']
        ];
    }

    $needs_import = false;
    $product_ids = [];
    $variant_ids = [];

    foreach ($raw_orders as $o) {
        $shopify_num = str_replace('#', '', $o['name']);
        if (!isset($packie_data[$shopify_num])) {
            $needs_import = true;
        }

        foreach ($o['line_items'] as $item) {
            if (!empty($item['product_id'])) $product_ids[] = $item['product_id'];
            if (!empty($item['variant_id'])) $variant_ids[] = (int)$item['variant_id'];
        }
    }

    // Trigger background sync if needed
    $cmd = $needs_import ? "cron_sync" : "cron_sync skip_import";
    exec("/usr/local/bin/php " . __DIR__ . "/api.php $cmd > /dev/null 2>&1 &");

    // Build variant-specific image map
    $variant_image_map = [];
    $product_fallback_image_map = [];

    if (!empty($variant_ids)) {
        foreach (array_chunk(array_unique($variant_ids), 100) as $chunk) {
            $gids = array_map(function ($id) {
                return "gid://shopify/ProductVariant/" . $id;
            }, $chunk);

            $query = <<<'GQL'
query VariantImages($ids: [ID!]!) {
  nodes(ids: $ids) {
    ... on ProductVariant {
      id
      image {
        url
      }
      product {
        featuredImage {
          url
        }
      }
    }
  }
}
GQL;

            $gql_res = shopify_graphql($query, ['ids' => $gids]);

            foreach (($gql_res['data']['nodes'] ?? []) as $node) {
                if (!$node || empty($node['id'])) continue;

                if (preg_match('#ProductVariant/(\d+)$#', $node['id'], $m)) {
                    $variant_id = (string)$m[1];
                    $variant_image_map[$variant_id] =
                        $node['image']['url']
                        ?? $node['product']['featuredImage']['url']
                        ?? null;
                }
            }
        }
    }

    if (!empty($product_ids)) {
        $prod_ids_str = implode(',', array_slice(array_unique($product_ids), 0, 100));
        $prod_res = shopify_call('GET', "products.json?ids=" . $prod_ids_str . "&fields=id,images");

        if (isset($prod_res['products'])) {
            foreach ($prod_res['products'] as $p) {
                $product_fallback_image_map[(string)$p['id']] = $p['images'][0]['src'] ?? null;
            }
        }
    }

    // Instant direct status detection for orders missing from cache
    // so new rural / invalid orders show correctly before cron_sync finishes.
    $insert_stmt = $db->prepare("
        INSERT INTO packie_cache (shopify_order_number, packie_id, packie_status, original_shopify_address)
        VALUES (?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE
            packie_id = VALUES(packie_id),
            packie_status = VALUES(packie_status),
            original_shopify_address = VALUES(original_shopify_address)
    ");

    $output = [];

    foreach ($raw_orders as $o) {
        $num = str_replace('#', '', $o['name']);

        if (!isset($packie_data[$num])) {
            $sa = $o['shipping_address'] ?? [];

            $street = trim((string)($sa['address1'] ?? ''));
            $suburb = trim((string)($sa['address2'] ?? ''));
            $city = trim((string)($sa['city'] ?? ''));
            $postcode = trim((string)($sa['zip'] ?? ''));
            $country = trim((string)($sa['country_code'] ?? ($sa['country'] ?? 'NZ')));

            $original_address = implode(', ', array_filter([$street, $suburb, $city, $postcode]));
            $instant_status = detect_packie_status($street, $suburb, $city, $postcode, $country);

            $packie_data[$num] = [
                'packie_id' => '',
                'status' => $instant_status,
                'original' => $original_address
            ];

            $blank_packie_id = '';
            $insert_stmt->bind_param("ssss", $num, $blank_packie_id, $instant_status, $original_address);
            $insert_stmt->execute();
        }

        $p_info = $packie_data[$num] ?? ['status' => 'PENDING', 'original' => ''];
        if ($p_info['status'] === 'PRINTED') continue;

        $skip = false;
        $note = '';
        $risky = false;
        $addr_check = false;

        foreach (explode(',', $o['tags'] ?? '') as $t) {
            $ct = strtolower(trim($t));
            if (stripos($ct, 'note:') === 0) $note = trim(substr(trim($t), 5));
            if ($ct === 'risk warning') $risky = true;
            if ($ct === 'check address') $addr_check = true;
            if ($ct === 'packed' || stripos($ct, 'packed by') === 0) $skip = true;
        }

        if ($skip) continue;

        $items = [];
        foreach ($o['line_items'] as $i) {
            $variant_id = (string)($i['variant_id'] ?? '');
            $product_id = (string)($i['product_id'] ?? '');

            $variant_img =
                ($variant_id && !empty($variant_image_map[$variant_id]) ? $variant_image_map[$variant_id] : null)
                ?? ($product_id && !empty($product_fallback_image_map[$product_id]) ? $product_fallback_image_map[$product_id] : null)
                ?? 'https://placehold.co/100x100/png?text=No+Img';

            $items[] = [
                'name' => $i['name'],
                'qty' => $i['quantity'],
                'sku' => $i['sku'] ?: 'No SKU',
                'img' => $variant_img
            ];
        }

        $method = $o['shipping_lines'][0]['title'] ?? 'Standard';

        $output[] = [
            'id' => (string)$o['id'],
            'name' => $o['name'],
            'customer' => $o['shipping_address']['name'] ?? 'Customer',
            'address' => trim(($o['shipping_address']['address1'] ?? '') . ', ' . ($o['shipping_address']['city'] ?? '')),
            'postcode' => $o['shipping_address']['zip'] ?? '',
            'method' => $method,
            'country' => $o['shipping_address']['country_code'] ?? ($o['shipping_address']['country'] ?? ''),
            'is_pickup' => (stripos($method, 'Pickup') !== false || stripos($method, '247 Cuba') !== false),
            'unpaid' => ($o['financial_status'] !== 'paid'),
            'note' => $note,
            'items' => $items,
            'packie_status' => $p_info['status'],
            'original_address' => $p_info['original'],
            'is_risky' => $risky,
            'needs_address_check' => $addr_check
        ];
    }

    echo json_encode($output);
    exit;
}

echo json_encode(["error" => "Unknown action"]);
?>