/**
 * Datto RMM Webhook Receiver
 * Generic endpoint that accepts any payload from Datto RMM and logs it raw.
 * No processing logic yet — refine after inspecting real payloads.
 */

import { NextRequest, NextResponse } from 'next/server';
import { postgresClient } from '@/lib/services/postgres-client';
import '@/lib/services/pipeline-steps';
import { pipelineEngine } from '@/lib/services/pipeline-engine';
import { getDattoRMMClient } from '@/lib/services/datto-rmm-factory';

async function getDattoPingTarget(alertUid: string): Promise<string | null> {
  try {
    const client = getDattoRMMClient();
    const target = await client.getPingAlertTarget(alertUid);
    return target;
  } catch {
    return null;
  }
}

/**
 * POST /api/webhooks/datto-rmm
 * Accepts any payload, stores it for inspection, returns 200.
 */
export async function POST(request: NextRequest) {
  const receivedAt = new Date();

  try {
    const sourceIp =
      request.headers.get('cf-connecting-ip') ||
      request.headers.get('x-forwarded-for')?.split(',')[0].trim() ||
      request.headers.get('x-real-ip') ||
      'unknown';
    const userAgent = request.headers.get('user-agent') || 'unknown';

    // Verify shared secret header
    const secret = process.env.DATTO_RMM_WEBHOOK_SECRET;
    if (secret) {
      const provided = request.headers.get('x-datto-webhook-secret');
      if (provided !== secret) {
        console.warn(`[DATTO-RMM-WEBHOOK] Invalid or missing X-Datto-Webhook-Secret from ${sourceIp}`);
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
      }
    }

    // Capture all headers as a plain object
    const headers: Record<string, string> = {};
    request.headers.forEach((value, key) => {
      headers[key] = value;
    });

    // Read raw body
    const rawBody = await request.text();

    // Try to parse as JSON; fall back to null
    let payload: any = null;
    try {
      payload = JSON.parse(rawBody);
    } catch {
      // Not valid JSON — store raw_body only
    }

    console.log(
      `[DATTO-RMM-WEBHOOK] Received payload from ${sourceIp} (${rawBody.length} bytes)`
    );

    // Store in database
    await postgresClient.query(
      `INSERT INTO datto_rmm_webhook_logs
         (received_at, source_ip, user_agent, headers, payload, raw_body, status)
       VALUES ($1, $2, $3, $4, $5, $6, 'received')`,
      [
        receivedAt,
        sourceIp,
        userAgent,
        JSON.stringify(headers),
        payload ? JSON.stringify(payload) : null,
        rawBody || null,
      ]
    );

    // Upsert into datto_rmm_alerts if payload looks like a real alert
    if (payload && typeof payload === 'object' && payload.alert_uid && !payload.alert_uid.startsWith('[')) {
      const pingTarget = payload.alert_type === 'PING'
        ? await getDattoPingTarget(payload.alert_uid)
        : null;
      const isResolved = String(payload.triggered).toLowerCase() === 'false';
      const str = (v: unknown) => (v && String(v).trim() !== '' ? String(v) : null);

      await postgresClient.query(
        `INSERT INTO datto_rmm_alerts (
          alert_uid, device_uid, device_name, device_hostname, device_ip, device_os,
          device_description, device_id, site_uid, site_name, site_id, platform,
          priority, alert_category, alert_type, alert_message_en, last_user,
          triggered, resolved, resolved_on,
          device_udf1,  device_udf2,  device_udf3,  device_udf4,  device_udf5,
          device_udf6,  device_udf7,  device_udf8,  device_udf9,  device_udf10,
          device_udf11, device_udf12, device_udf13, device_udf14, device_udf15,
          device_udf16, device_udf17, device_udf18, device_udf19, device_udf20,
          device_udf21, device_udf22, device_udf23, device_udf24, device_udf25,
          device_udf26, device_udf27, device_udf28, device_udf29,
          ping_target,
          timestamp, synced_at
        ) VALUES (
          $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,
          $21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$40,
          $41,$42,$43,$44,$45,$46,$47,$48,$49,
          $50,
          $51,$52
        )
        ON CONFLICT (alert_uid) DO UPDATE SET
          resolved       = EXCLUDED.resolved,
          resolved_on    = CASE WHEN EXCLUDED.resolved AND datto_rmm_alerts.resolved_on IS NULL
                                THEN NOW() ELSE datto_rmm_alerts.resolved_on END,
          triggered      = EXCLUDED.triggered,
          alert_message_en = COALESCE(EXCLUDED.alert_message_en, datto_rmm_alerts.alert_message_en),
          ping_target    = COALESCE(EXCLUDED.ping_target, datto_rmm_alerts.ping_target),
          synced_at      = NOW()`,
        [
          payload.alert_uid,
          str(payload.device_uid),
          str(payload.device_hostname),
          str(payload.device_hostname),
          str(payload.device_ip),
          str(payload.device_os),
          str(payload.device_description),
          str(payload.device_id),
          str(payload.site_uid),
          str(payload.site_name),
          str(payload.site_id),
          str(payload.platform),
          str(payload.alert_priority),
          str(payload.alert_category),
          str(payload.alert_type),
          str(payload.alert_message_en),
          str(payload.last_user),
          String(payload.triggered),
          isResolved,
          isResolved ? receivedAt : null,
          str(payload.device_udf1),  str(payload.device_udf2),  str(payload.device_udf3),
          str(payload.device_udf4),  str(payload.device_udf5),  str(payload.device_udf6),
          str(payload.device_udf7),  str(payload.device_udf8),  str(payload.device_udf9),
          str(payload.device_udf10), str(payload.device_udf11), str(payload.device_udf12),
          str(payload.device_udf13), str(payload.device_udf14), str(payload.device_udf15),
          str(payload.device_udf16), str(payload.device_udf17), str(payload.device_udf18),
          str(payload.device_udf19), str(payload.device_udf20),
          str(payload.device_udf21), str(payload.device_udf22), str(payload.device_udf23),
          str(payload.device_udf24), str(payload.device_udf25), str(payload.device_udf26),
          str(payload.device_udf27), str(payload.device_udf28), str(payload.device_udf29),
          pingTarget,
          receivedAt,
          receivedAt,
        ]
      );

      console.log(`[DATTO-RMM-WEBHOOK] Upserted alert ${payload.alert_uid} — resolved=${isResolved}`);
    }

    // Fire matching pipelines (fire-and-forget)
    if (payload && typeof payload === 'object') {
      pipelineEngine.processTrigger('datto_rmm', payload).catch(err =>
        console.error('[DATTO-RMM-WEBHOOK] Pipeline processing error:', err)
      );
    }

    return NextResponse.json({ success: true, received_at: receivedAt.toISOString() });
  } catch (error) {
    const msg = error instanceof Error ? error.message : String(error);
    console.error('[DATTO-RMM-WEBHOOK] Error storing webhook:', msg);

    // Still return 200 to avoid Datto disabling the webhook
    return NextResponse.json({ success: false, error: msg }, { status: 200 });
  }
}

/**
 * GET /api/webhooks/datto-rmm
 * Health check
 */
export async function GET() {
  return NextResponse.json({
    status: 'active',
    endpoint: '/api/webhooks/datto-rmm',
    message: 'Datto RMM webhook receiver is ready',
  });
}
