const MALAY_LANG = 'ms-MY';

const MALAY_DIGITS = [
    'kosong',
    'satu',
    'dua',
    'tiga',
    'empat',
    'lima',
    'enam',
    'tujuh',
    'lapan',
    'sembilan',
];

let speechUnlocked = false;
let speechQueue = [];
let speaking = false;

function speechSynthesisAvailable() {
    return typeof window !== 'undefined' && 'speechSynthesis' in window;
}

function loadVoices() {
    if (!speechSynthesisAvailable()) return [];
    return window.speechSynthesis.getVoices();
}

function pickMalayVoice() {
    const voices = loadVoices();
    return (
        voices.find((voice) => voice.lang === MALAY_LANG) ||
        voices.find((voice) => voice.lang.startsWith('ms')) ||
        null
    );
}

/**
 * Spell ticket numbers digit-by-digit in Malay for clearer announcements.
 */
export function formatTicketNumberForSpeech(ticketNumber) {
    return String(ticketNumber)
        .trim()
        .split('')
        .map((character) => {
            if (/\d/.test(character)) {
                return MALAY_DIGITS[Number(character)];
            }
            return character;
        })
        .join(' ');
}

export function formatMalayAnnouncement(ticketNumber, stationName) {
    const spokenNumber = formatTicketNumberForSpeech(ticketNumber);
    return `Nombor giliran ${spokenNumber}, sila ke ${stationName}.`;
}

/**
 * Call once after a user gesture so later speech is allowed on strict browsers.
 */
export function unlockQueueSpeech() {
    if (speechUnlocked || !speechSynthesisAvailable()) return;

    try {
        loadVoices();
        const utterance = new SpeechSynthesisUtterance('');
        utterance.volume = 0;
        utterance.lang = MALAY_LANG;
        window.speechSynthesis.speak(utterance);
    } catch {
        // Ignore unlock failures; real announcements will still be attempted.
    } finally {
        speechUnlocked = true;
    }
}

function processSpeechQueue() {
    if (speaking || speechQueue.length === 0 || !speechSynthesisAvailable()) return;

    speaking = true;
    const text = speechQueue.shift();
    const utterance = new SpeechSynthesisUtterance(text);
    utterance.lang = MALAY_LANG;

    const voice = pickMalayVoice();
    if (voice) {
        utterance.voice = voice;
    }

    utterance.rate = 0.75;

    const finish = () => {
        speaking = false;
        processSpeechQueue();
    };

    utterance.onend = finish;
    utterance.onerror = () => {
        console.warn('Could not speak queue announcement:', text);
        finish();
    };

    window.speechSynthesis.speak(utterance);
}

/**
 * Queue Malay voice announcements for one or more station calls.
 * @param {{ ticketNumber: string, stationName: string }[]} calls
 */
export function announceQueueCalls(calls) {
    if (!calls?.length || !speechSynthesisAvailable()) return;

    unlockQueueSpeech();

    for (const call of calls) {
        speechQueue.push(
            formatMalayAnnouncement(call.ticketNumber, call.stationName)
        );
    }

    processSpeechQueue();
}

export function cancelQueueSpeech() {
    if (!speechSynthesisAvailable()) return;
    window.speechSynthesis.cancel();
    speechQueue = [];
    speaking = false;
}
