import { unsafeHTML } from 'lit/directives/unsafe-html.js';

export function ansiToLitHtml(text: string) {
  const textColors: Record<string, string> = {
    '30': 'black',
    '31': 'red',
    '32': 'green',
    '33': 'yellow',
    '34': 'blue',
    '35': 'magenta',
    '36': 'cyan',
    '37': 'white',
    '90': 'gray',
    '91': 'lightred',
    '92': 'lightgreen',
    '93': 'lightyellow',
    '94': 'lightblue',
    '95': 'lightmagenta',
    '96': 'lightcyan',
    '97': 'white',
  };

  const bgColors: Record<string, string> = {
    '40': 'black',
    '41': 'red',
    '42': 'green',
    '43': 'yellow',
    '44': 'blue',
    '45': 'magenta',
    '46': 'cyan',
    '47': 'white',
    '100': 'gray',
    '101': 'lightred',
    '102': 'lightgreen',
    '103': 'lightyellow',
    '104': 'lightblue',
    '105': 'lightmagenta',
    '106': 'lightcyan',
    '107': 'white',
  };

  const styles: Record<string, string> = {
    '1': 'font-weight: bold;',
    '3': 'font-style: italic;',
    '4': 'text-decoration: underline;',
  };

  const ESC = '\u001b';
  const ansiPattern = new RegExp(`${ESC}\\[(\\d+(?:;\\d+)*)m`, 'g');
  const openTags: string[] = [];

  let result = text.replace(ansiPattern, (_, codes) => {
    const codeArray = codes.split(';');

    if (codeArray.includes('0')) {
      const closeTags = openTags.length > 0 ? '</span>'.repeat(openTags.length) : '';
      openTags.length = 0;
      return closeTags;
    }

    let style = '';

    for (const code of codeArray) {
      if (textColors[code]) {
        style += `color: ${textColors[code]};`;
      } else if (bgColors[code]) {
        style += `background-color: ${bgColors[code]};`;
      } else if (styles[code]) {
        style += styles[code];
      }
    }

    if (style) {
      openTags.push('span');
      return `<span style="${style}">`;
    }

    return '';
  });

  if (openTags.length > 0) result += '</span>'.repeat(openTags.length);

  return unsafeHTML(`${result}\n`);
}
