/**
 * P1-10 — compact scheduled report builder.
 *
 * Aggregates a per-user uptime summary over a configurable window
 * (matched to the report's frequency). Returns the HTML body + a
 * plain-text subject suitable for the existing email service.
 *
 * Heartbeat math is intentionally simple to stay readable: per-monitor
 * we count `down` heartbeats out of total non-maintenance heartbeats
 * in the window. Maintenance time is excluded (matches Theme C's SLA
 * calculator semantics). Incident count comes from StatusIncident.
 */
import type { PrismaClient } from '@prisma/client';

export interface ReportFrequency {
    frequency: 'weekly' | 'monthly' | 'quarterly' | string;
}

const ONE_DAY_MS = 24 * 60 * 60 * 1000;
const WINDOW_DAYS: Record<string, number> = {
    weekly: 7,
    monthly: 30,
    quarterly: 90,
};

interface MonitorRow {
    name: string;
    region: string | null;
    type: string;
    uptimePercent: number;
    downCount: number;
    totalCount: number;
}

export interface BuiltReport {
    subject: string;
    html: string;
    summary: { monitors: number; incidentsInPeriod: number; periodDays: number };
}

export async function buildScheduledReport(
    prisma: PrismaClient,
    userId: number,
    frequency: string,
    now: Date = new Date()
): Promise<BuiltReport | null> {
    const days = WINDOW_DAYS[frequency];
    if (typeof days !== 'number') return null;

    const since = new Date(now.getTime() - days * ONE_DAY_MS);

    const monitors = await prisma.monitor.findMany({
        where: { userId, deletedAt: null },
        select: { id: true, name: true, region: true, type: true },
        orderBy: { name: 'asc' },
    });

    const rows: MonitorRow[] = [];
    for (const m of monitors) {
        // Group-by status. `maintenance` rows are excluded from the
        // denominator so planned downtime doesn't drag the number.
        const grouped = await prisma.heartbeat.groupBy({
            by: ['status'],
            where: {
                monitorId: m.id,
                createdAt: { gte: since },
                status: { in: ['up', 'down'] },
            },
            _count: { _all: true },
        });
        const counts: Record<string, number> = {};
        for (const g of grouped) counts[g.status] = g._count._all;
        const up = counts.up || 0;
        const down = counts.down || 0;
        const total = up + down;
        const uptimePercent = total === 0 ? 100 : Math.round((up / total) * 10000) / 100;
        rows.push({
            name: m.name,
            region: m.region ?? null,
            type: m.type,
            uptimePercent,
            downCount: down,
            totalCount: total,
        });
    }

    const incidentsInPeriod = await prisma.statusIncident.count({
        where: {
            createdAt: { gte: since },
            deletedAt: null,
        },
    });

    const subject = `Uptime Sentinel ${frequency} report — ${rows.length} monitor${rows.length === 1 ? '' : 's'}`;

    const tableRows = rows.map((r) => {
        const colour = r.uptimePercent >= 99.5 ? '#10b981' : r.uptimePercent >= 95 ? '#f59e0b' : '#ef4444';
        return `<tr>
            <td style="padding:6px 12px;">${escapeHtml(r.name)}</td>
            <td style="padding:6px 12px;color:#64748b;">${escapeHtml(r.type)}</td>
            <td style="padding:6px 12px;color:#64748b;">${escapeHtml(r.region ?? '—')}</td>
            <td style="padding:6px 12px;color:${colour};font-weight:bold;text-align:right;">${r.uptimePercent.toFixed(2)}%</td>
            <td style="padding:6px 12px;text-align:right;color:#64748b;">${r.downCount} / ${r.totalCount}</td>
        </tr>`;
    }).join('');

    const html = `
    <div style="font-family:system-ui,sans-serif;color:#0f172a;max-width:680px;margin:0 auto;">
        <h2 style="margin:0 0 4px 0;">Uptime Sentinel — ${escapeHtml(frequency)} report</h2>
        <p style="color:#64748b;margin:0 0 16px 0;font-size:13px;">
            Window: last ${days} days &middot; ${rows.length} monitor${rows.length === 1 ? '' : 's'} &middot;
            ${incidentsInPeriod} incident${incidentsInPeriod === 1 ? '' : 's'} in period.
        </p>
        ${rows.length === 0
            ? '<p style="color:#94a3b8;font-style:italic;">No monitors configured for this account.</p>'
            : `<table style="width:100%;border-collapse:collapse;font-size:13px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;">
                <thead style="background:#f8fafc;text-align:left;color:#64748b;text-transform:uppercase;font-size:11px;font-weight:bold;">
                    <tr>
                        <th style="padding:8px 12px;">Monitor</th>
                        <th style="padding:8px 12px;">Type</th>
                        <th style="padding:8px 12px;">Region</th>
                        <th style="padding:8px 12px;text-align:right;">Uptime</th>
                        <th style="padding:8px 12px;text-align:right;">Down / Total</th>
                    </tr>
                </thead>
                <tbody>${tableRows}</tbody>
            </table>`
        }
        <p style="margin:16px 0 0 0;font-size:11px;color:#94a3b8;">
            You're receiving this because ${escapeHtml(frequency)} reports are enabled in your profile preferences.
            Disable them at <a href="/settings/reports" style="color:#f59e0b;">/settings/reports</a>.
        </p>
    </div>
    `;

    return {
        subject,
        html,
        summary: { monitors: rows.length, incidentsInPeriod, periodDays: days },
    };
}

function escapeHtml(s: string): string {
    return s
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;');
}
