import { NextRequest, NextResponse } from 'next/server';
import { requireAdminAuth, getClientIP } from '@/lib/admin/session';
import { auditLog } from '@/lib/admin/audit';
import { logger } from '@/lib/logger';
import {
  effectiveConsent,
  loadState,
  saveState,
  buildPayload,
  sendOnce,
  reschedule,
  DEFAULT_ENDPOINT,
  getLoginCounts,
  resolveEndpointAllowed,
} from '@/lib/telemetry';

/**
 * GET /api/admin/telemetry
 * Returns current consent + endpoint + next/last send + a live preview
 * of exactly what the next heartbeat would contain.
 */
export async function GET() {
  try {
    const auth = await requireAdminAuth();
    if ('error' in auth) return auth.error;

    const { consent, source, state } = await effectiveConsent();
    const [payload, accountCounts] = await Promise.all([
      buildPayload(),
      getLoginCounts(),
    ]);

    return NextResponse.json(
      {
        consent,
        consentSource: source,
        endpoint: state.endpoint || DEFAULT_ENDPOINT,
        consentedAt: state.consentedAt,
        lastSentAt: state.lastSentAt,
        nextScheduledAt: state.nextScheduledAt,
        defaultEndpoint: DEFAULT_ENDPOINT,
        payloadPreview: payload,
        accountCounts,
      },
      { headers: { 'Cache-Control': 'no-store' } },
    );
  } catch (err) {
    logger.error('telemetry GET error', {
      error: err instanceof Error ? err.message : 'unknown',
    });
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
  }
}

/**
 * POST /api/admin/telemetry
 * Body: { action: 'set-consent' | 'set-endpoint' | 'send-now', ... }
 *   set-consent  : { action, consent: 'on' | 'off' }
 *   set-endpoint : { action, endpoint: string }
 *   send-now     : { action }
 */
export async function POST(request: NextRequest) {
  try {
    const auth = await requireAdminAuth();
    if ('error' in auth) return auth.error;
    const ip = getClientIP(request);

    const body = (await request.json().catch(() => null)) as
      | { action?: string; consent?: string; endpoint?: string }
      | null;
    if (!body || typeof body.action !== 'string') {
      return NextResponse.json({ error: 'action required' }, { status: 400 });
    }

    const { source } = await effectiveConsent();

    if (body.action === 'set-consent') {
      if (source === 'env') {
        return NextResponse.json(
          { error: 'consent is overridden by BULWARK_TELEMETRY env var' },
          { status: 409 },
        );
      }
      if (body.consent !== 'on' && body.consent !== 'off') {
        return NextResponse.json({ error: 'consent must be "on" or "off"' }, { status: 400 });
      }
      const state = await loadState();
      const before = state.consent;
      state.consent = body.consent;
      if (body.consent === 'on' && !state.consentedAt) {
        state.consentedAt = new Date().toISOString();
      }
      await saveState(state);
      await reschedule();
      await auditLog('telemetry.set-consent', { from: before, to: body.consent }, ip);
      return NextResponse.json({ ok: true });
    }

    if (body.action === 'set-endpoint') {
      if (typeof body.endpoint !== 'string') {
        return NextResponse.json({ error: 'endpoint required' }, { status: 400 });
      }
      const trimmed = body.endpoint.trim();
      if (trimmed) {
        const check = await resolveEndpointAllowed(trimmed);
        if (!check.ok) {
          return NextResponse.json({ error: check.reason }, { status: 400 });
        }
      }
      const state = await loadState();
      const before = state.endpoint;
      state.endpoint = trimmed || DEFAULT_ENDPOINT;
      await saveState(state);
      await auditLog('telemetry.set-endpoint', { from: before, to: state.endpoint }, ip);
      return NextResponse.json({ ok: true, endpoint: state.endpoint });
    }

    if (body.action === 'send-now') {
      const result = await sendOnce({ reason: 'admin-manual' });
      await auditLog(
        'telemetry.send-now',
        { ok: result.ok, status: result.status ?? null, error: result.error ?? null },
        ip,
      );
      return NextResponse.json(result, { status: result.ok ? 200 : 502 });
    }

    return NextResponse.json({ error: 'unknown action' }, { status: 400 });
  } catch (err) {
    logger.error('telemetry POST error', {
      error: err instanceof Error ? err.message : 'unknown',
    });
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
  }
}
