import { Transform } from 'node:stream';

function parseSseChunk(chunk) {
  const events = [];
  const blocks = chunk.split('\n\n');
  for (const block of blocks) {
    if (!block.trim()) continue;
    let data;
    for (const line of block.split('\n')) {
      if (line.startsWith('data:')) {
        data = line.slice(5).trim();
      }
    }
    if (!data) continue;
    try {
      events.push(JSON.parse(data));
    } catch {
      // ignore malformed frames
    }
  }
  return events;
}

export function createSseBillingTransform({ onFinish }) {
  let buffer = '';

  return new Transform({
    transform(chunk, _encoding, callback) {
      buffer += chunk.toString('utf8');
      const parts = buffer.split('\n\n');
      buffer = parts.pop() ?? '';

      for (const block of parts) {
        if (!block.trim()) continue;
        let dataLine;
        for (const line of block.split('\n')) {
          if (line.startsWith('data:')) dataLine = line.slice(5).trim();
        }
        if (!dataLine) continue;
        try {
          const event = JSON.parse(dataLine);
          if (event?.type === 'Finish' && event.token_state) {
            void onFinish(event).catch(() => {});
          }
        } catch {
          // ignore
        }
      }

      callback(null, chunk);
    },
    flush(callback) {
      if (buffer.trim()) {
        for (const event of parseSseChunk(`${buffer}\n\n`)) {
          if (event?.type === 'Finish' && event.token_state) {
            void onFinish(event).catch(() => {});
          }
        }
      }
      callback();
    },
  });
}

export function appendBalanceEvent(payload) {
  const data =
    typeof payload === 'number'
      ? { balanceCents: payload }
      : payload && typeof payload === 'object'
        ? payload
        : { balanceCents: 0 };
  return `event: balance\ndata: ${JSON.stringify(data)}\n\n`;
}
