import { MessageSegment, AtSegmentData } from '../../../types';

export interface TextBlock {
  id: string;
  type: 'text';
  text: string;
  activeMentions: Map<number, { endIndex: number; userId: string; nickname: string }>;
}

export interface ImageBlock {
  id: string;
  type: 'image';
  localUri: string;
  remoteUrl?: string;
  uploading: boolean;
  width?: number;
  height?: number;
}

export type EditorBlock = TextBlock | ImageBlock;

export function generateBlockId(): string {
  return `blk_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
}

export function createInitialTextBlock(): TextBlock {
  return { id: generateBlockId(), type: 'text', text: '', activeMentions: new Map() };
}

export function remapMentionsBefore(
  mentions: Map<number, { endIndex: number; userId: string; nickname: string }>,
  cursorPos: number,
): Map<number, { endIndex: number; userId: string; nickname: string }> {
  const result = new Map<number, { endIndex: number; userId: string; nickname: string }>();
  for (const [start, mention] of mentions) {
    if (mention.endIndex <= cursorPos) {
      result.set(start, { ...mention });
    }
  }
  return result;
}

export function remapMentionsAfter(
  mentions: Map<number, { endIndex: number; userId: string; nickname: string }>,
  cursorPos: number,
  textLength: number,
): Map<number, { endIndex: number; userId: string; nickname: string }> {
  const result = new Map<number, { endIndex: number; userId: string; nickname: string }>();
  for (const [start, mention] of mentions) {
    if (start >= cursorPos) {
      result.set(start - cursorPos, {
        ...mention,
        endIndex: mention.endIndex - cursorPos,
      });
    }
  }
  return result;
}

export function mergeMentions(
  m1: Map<number, { endIndex: number; userId: string; nickname: string }>,
  m1TextLength: number,
  m2: Map<number, { endIndex: number; userId: string; nickname: string }>,
): Map<number, { endIndex: number; userId: string; nickname: string }> {
  const result = new Map(m1);
  for (const [start, mention] of m2) {
    result.set(start + m1TextLength, {
      ...mention,
      endIndex: mention.endIndex + m1TextLength,
    });
  }
  return result;
}

export function blockTextToSegments(
  text: string,
  activeMentions: Map<number, { endIndex: number; userId: string; nickname: string }>,
): MessageSegment[] {
  if (activeMentions.size === 0) {
    return text.trim() ? [{ type: 'text', data: { text } }] : [];
  }

  const segments: MessageSegment[] = [];
  const sorted = Array.from(activeMentions.entries()).sort((a, b) => a[0] - b[0]);
  let lastEnd = 0;

  for (const [startIdx, mention] of sorted) {
    if (startIdx > lastEnd) {
      segments.push({ type: 'text', data: { text: text.slice(lastEnd, startIdx) } });
    }
    segments.push({
      type: 'at',
      data: { user_id: mention.userId, nickname: mention.nickname } as AtSegmentData,
    });
    lastEnd = mention.endIndex;
  }

  if (lastEnd < text.length) {
    segments.push({ type: 'text', data: { text: text.slice(lastEnd) } });
  }

  return segments;
}
