import { NextRequest, NextResponse } from 'next/server';
import postgresClient from '@/lib/services/postgres-client';

const PERIOD_INTERVALS: Record<string, string> = {
  '1d':  '1 day',
  '7d':  '7 days',
  '14d': '14 days',
  '30d': '30 days',
};

// Closed AT status values (Complete, Closed variants)
const CLOSED_STATUSES = [5, 29832279, 29832280];

export async function GET(req: NextRequest) {
  try {
    const { searchParams } = new URL(req.url);
    const period   = searchParams.get('period') ?? '7d';
    const interval = PERIOD_INTERVALS[period] ?? '7 days';

    // ── 1. Pulse shadow tickets (open) with company_id ──────────────────────
    // Pull agent name as the reliable hostname — rmm_hostname on the shadow
    // ticket is only populated when the RMM resolver matched the device.
    // datto_rmm_sites.autotask_company_id is not populated, so join companies
    // via name match to get site_id, enabling hostname resolution via agent name.
    const shadowRes = await postgresClient.query(`
      SELECT
        st.job_instance_uid,
        st.job_name,
        st.org_name,
        st.priority_level,
        st.hours_overdue,
        st.failure_category,
        st.opened_at,
        vo.company_id,
        -- Use agent name as the device hostname (most reliable source)
        COALESCE(st.rmm_hostname, ba.name) AS rmm_hostname
      FROM veeam_rpo_shadow_tickets st
      JOIN veeam_backup_agent_jobs j  ON j.instance_uid  = st.job_instance_uid
      JOIN veeam_organizations vo     ON vo.instance_uid = j.organization_uid
      LEFT JOIN veeam_backup_agents ba ON ba.instance_uid = j.backup_agent_uid
      WHERE st.resolved_at IS NULL
    `);

    // ── 2. AT Veeam tickets created by Datto (title: "Veeam:* on HOST at Site")
    //    Use LATERAL to pull one alert row per ticket (most recent) so the
    //    GROUP BY stays clean — no multi-row fanout from the alert join.
    const atRes = await postgresClient.query(`
      WITH ticket_with_alert AS (
        SELECT
          t.ticket_number,
          t.company_id,
          t.title,
          t.status,
          t.priority,
          t.create_date,
          t.completed_date,
          UPPER((regexp_match(t.title, ' on ([A-Za-z0-9][A-Za-z0-9._-]*) at '))[1]) AS hostname,
          a.alert_uid        AS datto_alert_uid,
          a.resolved         AS datto_resolved,
          a.alert_context->>'source' AS datto_source,
          a.timestamp        AS datto_alert_fired
        FROM tickets t
        LEFT JOIN LATERAL (
          SELECT alert_uid, resolved, alert_context, timestamp
          FROM datto_rmm_alerts
          WHERE ticket_number = t.ticket_number
          ORDER BY timestamp DESC
          LIMIT 1
        ) a ON true
        WHERE t.title ILIKE 'Veeam:%'
          AND t.title NOT ILIKE '[Veeam RPO]%'
          AND t.create_date > NOW() - $1::interval
          AND (regexp_match(t.title, ' on ([A-Za-z0-9][A-Za-z0-9._-]*) at '))[1] IS NOT NULL
      )
      SELECT
        company_id,
        hostname,
        COUNT(*)                                                              AS ticket_count,
        COUNT(*) FILTER (
          WHERE completed_date IS NULL
            AND status NOT IN (${CLOSED_STATUSES.join(',')})
        )                                                                     AS open_count,
        MAX(create_date)                                                      AS latest_ticket_at,
        json_agg(
          json_build_object(
            'ticket_number',   ticket_number,
            'title',           title,
            'status',          status,
            'priority',        priority,
            'created_at',      create_date,
            'completed_at',    completed_date,
            'datto_alert_uid', datto_alert_uid,
            'datto_resolved',  datto_resolved,
            'datto_source',    datto_source,
            'datto_alert_fired', datto_alert_fired
          )
          ORDER BY create_date DESC
        )                                                                     AS tickets
      FROM ticket_with_alert
      GROUP BY company_id, hostname
    `, [interval]);

    // ── 3. Recent offline suppressions (latest per job) ─────────────────────
    const offlineRes = await postgresClient.query(`
      SELECT DISTINCT ON (job_instance_uid)
        job_instance_uid, rmm_hostname, org_name, hours_offline, checked_at
      FROM veeam_rpo_offline_log
      WHERE checked_at > NOW() - $1::interval
      ORDER BY job_instance_uid, checked_at DESC
    `, [interval]);

    // ── 4. Build lookup maps ─────────────────────────────────────────────────
    // Pulse: keyed by "company_id|hostname_lower".
    // If no hostname is available (agent not found), use job_instance_uid as key
    // so the row still appears as pulse_only in the comparison.
    const shadowByKey = new Map<string, any>();
    for (const row of shadowRes.rows) {
      const key = row.rmm_hostname
        ? `${row.company_id}|${row.rmm_hostname.toLowerCase()}`
        : `pulse_only|${row.job_instance_uid}`;
      shadowByKey.set(key, row);
    }

    // Offline: keyed by job_instance_uid
    const offlineByUid = new Map<string, any>();
    for (const row of offlineRes.rows) {
      offlineByUid.set(row.job_instance_uid, row);
    }

    // AT/Datto: keyed by "company_id|hostname_lower"
    const atByKey = new Map<string, any>();
    for (const row of atRes.rows) {
      if (!row.hostname) continue;
      const key = `${row.company_id}|${row.hostname.toLowerCase()}`;
      atByKey.set(key, row);
    }

    // ── 5. Build comparison rows ─────────────────────────────────────────────
    const allKeys = new Set([...shadowByKey.keys(), ...atByKey.keys()]);
    const matches: any[] = [];

    for (const key of allKeys) {
      const shadow = shadowByKey.get(key) ?? null;
      const at     = atByKey.get(key) ?? null;
      const offline = shadow ? offlineByUid.get(shadow.job_instance_uid) ?? null : null;

      let status: string;
      if (shadow && at)      status = 'both';
      else if (shadow)       status = offline ? 'offline_suppressed' : 'pulse_only';
      else                   status = 'datto_only';

      const tickets = (at?.tickets ?? []).slice(0, 5);

      matches.push({
        key,
        hostname:  shadow?.rmm_hostname ?? at?.hostname ?? null,
        org_name:  shadow?.org_name ?? null,
        company_id: shadow?.company_id ?? at?.company_id ?? null,
        status,
        pulse: shadow ? {
          job_instance_uid: shadow.job_instance_uid,
          job_name:         shadow.job_name,
          priority_level:   shadow.priority_level,
          hours_overdue:    shadow.hours_overdue,
          failure_category: shadow.failure_category,
          opened_at:        shadow.opened_at,
        } : null,
        offline: offline ? {
          hours_offline:   offline.hours_offline,
          last_suppressed: offline.checked_at,
        } : null,
        // Datto/AT side
        at_ticket_count: at?.ticket_count ?? 0,
        at_open_count:   at?.open_count ?? 0,
        at_latest_at:    at?.latest_ticket_at ?? null,
        at_tickets:      tickets,
      });
    }

    // Sort: both → pulse_only → datto_only → offline_suppressed
    const rank: Record<string, number> = { both: 0, pulse_only: 1, datto_only: 2, offline_suppressed: 3 };
    matches.sort((a, b) => {
      const r = rank[a.status] - rank[b.status];
      if (r !== 0) return r;
      return (b.pulse?.hours_overdue ?? 0) - (a.pulse?.hours_overdue ?? 0);
    });

    const summary = {
      pulse_open:         shadowRes.rows.length,
      datto_at_total:     atRes.rows.reduce((s: number, r: any) => s + parseInt(r.ticket_count), 0),
      datto_at_open:      atRes.rows.reduce((s: number, r: any) => s + parseInt(r.open_count), 0),
      both:               matches.filter(m => m.status === 'both').length,
      pulse_only:         matches.filter(m => m.status === 'pulse_only').length,
      datto_only:         matches.filter(m => m.status === 'datto_only').length,
      offline_suppressed: offlineRes.rows.length,
    };

    return NextResponse.json({ period, summary, matches });
  } catch (err: any) {
    return NextResponse.json({ error: err.message }, { status: 500 });
  }
}
