import axios from 'axios';
import { prisma } from '../../config/database.js';
import { signWebhookPayload } from '../../utils/crypto.js';
import { logger } from '../../utils/logger.js';
import { WEBHOOK_EVENTS } from '../../config/constants.js';

interface WebhookPayload {
  event: string;
  timestamp: string;
  data: Record<string, unknown>;
}

/**
 * Send a webhook notification to the tenant's configured webhook URL.
 * Includes HMAC-SHA256 signature for verification.
 */
export async function sendWebhook(
  tenantId: string,
  event: string,
  data: Record<string, unknown>,
): Promise<boolean> {
  try {
    const tenant = await prisma.tenant.findUnique({
      where: { id: tenantId },
      select: { webhookUrl: true, webhookSecret: true },
    });

    if (!tenant?.webhookUrl) {
      logger.debug({ tenantId, event }, '[Webhook] No webhook URL configured, skipping');
      return false;
    }

    const payload: WebhookPayload = {
      event,
      timestamp: new Date().toISOString(),
      data,
    };

    const body = JSON.stringify(payload);
    const signature = tenant.webhookSecret
      ? signWebhookPayload(body, tenant.webhookSecret)
      : '';

    const response = await axios.post(tenant.webhookUrl, payload, {
      headers: {
        'Content-Type': 'application/json',
        'X-BidCast-Signature': signature,
        'X-BidCast-Event': event,
        'User-Agent': 'BidCast-Webhook/1.0',
      },
      timeout: 10000, // 10 second timeout
      validateStatus: (status) => status < 500, // Don't throw on 4xx
    });

    const success = response.status >= 200 && response.status < 300;

    logger.info({
      tenantId,
      event,
      status: response.status,
      success,
    }, '[Webhook] Sent');

    return success;
  } catch (err: any) {
    logger.error({
      tenantId,
      event,
      error: err.message,
    }, '[Webhook] Failed to send');
    return false;
  }
}

/**
 * Send cart.item_added webhook and update cart event status.
 */
export async function sendCartWebhook(cartEventId: string): Promise<void> {
  try {
    const cartEvent = await prisma.cartEvent.findUnique({
      where: { id: cartEventId },
      include: {
        bid: {
          select: { igUsername: true, amount: true, bidType: true },
        },
        auctionItem: {
          include: {
            product: {
              select: {
                externalId: true,
                name: true,
                price: true,
                imageUrl: true,
                currency: true,
              },
            },
            liveSession: {
              select: { igLiveVideoId: true, title: true },
            },
          },
        },
        user: {
          select: {
            igUsername: true,
            email: true,
            displayName: true,
            externalUserId: true,
          },
        },
      },
    });

    if (!cartEvent) return;

    const success = await sendWebhook(
      cartEvent.tenantId,
      WEBHOOK_EVENTS.CART_ITEM_ADDED,
      {
        cart_event_id: cartEvent.id,
        product: {
          external_id: cartEvent.auctionItem.product.externalId,
          name: cartEvent.auctionItem.product.name,
          price: Number(cartEvent.bid.amount),
          currency: cartEvent.auctionItem.product.currency,
          image_url: cartEvent.auctionItem.product.imageUrl,
        },
        buyer: {
          ig_username: cartEvent.bid.igUsername,
          user_id: cartEvent.userId,
          email: cartEvent.user?.email ?? null,
          display_name: cartEvent.user?.displayName ?? null,
          external_user_id: cartEvent.user?.externalUserId ?? null,
        },
        session: {
          ig_live_video_id: cartEvent.auctionItem.liveSession.igLiveVideoId,
          title: cartEvent.auctionItem.liveSession.title,
        },
        bid_type: cartEvent.bid.bidType,
      },
    );

    await prisma.cartEvent.update({
      where: { id: cartEventId },
      data: {
        status: success ? 'sent' : 'failed',
        sentAt: new Date(),
        webhookResponse: { success, sentAt: new Date().toISOString() },
      },
    });
  } catch (err) {
    logger.error({ err, cartEventId }, '[Webhook] Error sending cart webhook');

    await prisma.cartEvent.update({
      where: { id: cartEventId },
      data: {
        status: 'failed',
        webhookResponse: { error: String(err), sentAt: new Date().toISOString() },
      },
    }).catch(() => {});
  }
}

/**
 * Send auction-related webhooks.
 */
export async function sendAuctionStartedWebhook(
  tenantId: string,
  auctionItem: { id: string; mode: string; startingPrice: number; productName: string; timeLimitSeconds: number | null },
) {
  await sendWebhook(tenantId, WEBHOOK_EVENTS.AUCTION_STARTED, {
    auction_item_id: auctionItem.id,
    mode: auctionItem.mode,
    starting_price: auctionItem.startingPrice,
    product_name: auctionItem.productName,
    time_limit_seconds: auctionItem.timeLimitSeconds,
  });
}

export async function sendAuctionEndedWebhook(
  tenantId: string,
  auctionItem: { id: string; productName: string; winnerIgUsername?: string; finalPrice: number },
) {
  await sendWebhook(tenantId, WEBHOOK_EVENTS.AUCTION_ENDED, {
    auction_item_id: auctionItem.id,
    product_name: auctionItem.productName,
    winner_ig_username: auctionItem.winnerIgUsername ?? null,
    final_price: auctionItem.finalPrice,
  });
}
