import type { AdventureLogBattleGroup, AdventureLogEntry, AdventureLogPlainEntry } from './types';
import type { LogEntry } from '../network/api';
import { parseAdventureLogLine } from './adventureLogMarkers';

/** Group server log rows (oldest first) into plain lines + battle groups. */
export function groupAdventureLogFromServer(
  sortedOldestFirst: Array<{ id: number; message: string; timestamp: number }>,
): AdventureLogEntry[] {
  const out: AdventureLogEntry[] = [];
  let i = 0;
  while (i < sortedOldestFirst.length) {
    const row = sortedOldestFirst[i]!;
    const parsed = parseAdventureLogLine(row.message);
    if (parsed.type === 'encounter') {
      const lines: { id: number; message: string }[] = [];
      i++;
      while (i < sortedOldestFirst.length) {
        const inner = sortedOldestFirst[i]!;
        const innerParsed = parseAdventureLogLine(inner.message);
        if (innerParsed.type === 'battle') {
          lines.push({ id: inner.id, message: innerParsed.text });
          i++;
        } else {
          break;
        }
      }
      const group: AdventureLogBattleGroup = {
        kind: 'battle_group',
        id: row.id,
        title: parsed.title,
        timestamp: row.timestamp,
        lines,
      };
      out.push(group);
    } else {
      const text =
        parsed.type === 'plain' ? parsed.text : parsed.type === 'battle' ? parsed.text : row.message;
      const plain: AdventureLogPlainEntry = {
        kind: 'line',
        id: row.id,
        message: text,
        timestamp: row.timestamp,
      };
      out.push(plain);
      i++;
    }
  }
  return out;
}

export function appendAdventureLogMessage(
  prev: AdventureLogEntry[],
  rawMessage: string,
  nextId: () => number,
): AdventureLogEntry[] {
  const parsed = parseAdventureLogLine(rawMessage);
  if (parsed.type === 'encounter') {
    const group: AdventureLogBattleGroup = {
      kind: 'battle_group',
      id: nextId(),
      title: parsed.title,
      timestamp: Date.now(),
      lines: [],
    };
    return [...prev, group];
  }
  if (parsed.type === 'battle') {
    const last = prev[prev.length - 1];
    if (last?.kind === 'battle_group') {
      const lineId = nextId();
      return [
        ...prev.slice(0, -1),
        {
          ...last,
          lines: [...last.lines, { id: lineId, message: parsed.text }],
        },
      ];
    }
    const line: AdventureLogPlainEntry = {
      kind: 'line',
      id: nextId(),
      message: parsed.text,
      timestamp: Date.now(),
    };
    return [...prev, line];
  }
  const line: AdventureLogPlainEntry = {
    kind: 'line',
    id: nextId(),
    message: parsed.text,
    timestamp: Date.now(),
  };
  return [...prev, line];
}

/** Map GET /hero/log lines to UI entries (oldest first, stable ids from DB). */
export function adventureEntriesFromServerLog(serverLog: LogEntry[]): {
  entries: AdventureLogEntry[];
  maxId: number;
} {
  const sorted = [...serverLog].sort(
    (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(),
  );
  const flat = sorted.map((entry) => ({
    id: Number(entry.id),
    message: entry.message,
    timestamp: new Date(entry.createdAt).getTime(),
  }));
  const entries = groupAdventureLogFromServer(flat);
  const maxId = flat.reduce((m, e) => Math.max(m, e.id), 0);
  return { entries, maxId };
}
