import { NextResponse } from 'next/server';
import { and, desc, eq, or, isNull } from 'drizzle-orm';

import { withAuth, withPermission } from '@/lib/api/helpers';
import { db } from '@/lib/db';
import { auditLogs, systemSettings } from '@/lib/db/schema/system';
import { errorResponse } from '@/lib/errors';
import { env } from '@/lib/env';

/**
 * GET /api/v1/admin/documenso-webhook/health
 *
 * Surfaces the current state of the inbound Documenso webhook pipeline
 * for the Documenso admin page's "Webhook health" card. Reads the
 * port's resolved Documenso config + the most recent webhook events
 * from audit_logs. Pairs with the `/test` POST that fires a synthetic
 * webhook through the receiver to verify the full pipeline.
 */
export const GET = withAuth(
  withPermission('admin', 'manage_settings', async (_req, ctx) => {
    try {
      const [portSecretRow] = await db
        .select({ value: systemSettings.value })
        .from(systemSettings)
        .where(
          and(
            eq(systemSettings.key, 'documenso_webhook_secret'),
            or(eq(systemSettings.portId, ctx.portId), isNull(systemSettings.portId)),
          ),
        )
        .limit(1);
      const portWebhookSecret =
        typeof portSecretRow?.value === 'string' && portSecretRow.value.length > 0
          ? portSecretRow.value
          : null;
      const envWebhookSecret = env.DOCUMENSO_WEBHOOK_SECRET ?? null;
      const effectiveSecret = portWebhookSecret ?? envWebhookSecret;
      const expectedUrl = `${env.APP_URL?.replace(/\/$/, '') ?? ''}/api/webhooks/documenso`;

      // Most recent successful webhook landing (entityType=webhook_inbound,
      // action != 'webhook_failed'). The receiver writes one audit row per
      // canonical event; we surface the latest so reps see "yes, traffic
      // is flowing" rather than guessing from logs.
      const [lastReceived] = await db
        .select({
          id: auditLogs.id,
          createdAt: auditLogs.createdAt,
          action: auditLogs.action,
          metadata: auditLogs.metadata,
        })
        .from(auditLogs)
        .where(
          and(eq(auditLogs.entityType, 'webhook_inbound'), eq(auditLogs.entityId, 'documenso')),
        )
        .orderBy(desc(auditLogs.createdAt))
        .limit(1);

      // Latest secret-mismatch entry - flags the "Documenso is hitting us
      // with a wrong secret" failure mode separately from "we haven't
      // heard anything." Combined with `secretConfigured=false` it
      // narrows the problem to a misalignment between the secret we
      // stored and what Documenso is sending.
      const [lastFailed] = await db
        .select({
          id: auditLogs.id,
          createdAt: auditLogs.createdAt,
          metadata: auditLogs.metadata,
        })
        .from(auditLogs)
        .where(
          and(
            eq(auditLogs.entityType, 'webhook_inbound'),
            eq(auditLogs.entityId, 'documenso'),
            eq(auditLogs.action, 'webhook_failed'),
          ),
        )
        .orderBy(desc(auditLogs.createdAt))
        .limit(1);

      return NextResponse.json({
        data: {
          secretConfigured: Boolean(effectiveSecret),
          secretSource: portWebhookSecret ? 'port' : envWebhookSecret ? 'env' : null,
          expectedUrl,
          lastReceived: lastReceived
            ? {
                id: lastReceived.id,
                receivedAt: lastReceived.createdAt,
                action: lastReceived.action,
                metadata: lastReceived.metadata,
              }
            : null,
          lastFailed: lastFailed
            ? {
                id: lastFailed.id,
                receivedAt: lastFailed.createdAt,
                metadata: lastFailed.metadata,
              }
            : null,
        },
      });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
