<?php
/**
 * Shopify Admin webhook: orders/paid
 *
 * When an order is marked paid, creates a HubSpot deal in the configured pipeline/stage
 * only if every line item's product has product_type matching SHOPIFY_REQUIRED_PRODUCT_TYPE.
 *
 * Idempotency: skips HubSpot create if a deal already exists with the same Shopify order id
 * (custom deal property HUBSPOT_DEAL_PROPERTY_SHOPIFY_ORDER_ID).
 *
 * Setup:
 * 1) HubSpot: create deal property matching HUBSPOT_DEAL_PROPERTY_SHOPIFY_ORDER_ID (string).
 * 2) hubspot-config.php: set token, pipeline, deal stage (sale completed).
 * 3) shopify-config.php: webhook secret, Admin API token, shop domain, product type if not "hardware".
 * 4) In Shopify Admin → Settings → Notifications → Webhooks: Event "Order payment",
 *    URL https://your-server/.../shopify-order-paid.php, JSON format.
 */

require __DIR__ . '/hubspot-config.php';
require __DIR__ . '/shopify-config.php';
require __DIR__ . '/includes/shopify-api.php';
require __DIR__ . '/includes/hubspot-api.php';

header('Content-Type: text/plain; charset=utf-8');

function log_message(string $level, string $message, array $context = []): void
{
    $primaryDir = __DIR__ . '/../logs';
    $logDir = $primaryDir;
    if (!is_dir($logDir)) {
        @mkdir($logDir, 0775, true);
    }
    // If project dir isn't writable (common on Windows/IIS), fall back to temp.
    if (!is_dir($logDir) || !is_writable($logDir)) {
        $fallback = rtrim((string) sys_get_temp_dir(), "\\/") . DIRECTORY_SEPARATOR . 'hubspot-shopify-logs';
        $logDir = $fallback;
        if (!is_dir($logDir)) {
            @mkdir($logDir, 0775, true);
        }
    }

    $logFile = rtrim($logDir, "\\/") . DIRECTORY_SEPARATOR . 'shopify-order-paid.log';
    $ts = (new DateTimeImmutable('now', new DateTimeZone('UTC')))->format('Y-m-d\TH:i:s\Z');

    $ctx = '';
    if (!empty($context)) {
        $ctx = ' ' . json_encode($context, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    }

    $line = $ts . ' [' . $level . '] ' . $message . $ctx . PHP_EOL;
    @file_put_contents($logFile, $line, FILE_APPEND | LOCK_EX);
    // Also write to PHP error log so hosting panels can show it.
    @error_log('[shopify-order-paid] ' . trim($line));
}

function order_has_payment_gateway(array $order, string $gatewayName): bool
{
    $needle = strtolower(trim($gatewayName));
    if ($needle === '') {
        return false;
    }

    $names = $order['payment_gateway_names'] ?? null;
    if (is_array($names)) {
        foreach ($names as $n) {
            if (strtolower(trim((string) $n)) === $needle) {
                return true;
            }
        }
    }

    // Some payloads include a single gateway string
    $gateway = $order['gateway'] ?? null;
    if (is_string($gateway) && strtolower(trim($gateway)) === $needle) {
        return true;
    }

    return false;
}

$rawBody = file_get_contents('php://input');
if (!is_string($rawBody)) {
    $rawBody = '';
}



$order = json_decode($rawBody, true);
if (!is_array($order)) {
    log_message('error', 'Invalid JSON payload');
    http_response_code(400);
    exit;
}

$topic = isset($_SERVER['HTTP_X_SHOPIFY_TOPIC']) ? (string) $_SERVER['HTTP_X_SHOPIFY_TOPIC'] : '';
if ($topic !== '' && $topic !== 'orders/paid') {
    log_message('info', 'Ignored webhook topic', ['topic' => $topic]);
    http_response_code(200);
    exit;
}

$financial = strtolower((string) ($order['financial_status'] ?? ''));
if ($financial !== '' && $financial !== 'paid') {
    log_message('info', 'Skipped: order not paid', ['financial_status' => $financial]);
    http_response_code(200);
    exit;
}

$shopifyOrderId = isset($order['id']) ? (string) $order['id'] : '';
if ($shopifyOrderId === '') {
    log_message('error', 'Missing order id');
    http_response_code(400);
    exit;
}

if (
    HUBSPOT_PRIVATE_APP_TOKEN === '' || HUBSPOT_PRIVATE_APP_TOKEN === 'YOUR_PRIVATE_APP_TOKEN_HERE'
) {
    log_message('error', 'HubSpot token not configured', ['shopifyOrderId' => $shopifyOrderId]);
    http_response_code(500);
    exit;
}

if (SHOPIFY_ADMIN_API_ACCESS_TOKEN === '' || SHOPIFY_SHOP_DOMAIN === '') {
    log_message('error', 'Shopify Admin API not configured', ['shopifyOrderId' => $shopifyOrderId]);
    http_response_code(500);
    exit;
}

$pgNames = $order['payment_gateway_names'] ?? null;
log_message('info', 'Webhook received', [
    'shopifyOrderId' => $shopifyOrderId,
    'payment_gateway_names' => is_array($pgNames) ? $pgNames : null,
    'gateway' => $order['gateway'] ?? null,
    'requiredType' => SHOPIFY_REQUIRED_PRODUCT_TYPE,
    'achGatewayMatchName' => SHOPIFY_HARDWARE_PAYMENT_GATEWAY_NAME,
]);

$requiredType = SHOPIFY_REQUIRED_PRODUCT_TYPE;
$requiredTypeNorm = strtolower(trim((string) $requiredType));
$lineItems = $order['line_items'] ?? [];
if (!is_array($lineItems) || $lineItems === []) {
    log_message('info', 'Skipped: no line items', ['shopifyOrderId' => $shopifyOrderId]);
    http_response_code(200);
    exit;
}

$hasEmptyProductType = false; // product_type empty/not specified
$hasNonHardware = false; // non-empty product_type that is not hardware
foreach ($lineItems as $item) {
    if (!is_array($item)) {
        log_message('error', 'Skipped: invalid line item', ['shopifyOrderId' => $shopifyOrderId]);
        http_response_code(200);
        exit;
    }
    $productId = $item['product_id'] ?? null;
    if ($productId === null || $productId === '') {
        log_message('error', 'Skipped: line item without product', ['shopifyOrderId' => $shopifyOrderId]);
        http_response_code(200);
        exit;
    }
    $pid = (int) $productId;
    if ($pid <= 0) {
        log_message('error', 'Skipped: invalid product id', ['shopifyOrderId' => $shopifyOrderId, 'productId' => $pid]);
        http_response_code(200);
        exit;
    }
    $ptype = shopify_get_product_type(
        SHOPIFY_SHOP_DOMAIN,
        SHOPIFY_ADMIN_API_ACCESS_TOKEN,
        $pid
    );
    if ($ptype === null) {
        log_message('error', 'Shopify product fetch failed', ['shopifyOrderId' => $shopifyOrderId, 'productId' => $pid]);
        http_response_code(500);
        exit;
    }
    $ptypeNorm = strtolower(trim((string) $ptype));
    if ($ptypeNorm === '') {
        // Empty / not specified => Sale Completed
        $hasEmptyProductType = true;
        continue;
    }
    if ($ptypeNorm !== $requiredTypeNorm) {
        // Non-hardware (non-empty) => Drawing Requested
        $hasNonHardware = true;
    }
}

// "All items are hardware" means: none empty and none non-hardware.
$allHardware = !$hasEmptyProductType && !$hasNonHardware;

// Stage decision:
// - If ANY item has empty product_type => Sale Completed
// - Else if ANY item is non-hardware => Drawing Requested
// - Else (all hardware) => Sale Completed
$dealStageId = HUBSPOT_DEALSTAGE_SALE_COMPLETED_ID;
if (!$hasEmptyProductType && $hasNonHardware) {
    $dealStageId = HUBSPOT_DEALSTAGE_DRAWING_REQUESTED_ID;
}

// Special rule:
// If ALL items are hardware AND payment method is the configured ACH method,
// set the stage to HUBSPOT_DEALSTAGE_HARDWARE_ACH_ID.
if ($allHardware && order_has_payment_gateway($order, SHOPIFY_HARDWARE_PAYMENT_GATEWAY_NAME)) {
    $dealStageId = HUBSPOT_DEALSTAGE_HARDWARE_ACH_ID;
}

log_message('info', 'Stage decision', [
    'shopifyOrderId' => $shopifyOrderId,
    'hasEmptyProductType' => $hasEmptyProductType,
    'hasNonHardware' => $hasNonHardware,
    'allHardware' => $allHardware,
    'achMatched' => order_has_payment_gateway($order, SHOPIFY_HARDWARE_PAYMENT_GATEWAY_NAME),
    'dealStageId' => $dealStageId,
]);

$existing = hubspot_find_deal_id_by_shopify_order($shopifyOrderId);
if ($existing !== null) {
    log_message('info', 'Deal already exists, skipping create', ['shopifyOrderId' => $shopifyOrderId, 'dealId' => $existing]);
    http_response_code(200);
    exit;
}

$created = hubspot_create_deal_from_shopify_order($order, $dealStageId);
if (!$created['ok']) {
    log_message('error', 'HubSpot create failed', [
        'shopifyOrderId' => $shopifyOrderId,
        'status' => $created['status'] ?? null,
        'error' => $created['error'] ?? null,
    ]);
    http_response_code(502);
    exit;
}

http_response_code(200);
log_message('info', 'Created HubSpot deal', [
    'shopifyOrderId' => $shopifyOrderId,
    'dealId' => $created['deal_id'] ?? null,
]);
