import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/db/client';
import { decrypt, encrypt } from '@/lib/crypto/encryption';
import { ShopifyClient } from '@/lib/shopify/client';
import { MetaGraphClient } from '@/lib/meta/client';
import { CatalogSyncRecord } from '@/types';
import { getAuthenticatedStore, unauthorizedResponse } from '@/lib/auth/storeContext';
import { logger } from '@/lib/logger';

export const dynamic = 'force-dynamic';

export async function POST(req: NextRequest) {
  try {
    const shop = await getAuthenticatedStore(req);
    if (!shop) {
      return unauthorizedResponse();
    }

    const body = await req.json().catch(() => ({}));
    const { forceFull, shopifyAccessToken } = body;

    let token = shopifyAccessToken?.trim();
    if (token) {
      await db.upsertShop({
        ...shop,
        access_token_encrypted: encrypt(token),
        status: 'installed',
        updated_at: new Date().toISOString(),
      });
    }

    // Create sync record
    const syncId = `sync_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`;
    const syncRecord: CatalogSyncRecord = {
      id: syncId,
      shop_id: shop.id,
      sync_type: 'batch_api',
      status: 'processing',
      total_products: 0,
      processed_products: 0,
      failed_products: 0,
      warning_count: 0,
      started_at: new Date().toISOString(),
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
    };

    await db.createSync(syncRecord);

    const client = new ShopifyClient(shop.shopify_domain, token || '');

    try {
      // Fetch live products & variants directly from Shopify GraphQL API
      const products = await client.fetchAllProductsForCatalog(shop.id);

      // Clean existing products for this shop if full sync requested
      if (forceFull !== false) {
        await db.clearProductsByShopId(shop.id);
      }

      // Upsert all fetched products & variants
      for (const prod of products) {
        await db.upsertProduct(prod);
      }

      // If Meta is connected, push batch items to Meta Catalog
      let metaSyncResult = null;
      try {
        const metaConn = await db.getMetaConnectionByShopId(shop.id);
        if (metaConn && metaConn.catalog_id && metaConn.status === 'connected' && metaConn.access_token_encrypted) {
          const metaToken = decrypt(metaConn.access_token_encrypted);
          const metaClient = new MetaGraphClient(metaToken);
          metaSyncResult = await metaClient.syncCatalogBatch(metaConn.catalog_id, products);
        }
      } catch (metaErr) {
        logger.warn(`Meta catalog sync batch error: ${metaErr instanceof Error ? metaErr.message : String(metaErr)}`);
      }

      // Update sync state to completed
      await db.updateSync(syncId, {
        status: 'completed',
        total_products: products.length,
        processed_products: products.length,
        failed_products: 0,
        completed_at: new Date().toISOString(),
      });

      await db.recordAuditLog({
        id: `audit_${Date.now()}`,
        shop_id: shop.id,
        action: 'catalog_sync_completed',
        actor: 'merchant',
        metadata: { total: products.length, shopDomain: shop.shopify_domain },
        created_at: new Date().toISOString(),
      });

      return NextResponse.json({
        success: true,
        syncId,
        status: 'completed',
        totalProducts: products.length,
        message: `Successfully synchronized ${products.length} live product variants directly from ${shop.shopify_domain}`,
        metaSync: metaSyncResult,
        products,
      });
    } catch (syncErr: any) {
      const errorMsg = syncErr instanceof Error ? syncErr.message : String(syncErr);
      logger.error('Catalog sync execution error:', errorMsg);

      await db.updateSync(syncId, {
        status: 'failed',
        error_message: errorMsg,
        completed_at: new Date().toISOString(),
      });

      return NextResponse.json(
        {
          success: false,
          error: errorMsg,
          syncId,
          status: 'failed',
          hint: errorMsg.includes('token') || errorMsg.includes('401') || errorMsg.includes('Unauthorized')
            ? 'Please provide or verify your Shopify Admin Access Token in Settings -> Shopify App Configuration.'
            : undefined,
        },
        { status: 400 }
      );
    }
  } catch (err) {
    return NextResponse.json(
      { success: false, error: err instanceof Error ? err.message : 'Internal Server Error' },
      { status: 500 }
    );
  }
}
