import Dexie, { type EntityTable } from 'dexie';
import type { Campaign } from '@/lib/schemas/campaign';
import type { Character } from '@/lib/schemas/character';
import type { Encounter } from '@/lib/schemas/encounter';
import type { DiceRoll } from '@/lib/schemas/dice';
import { characterDefaults } from '@/lib/schemas/character';

/**
 * Single Dexie instance for the whole app. Dexie wraps IndexedDB transactions
 * correctly (commits before resolving), which removes the silent-data-loss
 * class of bugs the old hand-rolled adapter shipped with.
 *
 * Schema versions are additive: bump `version(n)` and add a `.upgrade()` when
 * the shape changes — never edit a past version in place.
 */
export class TtrpgDatabase extends Dexie {
  campaigns!: EntityTable<Campaign, 'id'>;
  characters!: EntityTable<Character, 'id'>;
  encounters!: EntityTable<Encounter, 'id'>;
  diceRolls!: EntityTable<DiceRoll, 'id'>;

  constructor() {
    super('ttrpg-manager');
    this.version(1).stores({
      campaigns: 'id, updatedAt',
      characters: 'id, campaignId, kind',
      encounters: 'id, campaignId, status',
      diceRolls: 'id, campaignId, createdAt',
    });

    // v2 — Phase 1 character depth: backfill new fields on existing characters.
    this.version(2).stores({}).upgrade(async (tx) => {
      await tx
        .table('characters')
        .toCollection()
        .modify((c: Record<string, unknown>) => {
          for (const [key, value] of Object.entries(characterDefaults())) {
            if (c[key] === undefined) c[key] = value;
          }
        });
    });
  }
}

export const db = new TtrpgDatabase();
