<?php
require_once __DIR__ . '/config.php';

$rawBody = get_raw_body();
$receivedHmac = get_header_value('X-Shopify-Hmac-SHA256');
$topic = get_header_value('X-Shopify-Topic');
$shopDomain = get_header_value('X-Shopify-Shop-Domain');

$webhookId = log_webhook(
    'shopify',
    $topic,
    $shopDomain,
    getallheaders_safe(),
    $rawBody,
    'pending',
    null
);

if (!verify_shopify_webhook($rawBody, $receivedHmac)) {
    update_webhook_log($webhookId, 'failed', 'Invalid Shopify HMAC');
    json_response(['ok' => false, 'error' => 'Invalid Shopify HMAC'], 401);
}

$data = json_decode($rawBody, true);
if (!is_array($data)) {
    update_webhook_log($webhookId, 'failed', 'Invalid JSON payload');
    json_response(['ok' => false, 'error' => 'Invalid JSON'], 400);
}

function normalize_state_value_local($value): string
{
    $value = trim(mb_strtolower((string)$value, 'UTF-8'));
    $value = preg_replace('/\s+/', ' ', $value);
    return (string)$value;
}

function is_local_lalamove_destination_local($province, $provinceCode, $fullAddress): bool
{
    $provinceNorm = normalize_state_value_local($province);
    $provinceCodeNorm = strtoupper(trim((string)$provinceCode));
    $addressNorm = normalize_state_value_local($fullAddress);

    $acceptedStates = [
        'selangor',
        'kuala lumpur',
        'wilayah persekutuan kuala lumpur',
    ];

    if (in_array($provinceNorm, $acceptedStates, true)) {
        return true;
    }

    if ($provinceCodeNorm === 'KUL') {
        return true;
    }

    if ($addressNorm !== '') {
        if (strpos($addressNorm, 'selangor') !== false) {
            return true;
        }
        if (strpos($addressNorm, 'kuala lumpur') !== false) {
            return true;
        }
        if (strpos($addressNorm, 'wilayah persekutuan kuala lumpur') !== false) {
            return true;
        }
    }

    return false;
}

$shopifyOrderId = isset($data['id']) ? (string)$data['id'] : '';
if ($shopifyOrderId === '' || !ctype_digit($shopifyOrderId)) {
    update_webhook_log($webhookId, 'failed', 'Missing or invalid Shopify order id');
    json_response(['ok' => false, 'error' => 'Missing or invalid Shopify order id'], 400);
}
$shopifyOrderGid = isset($data['admin_graphql_api_id']) ? (string)$data['admin_graphql_api_id'] : null;
$shopifyOrderNumber = isset($data['order_number']) ? (string)$data['order_number'] : '';
$shopifyName = isset($data['name']) ? (string)$data['name'] : '';
$financialStatus = isset($data['financial_status']) ? (string)$data['financial_status'] : null;
$fulfillmentStatus = isset($data['fulfillment_status']) ? (string)$data['fulfillment_status'] : null;
$currency = isset($data['currency']) ? (string)$data['currency'] : null;
$totalPrice = isset($data['total_price']) ? (float)$data['total_price'] : null;

$customerFirst = $data['customer']['first_name'] ?? null;
$customerLast = $data['customer']['last_name'] ?? null;
$customerName = trim((string)$customerFirst . ' ' . (string)$customerLast);
$customerEmail = $data['customer']['email'] ?? ($data['email'] ?? null);
$customerPhoneRaw = $data['customer']['phone'] ?? null;
$customerPhoneNorm = normalize_phone($customerPhoneRaw);

$shipping = is_array($data['shipping_address'] ?? null) ? $data['shipping_address'] : [];
$shippingName = $shipping['name'] ?? null;
$shippingCompany = $shipping['company'] ?? null;
$shippingAddress1 = $shipping['address1'] ?? null;
$shippingAddress2 = $shipping['address2'] ?? null;
$shippingCity = $shipping['city'] ?? null;
$shippingProvince = $shipping['province'] ?? null;
$shippingProvinceCode = $shipping['province_code'] ?? null;
$shippingZip = $shipping['zip'] ?? null;
$shippingCountry = $shipping['country'] ?? null;
$shippingCountryCode = $shipping['country_code'] ?? null;
$shippingPhoneRaw = $shipping['phone'] ?? null;
$shippingPhoneNorm = normalize_phone($shippingPhoneRaw);

$fullAddress = trim(implode(', ', array_filter([
    $shippingName,
    $shippingAddress1,
    $shippingAddress2,
    $shippingCity,
    $shippingProvince,
    $shippingZip,
    $shippingCountry
], function ($v) {
    return trim((string)$v) !== '';
})));

$orderCreatedAt = null;
if (!empty($data['created_at'])) {
    $orderCreatedAt = date('Y-m-d H:i:s', strtotime((string)$data['created_at']));
}

$notes = $data['note'] ?? null;
$tags = $data['tags'] ?? null;
$rawPayload = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

$matchStatus = is_local_lalamove_destination_local($shippingProvince, $shippingProvinceCode, $fullAddress)
    ? 'unmatched'
    : 'ignored';

$mysqli = db();

$stmt = $mysqli->prepare("
    INSERT INTO shopify_orders (
        shopify_order_id, shopify_order_gid, shopify_order_number, shopify_name, financial_status, fulfillment_status,
        currency, total_price, customer_first_name, customer_last_name, customer_name, customer_email,
        customer_phone_raw, customer_phone_normalized, shipping_name, shipping_company, shipping_address1,
        shipping_address2, shipping_city, shipping_province, shipping_zip, shipping_country,
        shipping_country_code, shipping_phone_raw, shipping_phone_normalized, address_full_text,
        notes, tags, order_created_at, webhook_received_at, last_synced_at, match_status, raw_payload
    ) VALUES (
        ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW(), ?, ?
    )
    ON DUPLICATE KEY UPDATE
        shopify_order_gid = VALUES(shopify_order_gid),
        shopify_order_number = VALUES(shopify_order_number),
        shopify_name = VALUES(shopify_name),
        financial_status = VALUES(financial_status),
        fulfillment_status = VALUES(fulfillment_status),
        currency = VALUES(currency),
        total_price = VALUES(total_price),
        customer_first_name = VALUES(customer_first_name),
        customer_last_name = VALUES(customer_last_name),
        customer_name = VALUES(customer_name),
        customer_email = VALUES(customer_email),
        customer_phone_raw = VALUES(customer_phone_raw),
        customer_phone_normalized = VALUES(customer_phone_normalized),
        shipping_name = VALUES(shipping_name),
        shipping_company = VALUES(shipping_company),
        shipping_address1 = VALUES(shipping_address1),
        shipping_address2 = VALUES(shipping_address2),
        shipping_city = VALUES(shipping_city),
        shipping_province = VALUES(shipping_province),
        shipping_zip = VALUES(shipping_zip),
        shipping_country = VALUES(shipping_country),
        shipping_country_code = VALUES(shipping_country_code),
        shipping_phone_raw = VALUES(shipping_phone_raw),
        shipping_phone_normalized = VALUES(shipping_phone_normalized),
        address_full_text = VALUES(address_full_text),
        notes = VALUES(notes),
        tags = VALUES(tags),
        order_created_at = VALUES(order_created_at),
        last_synced_at = NOW(),
        match_status = VALUES(match_status),
        raw_payload = VALUES(raw_payload)
");

if (!$stmt) {
    update_webhook_log($webhookId, 'failed', $mysqli->error);
    json_response(['ok' => false, 'error' => $mysqli->error], 500);
}

$shopifyOrderIdInt = (int)$shopifyOrderId;
$totalPriceForBind = $totalPrice;
$bindTypes = 'issssssd' . str_repeat('s', 23); // 31 params total
$stmt->bind_param(
    $bindTypes,
    $shopifyOrderIdInt,
    $shopifyOrderGid,
    $shopifyOrderNumber,
    $shopifyName,
    $financialStatus,
    $fulfillmentStatus,
    $currency,
    $totalPriceForBind,
    $customerFirst,
    $customerLast,
    $customerName,
    $customerEmail,
    $customerPhoneRaw,
    $customerPhoneNorm,
    $shippingName,
    $shippingCompany,
    $shippingAddress1,
    $shippingAddress2,
    $shippingCity,
    $shippingProvince,
    $shippingZip,
    $shippingCountry,
    $shippingCountryCode,
    $shippingPhoneRaw,
    $shippingPhoneNorm,
    $fullAddress,
    $notes,
    $tags,
    $orderCreatedAt,
    $matchStatus,
    $rawPayload
);

if (!$stmt->execute()) {
    update_webhook_log($webhookId, 'failed', $stmt->error);
    json_response(['ok' => false, 'error' => $stmt->error], 500);
}
$stmt->close();

// Find local row id
$rowId = 0;
$stmt = $mysqli->prepare("SELECT id FROM shopify_orders WHERE shopify_order_id = ?");
$stmt->bind_param('i', $shopifyOrderIdInt);
$stmt->execute();
$stmt->bind_result($rowId);
$stmt->fetch();
$stmt->close();

// Refresh items
$mysqli->query("DELETE FROM shopify_order_items WHERE shopify_order_row_id = " . (int)$rowId);

if ($rowId > 0 && !empty($data['line_items']) && is_array($data['line_items'])) {
    $itemStmt = $mysqli->prepare("
        INSERT INTO shopify_order_items
        (shopify_order_row_id, shopify_line_item_id, sku, title, variant_title, quantity, price, grams, requires_shipping, taxable, raw_payload)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");

    if ($itemStmt) {
        foreach ($data['line_items'] as $item) {
            $lineItemId = isset($item['id']) ? (int)$item['id'] : null;
            $sku = $item['sku'] ?? null;
            $title = $item['title'] ?? null;
            $variantTitle = $item['variant_title'] ?? null;
            $quantity = isset($item['quantity']) ? (int)$item['quantity'] : 1;
            $price = isset($item['price']) ? (float)$item['price'] : null;
            $grams = isset($item['grams']) ? (int)$item['grams'] : null;
            $requiresShipping = !empty($item['requires_shipping']) ? 1 : 0;
            $taxable = !empty($item['taxable']) ? 1 : 0;
            $rawItem = json_encode($item, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

            $itemStmt->bind_param(
                'iisssidiiis',
                $rowId, $lineItemId, $sku, $title, $variantTitle, $quantity, $price, $grams, $requiresShipping, $taxable, $rawItem
            );
            $itemStmt->execute();
        }
        $itemStmt->close();
    }
}

update_webhook_log($webhookId, 'processed', null);
json_response([
    'ok' => true,
    'message' => 'Shopify order stored',
    'shopify_order_id' => $shopifyOrderIdInt,
    'local_row_id' => $rowId,
    'shop_domain' => $shopDomain,
    'topic' => $topic,
    'match_status' => $matchStatus,
    'shipping_province' => $shippingProvince,
    'shipping_province_code' => $shippingProvinceCode
]);

function getallheaders_safe(): array
{
    if (function_exists('getallheaders')) {
        $headers = getallheaders();
        return is_array($headers) ? $headers : [];
    }

    $headers = [];
    foreach ($_SERVER as $name => $value) {
        if (strpos($name, 'HTTP_') === 0) {
            $headerName = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
            $headers[$headerName] = $value;
        }
    }
    return $headers;
}
