<?php
declare(strict_types=1);

require_once dirname(__DIR__) . '/_bootstrap.php';
require_once dirname(__DIR__, 3) . '/common/auth_middleware.php';

if (strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
    sync_api_json_response(['status' => 'error', 'code' => 'METHOD_NOT_ALLOWED'], 405);
}

$master = golder_master_pdo();
$tokenRow = golder_auth_token($master, 'desktop_sync');
$customerId = (int)($tokenRow['customer_id'] ?? 0);
if ($customerId <= 0) {
    sync_api_json_response(['status' => 'error', 'code' => 'UNAUTHORIZED'], 401);
}
sync_api_require_profile_sync_customer($customerId);

golder_apply_default_rate_limit($master, 'sync_push_' . $customerId, 120, 60);

$body = sync_api_read_json_body();
$profileId = trim((string)($body['profile_id'] ?? ''));
$dbName = trim((string)($body['db_name'] ?? ''));
$tableName = trim((string)($body['table_name'] ?? ''));
$actionType = strtoupper(trim((string)($body['action_type'] ?? '')));
$recordId = trim((string)($body['record_id'] ?? ''));
$deviceId = trim((string)($body['device_id'] ?? ''));
$transactionUuid = trim((string)($body['transaction_uuid'] ?? ''));
$payload = $body['payload_json'] ?? [];

if ($transactionUuid === '') {
    $transactionUuid = sync_api_uuid4();
}
if ($profileId === '' || $recordId === '' || !sync_api_is_safe_table_name($tableName)) {
    sync_api_json_error(400, 'INVALID_REQUEST', 'profile_id, record_id and safe table_name are required.');
}
if (!in_array($actionType, ['ADD', 'UPDATE', 'DELETE', 'ROLLBACK'], true)) {
    sync_api_json_error(400, 'INVALID_REQUEST', 'action_type is invalid.');
}
if (!is_array($payload)) {
    $payload = [];
}

$extractUpdatedAt = static function (array $p): int {
    $candidates = [
        (string)(($p['after'] ?? [])['updated_at'] ?? ''),
        (string)(($p['before'] ?? [])['updated_at'] ?? ''),
        (string)(($p['meta'] ?? [])['updated_at'] ?? ''),
        (string)($p['updated_at'] ?? ''),
    ];
    foreach ($candidates as $candidate) {
        $candidate = trim($candidate);
        if ($candidate === '') {
            continue;
        }
        $ts = strtotime($candidate);
        if ($ts !== false) {
            return (int)$ts;
        }
    }
    return time();
};

try {
    $requireProfile = ($tableName !== 'profiles');
    $tenantInfo = sync_api_profile_tenant_pdo($profileId, $dbName, $customerId, $requireProfile);
    if (!$tenantInfo || !($tenantInfo['pdo'] instanceof PDO)) {
        $tenantOnly = sync_api_profile_tenant_pdo($profileId, $dbName, $customerId, false);
        if ($tenantOnly && ($tenantOnly['pdo'] instanceof PDO)) {
            sync_api_json_response(
                ['status' => 'deferred', 'code' => 'PROFILE_NOT_READY', 'message' => 'Profile row is not available yet.'],
                409
            );
        }
        sync_api_json_response(
            ['status' => 'error', 'code' => 'PROFILE_DB_NOT_FOUND', 'message' => 'Profile database not found'],
            404
        );
    }
    /** @var PDO $db */
    $db = $tenantInfo['pdo'];
    sync_api_ensure_global_events_table($db);
    if ($tableName === 'profiles' && in_array($actionType, ['ADD', 'UPDATE'], true)) {
        sync_api_ensure_deleted_profiles_table($db);
        if (!sync_api_profile_exists($db, $profileId) && sync_api_deleted_profile_row($db, $profileId)) {
            sync_api_json_response(
                ['status' => 'error', 'code' => 'TOMBSTONED_PROFILE', 'message' => 'Profile was deleted and cannot be restored automatically.'],
                409
            );
        }
    }
    sync_api_assert_table_scope($db, $tableName, $profileId, $payload, $recordId);

    $checkDup = $db->prepare('SELECT id FROM global_sync_events WHERE transaction_uuid = :tx LIMIT 1');
    $checkDup->execute([':tx' => $transactionUuid]);
    $dup = $checkDup->fetch();
    if ($dup) {
        sync_api_json_response(['status' => 'ok', 'event_id' => (int)($dup['id'] ?? 0), 'duplicate' => true], 200);
    }

    $incomingUpdatedAt = $extractUpdatedAt($payload);
    $lastEventSt = $db->prepare(
        'SELECT id, payload_json
         FROM global_sync_events
         WHERE profile_id = :pid AND table_name = :tbl AND record_id = :rid
         ORDER BY id DESC
         LIMIT 1'
    );
    $lastEventSt->execute([':pid' => $profileId, ':tbl' => $tableName, ':rid' => $recordId]);
    $lastEvent = $lastEventSt->fetch();

    if ($lastEvent) {
        $lastPayload = $lastEvent['payload_json'] ?? [];
        if (is_string($lastPayload)) {
            $decoded = json_decode($lastPayload, true);
            $lastPayload = is_array($decoded) ? $decoded : [];
        }
        if (!is_array($lastPayload)) {
            $lastPayload = [];
        }

        $lastUpdatedAt = $extractUpdatedAt($lastPayload);
        if ($incomingUpdatedAt < $lastUpdatedAt) {
            sync_api_json_response([
                'status' => 'ok',
                'stale_ignored' => true,
                'last_event_id' => (int)($lastEvent['id'] ?? 0),
            ], 200);
        }
    }

    $payloadJson = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    if ($payloadJson === false) {
        $payloadJson = '{}';
    }

    $db->beginTransaction();
    sync_api_apply_event_to_table($db, $tableName, $actionType, $recordId, $profileId, $payload);

    $ins = $db->prepare(
        'INSERT INTO global_sync_events
         (transaction_uuid, device_id, profile_id, table_name, action_type, record_id, payload_json, created_at)
         VALUES (:tx, :dev, :pid, :tbl, :act, :rid, :payload, NOW())'
    );
    $ins->execute([
        ':tx' => $transactionUuid,
        ':dev' => $deviceId,
        ':pid' => $profileId,
        ':tbl' => $tableName,
        ':act' => $actionType,
        ':rid' => $recordId,
        ':payload' => $payloadJson,
    ]);

    $eventId = (int)$db->lastInsertId();
    $db->commit();

    sync_api_json_response(['status' => 'ok', 'event_id' => $eventId], 200);
} catch (Throwable $e) {
    if (isset($db) && $db instanceof PDO && $db->inTransaction()) {
        $db->rollBack();
    }
    sync_api_log('SYNC_PUSH_ERROR', [
        'error' => $e->getMessage(),
        'profile_id' => $profileId,
        'table_name' => $tableName,
        'record_id' => $recordId,
        'tx' => $transactionUuid,
        'customer_id' => $customerId,
    ]);
    sync_api_json_response(['status' => 'error', 'code' => 'SERVER_ERROR', 'message' => $e->getMessage()], 500);
}


