import { ScreenplayElementType, DetectionResult } from './types';

const SCENE_HEADING_RE = /^(INT|EXT|INT\/EXT|I\/E)\.\s*/i;
const TRANSITION_RE = /^(CUT TO|FADE IN|FADE OUT|SMASH CUT|MATCH CUT|DISSOLVE TO|IRIS IN|IRIS OUT|BACK TO|TIME CUT|JUMP CUT)\s*[:.!?]?\s*$/i;
const PARENTHETICAL_RE = /^\(.*\)$/;
const CHARACTER_RE = /^\s{4,}([A-Z][A-Z0-9.'-]+(?:\s+[A-Z][A-Z0-9.'-]+)*)\s*$/;
const EMPTY_LINE_RE = /^\s*$/;

export function detectElementType(line: string): ScreenplayElementType {
  const trimmed = line.trim();

  if (EMPTY_LINE_RE.test(trimmed)) {
    return 'action';
  }

  if (SCENE_HEADING_RE.test(trimmed)) {
    return 'sceneHeading';
  }

  if (TRANSITION_RE.test(trimmed)) {
    return 'transition';
  }

  if (PARENTHETICAL_RE.test(trimmed)) {
    return 'parenthetical';
  }

  if (CHARACTER_RE.test(line)) {
    return 'character';
  }

  if (trimmed === trimmed.toUpperCase() && trimmed.length < 60 && !trimmed.includes(' ')) {
    return 'character';
  }

  return 'dialogue';
}

export function detectWithType(line: string): DetectionResult {
  const type = detectElementType(line);
  let confidence = 0.5;

  if (SCENE_HEADING_RE.test(line.trim())) {
    confidence = 0.95;
  } else if (TRANSITION_RE.test(line.trim())) {
    confidence = 0.95;
  } else if (PARENTHETICAL_RE.test(line.trim())) {
    confidence = 0.85;
  } else if (CHARACTER_RE.test(line)) {
    confidence = 0.9;
  } else if (line.trim() === line.trim().toUpperCase() && line.trim().length < 60) {
    confidence = 0.6;
  }

  return { type, confidence, text: line };
}

export function isSceneHeading(line: string): boolean {
  return detectElementType(line) === 'sceneHeading';
}

export function isTransition(line: string): boolean {
  return detectElementType(line) === 'transition';
}

export function isCharacter(line: string): boolean {
  return detectElementType(line) === 'character';
}

export function isParenthetical(line: string): boolean {
  return detectElementType(line) === 'parenthetical';
}

export function detectNamedEntities(line: string): string[] {
  const trimmed = line.trim();
  const names: string[] = [];

  if (CHARACTER_RE.test(line)) {
    const match = line.match(/([A-Z][A-Z0-9.'-]+(?:\s+[A-Z][A-Z0-9.'-]+)*)/);
    if (match && match[1]) {
      names.push(match[1]);
    }
  }

  const sceneMatch = trimmed.match(/^(?:INT|EXT|INT\/EXT|I\/E)\.\s+(.*)/i);
  if (sceneMatch && sceneMatch[1]) {
    names.push(sceneMatch[1].trim());
  }

  return names;
}
