import type { ScreenplayElement } from '../screenplay/types';
import type { ScreenplayExporter, ExportOptions, ExportResult } from './types';
import { CONTENT_TYPES, EXTENSIONS } from './types';

function escapeXml(s: string): string {
  return s
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&apos;');
}

function elementToXmlTag(type: string): string {
  const map: Record<string, string> = {
    sceneHeading: 'SceneHeading',
    action: 'Action',
    character: 'Character',
    dialogue: 'Dialogue',
    parenthetical: 'Parenthetical',
    transition: 'Transition',
    note: 'Note',
    retained: 'Retained',
    centered: 'Centered',
  };
  return map[type] || 'Action';
}

export class FdxExporter implements ScreenplayExporter {
  public readonly supportedFormats: readonly ['fdx'] = ['fdx'];

  public export(elements: ScreenplayElement[], options: ExportOptions): ExportResult {
    const title = options.title ?? 'Untitled';
    const author = options.author ?? '';
    const datetime = options.datetime ?? new Date().toISOString().split('T')[0] ?? '';

    let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
    xml += '<FDX version="8.0">\n';

    xml += '  <TitlePage>\n';
    xml += '    <Title>' + escapeXml(title) + '</Title>\n';
    xml += '    <Author>' + escapeXml(author) + '</Author>\n';
    xml += '    <Date>' + escapeXml(datetime) + '</Date>\n';
    if (options.contact) {
      xml += '    <Contact>' + escapeXml(options.contact) + '</Contact>\n';
    }
    xml += '  </TitlePage>\n';

    xml += '  <FontFace id="0" name="Courier" size="12" />\n';
    xml += '  <PageSetup width="8.5" height="11" topMargin="1.0" bottomMargin="1.0" leftMargin="1.0" rightMargin="1.0" />\n';

    xml += '  <Content>\n';

    for (const el of elements) {
      const tag = elementToXmlTag(el.type);
      const content = escapeXml(el.content.trim());

      switch (el.type) {
        case 'sceneHeading':
          xml += '    <SceneHeading fontFaceId="0">' + content.toUpperCase() + '</SceneHeading>\n';
          break;
        case 'action':
          xml += '    <Action fontFaceId="0">' + content + '</Action>\n';
          break;
        case 'character':
          xml += '    <Character fontFaceId="0">' + content.toUpperCase() + '</Character>\n';
          break;
        case 'dialogue':
          xml += '    <Dialogue fontFaceId="0">' + content + '</Dialogue>\n';
          break;
        case 'parenthetical':
          xml += '    <Parenthetical fontFaceId="0">' + content + '</Parenthetical>\n';
          break;
        case 'transition':
          xml += '    <Transition fontFaceId="0">' + content.toUpperCase() + '</Transition>\n';
          break;
        case 'note':
          xml += '    <Note fontFaceId="0">' + content + '</Note>\n';
          break;
        case 'retained':
          xml += '    <Retained fontFaceId="0">' + content + '</Retained>\n';
          break;
        case 'centered':
          xml += '    <Centered fontFaceId="0">' + content + '</Centered>\n';
          break;
        default:
          xml += '    <Action fontFaceId="0">' + content + '</Action>\n';
      }
    }

    xml += '  </Content>\n';
    xml += '</FDX>\n';

    const filename = (title || 'screenplay').replace(/[^a-zA-Z0-9]/g, '_');

    return {
      format: 'fdx',
      contentType: CONTENT_TYPES.fdx,
      extension: EXTENSIONS.fdx,
      data: xml,
      filename: filename + EXTENSIONS.fdx,
    };
  }
}
