import db from '../database/models/index.js';
import type { SlaNotificationDispatchType } from '../database/models/compliance/SLANotificationDispatch.js';

const { SLANotificationDispatch } = db;

export type ClaimSlaDispatchParams = {
    trackingId: string;
    thresholdKey: string;
    dispatchType: SlaNotificationDispatchType;
    templateCode?: string;
    stageName?: string;
    reminderId?: string | null;
    escalationLevel?: number | null;
    recipientCount?: number;
};

/** Build stable threshold keys used for idempotency */
export const SlaDispatchKeys = {
    preBreachReminder(reminder: { id?: string; timeValue: number; timeUnit: string }) {
        if (reminder.id) return `reminder:${reminder.id}`;
        return `reminder:${reminder.timeValue}_${reminder.timeUnit}`;
    },
    breach: () => 'breach',
    escalation(level: number) {
        return `escalation:L${level}`;
    },
    repeatOverdueBucket(nowMs: number, repeatWindowMs: number) {
        return `repeat_overdue:${Math.floor(nowMs / repeatWindowMs)}`;
    }
};

/**
 * Returns true if this threshold was already dispatched (DB or legacy metadata flag).
 */
export async function wasSlaNotificationDispatched(
    trackingId: string,
    thresholdKey: string,
    legacyMetadata?: Record<string, unknown> | null,
    legacyMetadataKey?: string
): Promise<boolean> {
    const existing = await SLANotificationDispatch.findOne({
        where: { trackingId, thresholdKey },
        attributes: ['id']
    });
    if (existing) return true;

    if (legacyMetadataKey && legacyMetadata?.[legacyMetadataKey]) {
        return true;
    }
    return false;
}

/**
 * Atomically claim a dispatch slot (unique per tracking + threshold).
 * Returns true if this caller should send notifications; false if already sent.
 */
export async function claimSlaNotificationDispatch(
    params: ClaimSlaDispatchParams
): Promise<boolean> {
    try {
        const [, created] = await SLANotificationDispatch.findOrCreate({
            where: {
                trackingId: params.trackingId,
                thresholdKey: params.thresholdKey
            },
            defaults: {
                trackingId: params.trackingId,
                thresholdKey: params.thresholdKey,
                dispatchType: params.dispatchType,
                templateCode: params.templateCode ?? null,
                stageName: params.stageName ?? null,
                reminderId: params.reminderId ?? null,
                escalationLevel: params.escalationLevel ?? null,
                recipientCount: params.recipientCount ?? 0,
                sentAt: new Date(),
                status: 'sent'
            }
        });
        return created;
    } catch (error: unknown) {
        const err = error as { name?: string; message?: string };
        console.error(
            `[SLA Dispatch] claim failed (${params.thresholdKey}): ${err.message || err.name}`
        );
        return false;
    }
}

export async function updateSlaDispatchRecipientCount(
    trackingId: string,
    thresholdKey: string,
    recipientCount: number
): Promise<void> {
    await SLANotificationDispatch.update(
        { recipientCount },
        { where: { trackingId, thresholdKey } }
    );
}

export async function listDispatchesForTracking(trackingId: string) {
    return SLANotificationDispatch.findAll({
        where: { trackingId },
        order: [['sentAt', 'ASC']]
    });
}
