import { describe, it, expect, beforeEach } from 'vitest';
import type Database from 'better-sqlite3';
import { createDb } from '../src/lib/db';
import { contentSeed } from '../src/data/content-seed';
import { makeContentStore, syncSeed, resolveContent } from '../src/lib/content';

let db: Database.Database;
beforeEach(() => { db = createDb(':memory:'); });

describe('seed', () => {
  it('tag univoci, validi e valori non vuoti', () => {
    const tags = contentSeed.map((e) => e.tag);
    expect(new Set(tags).size).toBe(tags.length);
    for (const e of contentSeed) {
      expect(e.tag).toMatch(/^[a-z0-9-]+(\.[a-z0-9-]+)+$/);
      if (e.type !== 'image') expect(e.value.length).toBeGreaterThan(0);
    }
  });

  it('createDb sincronizza il seed senza sovrascrivere modifiche', () => {
    const n = (db.prepare('SELECT COUNT(*) AS n FROM content_blocks').get() as { n: number }).n;
    expect(n).toBe(contentSeed.length);
    db.prepare(`UPDATE content_blocks SET value = 'MODIFICATO' WHERE tag = ?`).run(contentSeed[0].tag);
    // ri-sync (come a un nuovo avvio) non deve toccare la modifica
    syncSeed(db);
    const v = db.prepare('SELECT value FROM content_blocks WHERE tag = ?').get(contentSeed[0].tag) as { value: string };
    expect(v.value).toBe('MODIFICATO');
  });
});

describe('content store', () => {
  it('legge dal DB con classi preset e cache invalidabile', () => {
    const store = makeContentStore(() => db);
    const tag = contentSeed[0].tag;
    db.prepare(`UPDATE content_blocks SET value = 'Nuovo', styles = '{"size":"l"}' WHERE tag = ?`).run(tag);
    store.invalidate();
    const r = store.resolve(tag);
    expect(r.value).toBe('Nuovo');
    expect(r.classes).toBe('cs-size-l');
    // senza invalidate la cache resta
    db.prepare(`UPDATE content_blocks SET value = 'Altro' WHERE tag = ?`).run(tag);
    expect(store.resolve(tag).value).toBe('Nuovo');
    store.invalidate();
    expect(store.resolve(tag).value).toBe('Altro');
  });

  it('fallback: tag assente nel DB usa il seed, sconosciuto stringa vuota', () => {
    const store = makeContentStore(() => db);
    db.prepare('DELETE FROM content_blocks WHERE tag = ?').run(contentSeed[0].tag);
    store.invalidate();
    expect(store.resolve(contentSeed[0].tag).value).toBe(contentSeed[0].value);
    expect(store.resolve('tag.inesistente').value).toBe('');
  });

  it('styles corrotto nel DB viene ignorato', () => {
    const store = makeContentStore(() => db);
    db.prepare(`UPDATE content_blocks SET styles = 'non-json' WHERE tag = ?`).run(contentSeed[0].tag);
    store.invalidate();
    expect(store.resolve(contentSeed[0].tag).classes).toBe('');
  });

  it('resolveContent restituisce il guid dal DB', () => {
    const r = resolveContent('home.hero.cta');
    expect(typeof r.guid).toBe('string');
    expect(r.guid.length).toBeGreaterThan(10);
  });
});
