<?php
declare(strict_types=1);

/**
 * Shopify webhook: orders/updated and draft_orders/update
 *
 * Read raw body FIRST so no other code can consume php://input before HMAC verification.
 */

@set_time_limit(180);

$rawBody = file_get_contents('php://input');
$rawBody = is_string($rawBody) ? $rawBody : '';

require_once __DIR__ . '/../pandadoc_integration/orchestrator.php';

if (!function_exists('shopify_webhook_log')) {
    function shopify_webhook_log(string $message, array $context = []): void {
        $logDir = dirname(__DIR__, 1) . '/log';
        $logFile = $logDir . '/shopify_webhook.log';
        if (!is_dir($logDir)) {
            @mkdir($logDir, 0777, true);
        }
        $line = '[' . date('c') . '] ' . $message;
        if (!empty($context)) {
            $json = @json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            if (is_string($json) && $json !== '') {
                $line .= ' ' . $json;
            }
        }
        @file_put_contents($logFile, $line . "\n", FILE_APPEND);
    }
}

register_shutdown_function(static function (): void {
    $err = error_get_last();
    if (!is_array($err)) {
        return;
    }
    if (!in_array($err['type'] ?? 0, [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {
        return;
    }
    shopify_webhook_log('FATAL PHP error', $err);
});

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

//shopify_verify_webhook($rawBody);

$topic = (string)($_SERVER['HTTP_X_SHOPIFY_TOPIC'] ?? '');
$shopDomain = (string)($_SERVER['HTTP_X_SHOPIFY_SHOP_DOMAIN'] ?? '');
shopify_webhook_log('Webhook received', [
    'topic' => $topic,
    'shop' => $shopDomain,
    'method' => (string)($_SERVER['REQUEST_METHOD'] ?? ''),
    'body_length' => strlen($rawBody),
    'has_hmac' => isset($_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256']),
]);

$payloadPreview = strlen($rawBody) > 4000 ? (substr($rawBody, 0, 4000) . '…[truncated]') : $rawBody;
shopify_webhook_log('Webhook payload', ['body' => $payloadPreview]);

$isOrderTopic = ($topic === 'orders/updated');
$isDraftTopic = ($topic === 'draft_orders/update');
if (!$isOrderTopic && !$isDraftTopic) {
    shopify_webhook_ignore('topic', ['topic' => $topic]);
}

$payload = json_decode($rawBody, true);
if (!is_array($payload)) {
    shopify_webhook_ignore('non-json');
}

$entityId = (int)($payload['id'] ?? $payload['order']['id'] ?? $payload['draft_order']['id'] ?? 0);
if ($entityId <= 0) {
    shopify_webhook_ignore('no-entity-id', ['topic' => $topic]);
}

$idKey = $isOrderTopic ? 'order_id' : 'draft_order_id';
shopify_webhook_log('Processing entity', [
    'topic' => $topic,
    $idKey => $entityId,
    'payload_name' => (string)($payload['name'] ?? ''),
]);

try {
    if ($isOrderTopic) {
        $entity = shopify_get_order_minimal($entityId);
        $setMetafields = static fn(array $mfs) => shopify_set_order_metafields($entityId, $mfs);
        $runGenerate = static fn() => pd_run_generate_for_order($entityId);
    } else {
        $entity = shopify_get_draft_order_minimal($entityId);
        $setMetafields = static fn(array $mfs) => shopify_set_draft_order_metafields($entityId, $mfs);
        $runGenerate = static fn() => pd_run_generate_for_draft_order($entityId);
    }
} catch (Throwable $e) {
    shopify_webhook_log('ERROR: entity fetch exception', [
        'topic' => $topic,
        $idKey => $entityId,
        'error' => $e->getMessage(),
    ]);
    pd_log('shopify_metafields_update entity fetch failed', ['topic' => $topic, $idKey => $entityId, 'error' => $e->getMessage()]);
    pd_json(500, ['success' => false, 'error' => 'Entity fetch failed', 'details' => $e->getMessage()]);
}

$metafieldSummary = pd_summarize_custom_metafields($entity);
shopify_webhook_log('Custom metafields from GraphQL', [
    $idKey => $entityId,
    'metafields' => $metafieldSummary,
]);

$mf = pd_extract_custom_metafield($entity, 'document_generate');
$isTrigger = pd_metafield_is_true($mf);
shopify_webhook_log('document_generate check', [
    $idKey => $entityId,
    'raw_value' => $mf['value'] ?? null,
    'is_trigger' => $isTrigger,
]);

if (!$isTrigger) {
    shopify_webhook_ignore('document_generate_not_true', [
        'topic' => $topic,
        $idKey => $entityId,
        'metafields' => $metafieldSummary,
    ]);
}

if ($isOrderTopic) {
    $draftBlock = pd_order_blocked_by_draft_generation($entityId);
    if (is_array($draftBlock)) {
        pd_sync_order_metafields_from_draft_row($entityId, $draftBlock);
        try {
            $setMetafields([
                ['namespace' => 'custom', 'key' => 'document_generate', 'type' => 'boolean', 'value' => false],
            ]);
        } catch (Throwable $e) {
            shopify_webhook_log('WARN: failed to reset order trigger after draft block', [
                'order_id' => $entityId,
                'error' => $e->getMessage(),
            ]);
        }
        shopify_webhook_ignore('draft_already_generated', [
            'order_id' => $entityId,
            'draft_order_id' => (int)($draftBlock['shopify_draft_order_id'] ?? 0),
            'pandadoc_document_id' => (string)($draftBlock['pandadoc_document_id'] ?? ''),
        ]);
    }
}

$lockedMf = pd_extract_custom_metafield($entity, 'document_generate_locked');
if (pd_metafield_is_true($lockedMf)) {
    shopify_webhook_ignore('document_generate_locked', [$idKey => $entityId]);
}

$docIdMf = pd_extract_custom_metafield($entity, 'document_id');
$statusMf = pd_extract_custom_metafield($entity, 'document_status');
$existingDocId = trim((string)($docIdMf['value'] ?? ''));
$existingStatus = trim((string)($statusMf['value'] ?? ''));
if ($existingDocId !== '' && in_array($existingStatus, ['completed', 'sent', 'viewed'], true)) {
    shopify_webhook_ignore('document_already_exists', [
        $idKey => $entityId,
        'document_id' => $existingDocId,
        'document_status' => $existingStatus,
    ]);
}

$driveUrl = pd_extract_drive_pdf_url_from_entity($entity);
shopify_webhook_log('Drive PDF URL resolved', [
    $idKey => $entityId,
    'drive_url_set' => $driveUrl !== null && $driveUrl !== '',
    'drive_url_preview' => $driveUrl !== null ? substr($driveUrl, 0, 80) : null,
]);

shopify_webhook_log('TRIGGER ACCEPTED — starting PandaDoc generate', [
    'topic' => $topic,
    $idKey => $entityId,
]);
pd_log('Trigger received', ['topic' => $topic, $idKey => $entityId]);

try {
    $setMetafields([
        ['namespace' => 'custom', 'key' => 'document_generate', 'type' => 'boolean', 'value' => false],
        ['namespace' => 'custom', 'key' => 'document_status', 'type' => 'single_line_text_field', 'value' => 'queued'],
    ]);
    shopify_webhook_log('Trigger metafields reset to queued', [$idKey => $entityId]);
} catch (Throwable $e) {
    shopify_webhook_log('WARN: failed to reset trigger metafield', [
        $idKey => $entityId,
        'error' => $e->getMessage(),
    ]);
    pd_log('Failed to reset trigger metafield', [$idKey => $entityId, 'err' => $e->getMessage()]);
}

http_response_code(200);
echo json_encode(['success' => true, 'accepted' => true, $idKey => $entityId, 'topic' => $topic]);

if (function_exists('fastcgi_finish_request')) {
    @fastcgi_finish_request();
}

try {
    $result = $runGenerate();
    shopify_webhook_log('Generate finished', [
        'topic' => $topic,
        $idKey => $entityId,
        'result' => $result,
    ]);
    pd_log('Generate finished', ['topic' => $topic, $idKey => $entityId, 'result' => $result]);
} catch (Throwable $e) {
    shopify_webhook_log('ERROR: generate exception', [
        'topic' => $topic,
        $idKey => $entityId,
        'error' => $e->getMessage(),
        'file' => $e->getFile(),
        'line' => $e->getLine(),
    ]);
    pd_log('Generate exception', ['topic' => $topic, $idKey => $entityId, 'error' => $e->getMessage()]);
}
