import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import { sql } from 'drizzle-orm'
import { makePgHarness } from './pg-harness.js'
import { fieldsMigrationSql } from './migrate.js'
import { defineFieldGroup, resolveGroups, typedValues } from './registry.js'
import { isFieldGroupConflictError, isFieldValidationError } from './errors.js'

const code = defineFieldGroup({
  key: 'product_attrs', label: 'Attributes', location: { entityType: 'product' },
  fields: [{ type: 'text', key: 'material', label: 'Material' }],
})
const h = await makePgHarness()
beforeAll(async () => {
  for (const s of fieldsMigrationSql()
    .split(';')
    .map((x) => x.trim())
    .filter(Boolean)) {
    await h.db.execute(sql.raw(s))
  }
})
afterAll(async () => { await h.teardown() })

describe('defineFieldGroup', () => {
  it('rejects a bad field key', () => {
    try { defineFieldGroup({ key: 'g', label: 'G', location: { entityType: 'p' }, fields: [{ type: 'text', key: '2bad', label: 'X' }] }); throw new Error('no throw') }
    catch (e) { expect(isFieldValidationError(e)).toBe(true) }
  })
})
describe('resolveGroups', () => {
  it('merges code + db groups ordered by position', async () => {
    await h.db.execute(sql`insert into field_groups (entity_type, key, label, fields, position) values ('product','care','Care', ${JSON.stringify([{ type: 'textarea', key: 'care_text', label: 'Care' }])}::jsonb, 5)`)
    const r = await resolveGroups(h.db, { entityType: 'product', codeGroups: [code] })
    expect(r.map((g) => g.key)).toContain('product_attrs')
    expect(r.map((g) => g.key)).toContain('care')
    expect(r.find((g) => g.key === 'product_attrs')!.origin).toBe('code')
    expect(r.find((g) => g.key === 'care')!.origin).toBe('db')
  })
  it('throws on a cross-group duplicate field key', async () => {
    await h.db.execute(sql`insert into field_groups (entity_type, key, label, fields) values ('dup','g2','G2', ${JSON.stringify([{ type: 'text', key: 'material', label: 'M' }])}::jsonb)`)
    const dupCode = defineFieldGroup({ key: 'g1', label: 'G1', location: { entityType: 'dup' }, fields: [{ type: 'text', key: 'material', label: 'M' }] })
    await expect(resolveGroups(h.db, { entityType: 'dup', codeGroups: [dupCode] })).rejects.toSatisfy(isFieldGroupConflictError)
  })
})
describe('typedValues', () => {
  it('returns the map narrowed to the group keys', () => {
    expect(typedValues(code, { material: 'leather' })).toEqual({ material: 'leather' })
  })
})
