import type { ScreenplayElement, TemplateType } from '../screenplay/types';
import type {
  ExportFormat,
  ExportOptions,
  ExportResult,
  ScreenplayExporter,
  BatchExportOptions,
  BatchExportResult,
  BatchExportError,
} from './types';
import { FountainExporter } from './fountain';
import { FdxExporter } from './fdx';
import { PdfExporter } from './pdf';
import { ScreenplayProExporter } from './screenplay-pro';
import { getTemplate } from '../screenplay/format';

export class ExportManager {
  private exporters: Map<ExportFormat, ScreenplayExporter>;

  constructor() {
    this.exporters = new Map();
    this.register(new FountainExporter());
    this.register(new FdxExporter());
    this.register(new PdfExporter());
    this.register(new ScreenplayProExporter());
  }

  public register(exp: ScreenplayExporter): void {
    for (const format of exp.supportedFormats) {
      this.exporters.set(format, exp);
    }
  }

  public getAvailableFormats(): ExportFormat[] {
    return Array.from(this.exporters.keys());
  }

  public export(elements: ScreenplayElement[], options: ExportOptions): ExportResult {
    const exporter = this.exporters.get(options.format);
    if (!exporter) {
      throw new Error(`Unsupported export format: ${options.format}`);
    }
    return exporter.export(elements, options);
  }

  public batchExport(
    elements: ScreenplayElement[],
    formats: ExportFormat[],
    baseOptions: BatchExportOptions = {}
  ): BatchExportResult {
    const results: ExportResult[] = [];
    const errors: BatchExportError[] = [];

    for (const format of formats) {
      try {
        const options: ExportOptions = {
          format,
          title: baseOptions.title,
          author: baseOptions.author,
          contact: baseOptions.contact,
          template: baseOptions.template,
          includeCoverPage: baseOptions.includeCoverPage,
          gutterMargin: baseOptions.gutterMargin,
        };
        const result = this.export(elements, options);
        results.push(result);
      } catch (err) {
        errors.push({
          format,
          error: err instanceof Error ? err.message : String(err),
        });
      }
    }

    return { formats, results, errors };
  }

  public exportToRawText(elements: ScreenplayElement[], template: TemplateType = 'standard'): string {
    const tpl = getTemplate(template);
    const lines: string[] = [];

    for (const el of elements) {
      const style = tpl.elementStyles[el.type];
      const contentLines = el.content.trim().split('\n');

      for (const line of contentLines) {
        let formatted = line.trim();
        if (style.uppercase) formatted = formatted.toUpperCase();
        const indent = '  '.repeat(Math.round(style.indentStart * 2));
        lines.push(indent + formatted);
      }

      if (style.marginBottom > 0) {
        lines.push('');
      }
    }

    return lines.join('\n').trim();
  }
}
