import { eq, and, desc, sql } from 'drizzle-orm';
import { db } from '../db/index';
import { webhooks } from '../db/schema';
import { eventBus } from '../events/bus';
import { WS_EVENT_TYPES } from '../types/index';
import { createHmac } from 'crypto';

// ═══════════════════════════════════════════════════════════
// Webhook Service — Registration + delivery
// ═══════════════════════════════════════════════════════════

export async function createWebhook(data: {
  url: string;
  events: string[];
  secret?: string;
  createdBy?: string;
}) {
  const [webhook] = await db
    .insert(webhooks)
    .values({
      url: data.url,
      events: data.events,
      secret: data.secret || null,
      active: true,
      createdBy: data.createdBy || null,
    })
    .returning();

  return webhook;
}

export async function listWebhooks() {
  return db
    .select({
      id: webhooks.id,
      url: webhooks.url,
      events: webhooks.events,
      active: webhooks.active,
      createdAt: webhooks.createdAt,
      updatedAt: webhooks.updatedAt,
    })
    .from(webhooks)
    .where(eq(webhooks.active, true))
    .orderBy(desc(webhooks.createdAt));
}

export async function deleteWebhook(id: string) {
  const existing = await db.query.webhooks.findFirst({
    where: eq(webhooks.id, id),
  });

  if (!existing) return null;

  // Soft delete via active flag
  const [updated] = await db
    .update(webhooks)
    .set({ active: false, updatedAt: new Date() })
    .where(eq(webhooks.id, id))
    .returning();

  return updated;
}

export function getAvailableEventTypes() {
  return [...WS_EVENT_TYPES];
}

/**
 * Deliver an event to all matching webhooks.
 * Called by the event bus consumer.
 */
export async function deliverEvent(eventType: string, payload: unknown): Promise<void> {
  const activeWebhooks = await db
    .select()
    .from(webhooks)
    .where(eq(webhooks.active, true));

  for (const wh of activeWebhooks) {
    const events = (wh.events as string[]) || [];
    if (!events.includes(eventType) && !events.includes('*')) continue;

    try {
      const body = JSON.stringify({
        type: eventType,
        timestamp: new Date().toISOString(),
        data: payload,
      });

      const headers: Record<string, string> = {
        'Content-Type': 'application/json',
        'User-Agent': 'GooseFactory-Webhook/1.0',
      };

      // Sign payload if secret is set
      if (wh.secret) {
        const signature = createHmac('sha256', wh.secret)
          .update(body)
          .digest('hex');
        headers['X-Webhook-Signature'] = `sha256=${signature}`;
      }

      // Fire-and-forget HTTP POST
      fetch(wh.url, {
        method: 'POST',
        headers,
        body,
        signal: AbortSignal.timeout(10_000),
      }).catch((err) => {
        console.error(`[Webhook] Delivery failed to ${wh.url}:`, err.message);
      });
    } catch (err) {
      console.error(`[Webhook] Error preparing delivery to ${wh.url}:`, err);
    }
  }
}

/**
 * Initialize webhook delivery consumer
 */
export function initWebhookDelivery(): void {
  eventBus.on('*', (event) => {
    deliverEvent(event.type, event.data).catch((err) => {
      console.error('[Webhook] Delivery consumer error:', err);
    });
  });
  console.log('[Webhook] Delivery consumer initialized');
}
