import db from "../db.server";
import { RULES } from "./rules";
import { syncRulesToMetafield } from "./metafield-sync.server";
import { adminLog } from "./admin-logger.server";

interface ShopifyAdmin {
  graphql: (query: string, options?: { variables?: Record<string, unknown> }) => Promise<Response>;
}

export async function ensureShopSetup(
  admin: ShopifyAdmin,
  session: { shop: string },
): Promise<string> {
  const shopDomain = session.shop;

  const existingShop = await db.shop.findUnique({
    where: { id: shopDomain },
  });

  if (existingShop && existingShop.isActive) {
    // Migrate: split old tagged rule into collections + blogs
    await migrateTaggedRule(shopDomain);
    return shopDomain;
  }

  // Use transaction to prevent race conditions
  await db.$transaction(async (tx) => {
    // Upsert the shop
    await tx.shop.upsert({
      where: { id: shopDomain },
      create: {
        id: shopDomain,
        name: shopDomain,
        isActive: true,
      },
      update: {
        isActive: true,
        uninstalledAt: null,
      },
    });

    // Check if rules exist already
    const existingRulesCount = await tx.shopRule.count({
      where: { shopId: shopDomain },
    });

    if (existingRulesCount === 0) {
      // Create default rules (transaction prevents race condition)
      await tx.shopRule.createMany({
        data: RULES.map((rule) => ({
          shopId: shopDomain,
          ruleKey: rule.key,
          enabled: rule.defaultEnabled,
        })),
      });
    }
  });

  // Sync initial config outside transaction (external API call)
  const existingRulesCount = await db.shopRule.count({
    where: { shopId: shopDomain },
  });
  if (existingRulesCount > 0) {
    await syncRulesToMetafield(admin, shopDomain);
  }

  return shopDomain;
}

async function migrateTaggedRule(shopDomain: string) {
  const oldRule = await db.shopRule.findUnique({
    where: { shopId_ruleKey: { shopId: shopDomain, ruleKey: "noindex_tagged_collections_and_blogs" } },
  });
  if (!oldRule) return;

  // Create the two new rules with the same enabled state
  await db.shopRule.createMany({
    data: [
      { shopId: shopDomain, ruleKey: "noindex_tagged_collections", enabled: oldRule.enabled },
      { shopId: shopDomain, ruleKey: "noindex_tagged_blogs", enabled: oldRule.enabled },
    ],
    skipDuplicates: true,
  });

  // Delete the old rule
  await db.shopRule.delete({
    where: { shopId_ruleKey: { shopId: shopDomain, ruleKey: "noindex_tagged_collections_and_blogs" } },
  });
}

export async function markShopUninstalled(
  shopDomain: string,
): Promise<void> {
  try {
    await db.shop.update({
      where: { id: shopDomain },
      data: {
        isActive: false,
        uninstalledAt: new Date(),
      },
    });
  } catch (error) {
    // Shop may not exist in our DB yet — log for visibility
    await adminLog("warn", `Failed to mark shop as uninstalled: ${error instanceof Error ? error.message : String(error)}`, { shopId: shopDomain });
  }
}
