import { Op } from 'sequelize';
import { REQUEST_TYPES } from '../config/constants.js';

type DbLike = Record<string, any>;

/** RFC-style UUID v1–v5 shape; same rule used inside {@link resolveEntityUuidByType}. */
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;

/** Use before binding to UUID-typed columns (e.g. `worknotes.request_id`) — human codes like REL-xxx / CC-xxx must not be passed raw. */
export function isEntityUuidString(id: string | undefined | null): boolean {
    return UUID_REGEX.test(String(id || '').trim());
}

/**
 * Distinct UUID strings safe for FK lookups on `worknotes.request_id` after {@link resolveEntityUuidByType}.
 * Drops human-readable business IDs when the resolved row exists (resolvedId is UUID).
 */
export function uuidCandidatesForWorknoteRequestId(
    rawId: string | undefined | null,
    resolvedId: string | undefined | null
): string[] {
    return [...new Set([String(rawId || '').trim(), String(resolvedId || '').trim()].filter(Boolean))].filter(isEntityUuidString);
}

const TYPE_ALIASES: Record<string, string> = {
    application: 'application',
    onboarding: 'application',
    resignation: REQUEST_TYPES.RESIGNATION,
    relocation: REQUEST_TYPES.RELOCATION,
    relocation_request: REQUEST_TYPES.RELOCATION,
    constitutional: REQUEST_TYPES.CONSTITUTIONAL,
    constitutional_change: REQUEST_TYPES.CONSTITUTIONAL,
    'constitutional-change': REQUEST_TYPES.CONSTITUTIONAL,
    termination: REQUEST_TYPES.TERMINATION,
    fnf: REQUEST_TYPES.FNF
};

const LOOKUP_CONFIG: Record<string, { model: string; codeField: string }> = {
    application: { model: 'Application', codeField: 'applicationId' },
    resignation: { model: 'Resignation', codeField: 'resignationId' },
    relocation: { model: 'RelocationRequest', codeField: 'requestId' },
    constitutional: { model: 'ConstitutionalChange', codeField: 'requestId' },
    termination: { model: 'TerminationRequest', codeField: 'requestId' },
    fnf: { model: 'FnF', codeField: 'settlementId' }
};

export function normalizeRequestType(rawType: string | undefined | null): string {
    const type = String(rawType || 'application').trim().toLowerCase();
    return TYPE_ALIASES[type] || type;
}

export function requestTypeQueryVariants(normalizedType: string): string[] {
    if (normalizedType === REQUEST_TYPES.CONSTITUTIONAL) {
        return [REQUEST_TYPES.CONSTITUTIONAL, 'constitutional-change'];
    }
    return [normalizedType];
}

export async function resolveEntityUuidByType(
    db: DbLike,
    rawId: string | undefined | null,
    rawType: string | undefined | null
): Promise<{ resolvedId: string; normalizedType: string }> {
    const id = String(rawId || '').trim();
    const normalizedType = normalizeRequestType(rawType);
    if (!id) return { resolvedId: id, normalizedType };

    const cfg = LOOKUP_CONFIG[normalizedType];
    if (!cfg || !db?.[cfg.model]) return { resolvedId: id, normalizedType };

    const isUuid = isEntityUuidString(id);
    const where = isUuid
        ? { [Op.or]: [{ id }, { [cfg.codeField]: id }] }
        : { [cfg.codeField]: id };

    const row = await db[cfg.model].findOne({
        where,
        attributes: ['id']
    });

    return {
        resolvedId: row?.id || id,
        normalizedType
    };
}
