/**
 * Blueprint composition proof — content + fields (spec §8.1 / §11).
 *
 * Proves the engine binds by opaque (entityType, entityId) with ZERO package edge between
 * `@platform-modules/content` and `@platform-modules/fields`. The host wires
 * deleteEntityValues on content-entry delete (no FK — orphan prevention).
 */
import { sql } from 'drizzle-orm'
import { beforeEach, describe, expect, it } from 'vitest'
import { put as putRaw, remove, type Actor, type ContentInput, type StoreOpts } from '@platform-modules/content'
import {
  deleteEntityValues,
  fieldValues,
  getEntityValues,
  resolveGroups,
  setEntityValues,
} from '@platform-modules/fields'
import {
  createContentWithFieldsDb,
  type FieldsDb,
  type SeededContentWithFields,
} from '../src/blueprints/cms/wiring/fields'
import type { ContentDb } from '../src/blueprints/cms/wiring/content'

function sanitize(raw: string): string {
  return raw
    .replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, '')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
}

function put(db: ContentDb, raw: ContentInput, actor: Actor, opts?: StoreOpts) {
  return putRaw(db, raw, actor, sanitize, opts)
}

describe('fields consumer composition (content + fields — swap-survival)', () => {
  let seeded: SeededContentWithFields
  let db: ContentDb
  let fieldsDb: FieldsDb

  beforeEach(async () => {
    seeded = await createContentWithFieldsDb()
    db = seeded.db
    fieldsDb = seeded.fieldsDb
  })

  it('attaches code group values to a content entry and cleans up on delete', async () => {
    const entry = await put(
      db,
      { slug: 'cf-proof', type: 'post', title: 'Proof', body: 'body' },
      seeded.editorActor,
    )
    const ref = { entityType: 'content', entityId: entry.id }
    const resolved = (
      await resolveGroups(fieldsDb, {
        entityType: 'content',
        subType: entry.type,
        codeGroups: [seeded.contentAttrsGroup],
      })
    ).find((g) => g.key === 'content_attrs')!

    await setEntityValues(fieldsDb, seeded.fieldsEditor, {
      ref,
      groupId: 'content_attrs',
      resolved,
      values: { material: 'leather' },
    })

    const got = await getEntityValues(fieldsDb, ref, {
      entityType: 'content',
      subType: entry.type,
      codeGroups: [seeded.contentAttrsGroup],
    })
    expect(got.material).toBe('leather')

    await remove(db, entry.id, seeded.editorActor)
    await deleteEntityValues(fieldsDb, ref)

    const orphanCount = await fieldsDb
      .select({ n: sql<number>`count(*)::int` })
      .from(fieldValues)
      .where(sql`${fieldValues.entityId} = ${entry.id}`)
    expect(orphanCount[0]?.n ?? 0).toBe(0)
  })
})
