<?php

namespace Datalumo\Sync;

use Datalumo\PhpSdk\Exceptions\DatalumoException;

class ContentSync
{
    public function __construct()
    {
        add_action('transition_post_status', [$this, 'onTransitionPostStatus'], 10, 3);
        add_action('before_delete_post', [$this, 'onBeforeDeletePost'], 10, 1);

        add_action('datalumo_sync_entry', [$this, 'processSyncEntry'], 10, 4);
    }

    public function onTransitionPostStatus(string $newStatus, string $oldStatus, \WP_Post $post): void
    {
        if (! datalumo_is_configured() || $this->isAutosaveOrRevision($post->ID)) {
            return;
        }

        $syncs = datalumo_get_syncs_for_post_type($post->post_type);

        if (empty($syncs)) {
            return;
        }

        foreach ($syncs as $sync) {
            if ($newStatus === 'publish') {
                $this->scheduleAction($post->ID, 'upsert', $sync['collection_id'], $sync['meta_mappings'] ?? []);
            } elseif ($oldStatus === 'publish' && $newStatus !== 'publish') {
                $this->scheduleAction($post->ID, 'delete', $sync['collection_id']);
            }
        }
    }

    public function onBeforeDeletePost(int $postId): void
    {
        if (! datalumo_is_configured()) {
            return;
        }

        $post = get_post($postId);

        if (! $post || $post->post_status !== 'publish') {
            return;
        }

        $syncs = datalumo_get_syncs_for_post_type($post->post_type);

        foreach ($syncs as $sync) {
            $this->scheduleAction($postId, 'delete', $sync['collection_id']);
        }
    }

    public function processSyncEntry(int $postId, string $action, string $collectionId, array $metaMappings = []): void
    {
        if (! datalumo_is_configured() || empty($collectionId)) {
            return;
        }

        try {
            $sdk = datalumo_sdk();

            if ($action === 'upsert') {
                $post = get_post($postId);

                if (! $post || $post->post_status !== 'publish') {
                    return;
                }

                $preparer = new EntryPreparer();
                $data = $preparer->prepare($post, $metaMappings);

                if ($data === null) {
                    return;
                }

                $sdk->entries($collectionId)->upsert($data);
            } elseif ($action === 'delete') {
                $sdk->entries($collectionId)->deleteBySource('wordpress', (string) $postId);
            }
        } catch (DatalumoException $e) {
            error_log("Datalumo sync error (post {$postId}, {$action}): {$e->getMessage()} — rescheduling 5 min");

            // Re-queue this single-entry action so the publish/update eventually
            // syncs through a transient API outage. Action Scheduler handles the
            // delay without tying up a web worker.
            \as_schedule_single_action(
                time() + 5 * MINUTE_IN_SECONDS,
                'datalumo_sync_entry',
                [
                    'post_id'        => $postId,
                    'action'         => $action,
                    'collection_id'  => $collectionId,
                    'meta_mappings'  => $metaMappings,
                ],
                'datalumo'
            );
        }
    }

    private function isAutosaveOrRevision(int $postId): bool
    {
        return (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || wp_is_post_revision($postId);
    }

    private function scheduleAction(int $postId, string $action, string $collectionId, array $metaMappings = []): void
    {
        if (function_exists('as_enqueue_async_action')) {
            \as_enqueue_async_action('datalumo_sync_entry', [
                'post_id'        => $postId,
                'action'         => $action,
                'collection_id'  => $collectionId,
                'meta_mappings'  => $metaMappings,
            ], 'datalumo');
        }
    }
}
