import { characterSchema, type Character } from '@/lib/schemas';
import { newId } from '@/lib/ids';
import { downloadJson, safeFilename } from './file';

const FORMAT = 'ttrpg-manager:character';
const VERSION = 1;

interface CharacterFile {
  format: typeof FORMAT;
  version: number;
  character: Character;
}

/** Download a character as a portable JSON file. */
export function exportCharacter(c: Character): void {
  const payload: CharacterFile = { format: FORMAT, version: VERSION, character: c };
  downloadJson(`${safeFilename(c.name)}.character.json`, payload);
}

export class CharacterImportError extends Error {}

/**
 * Parse imported JSON into a valid Character bound to the given campaign. Accepts
 * both our wrapped export format and a bare character object. Always assigns a
 * fresh id + timestamps so importing never collides with or overwrites existing
 * data.
 */
export function parseCharacterImport(text: string, campaignId: string): Character {
  let raw: unknown;
  try {
    raw = JSON.parse(text);
  } catch {
    throw new CharacterImportError('That file is not valid JSON.');
  }

  const candidate =
    raw && typeof raw === 'object' && 'character' in raw
      ? (raw as { character: unknown }).character
      : raw;

  if (!candidate || typeof candidate !== 'object') {
    throw new CharacterImportError('No character data found in that file.');
  }

  const now = new Date().toISOString();
  const result = characterSchema.safeParse({
    ...(candidate as Record<string, unknown>),
    id: newId(),
    campaignId,
    createdAt: now,
    updatedAt: now,
  });
  if (!result.success) {
    throw new CharacterImportError(
      `That file isn't a valid character: ${result.error.issues[0]?.message ?? 'unknown error'}`,
    );
  }
  return result.data;
}
