import type {DocumentActionComponent} from "sanity";
import {useClient} from "sanity";

const API_VERSION = "2026-03-26";

function buildThemeReferenceKey(themeId: string, productId: string) {
  return `theme-${themeId}-${productId.replace(/^drafts\./, "")}`.slice(0, 120);
}

function wait(ms: number) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function waitForPublishedTheme(client: ReturnType<typeof useClient>, themeId: string) {
  for (let attempt = 0; attempt < 12; attempt += 1) {
    const theme = await client.getDocument(themeId);
    if (theme) {
      return true;
    }

    await wait(500);
  }

  return false;
}

async function attachThemeToAllProducts(client: ReturnType<typeof useClient>, themeId: string) {
  const productIds = await client.fetch<string[]>(
    `*[_type == "product" && !references($themeId)]._id`,
    {themeId},
  );

  if (!productIds.length) {
    return;
  }

  let transaction = client.transaction();

  for (const productId of productIds) {
    transaction = transaction.patch(productId, (patch) =>
      patch
        .setIfMissing({themes: []})
        .append("themes", [
          {
            _type: "reference",
            _ref: themeId,
            _key: buildThemeReferenceKey(themeId, productId),
          },
        ]),
    );
  }

  await transaction.commit();
}

export function createThemePublishAction(originalPublishAction: DocumentActionComponent): DocumentActionComponent {
  return function ThemePublishAction(props) {
    const client = useClient({apiVersion: API_VERSION});
    const originalResult = originalPublishAction(props);

    if (!originalResult) {
      return null;
    }

    const themeId = props.id.replace(/^drafts\./, "");
    const isFirstPublish = !props.published;

    return {
      ...originalResult,
      onHandle: () => {
        originalResult.onHandle?.();

        if (!isFirstPublish || !themeId) {
          return;
        }

        void (async () => {
          const isPublished = await waitForPublishedTheme(client, themeId);
          if (!isPublished) {
            console.error(`[theme-publish-action] Theme ${themeId} was not published in time; skipping product auto-link.`);
            return;
          }

          await attachThemeToAllProducts(client, themeId);
        })();
      },
    };
  };
}
