import { sql } from 'drizzle-orm'
import { startPg } from './pg-harness.js'
import { contentModelForwardMigrationSql } from './migrations/content-model.js'
import { contentRevisionsMigrationSql } from './revisions.js'
import { contentTaxonomyMigrationSql } from './taxonomy.js'
import { contentSchema } from './schema.js'
import { createContentStatus, type ContentStatusDefinition } from './status.js'
import { createContentType, type ContentTypeCapabilities, type ContentTypeDefinition, type ContentTypeLabels } from './registry.js'
import type { ContentDefinitionEffects, ContentDefinitionAuthorization } from './definition-lifecycle.js'
import type { ContentPrincipal } from './authz.js'
import type { ContentOutbox, ContentWriteDependencies } from './lifecycle.js'

const LEGACY_PG_DDL = `CREATE TABLE content_entries (
  id uuid PRIMARY KEY, slug text NOT NULL, type text NOT NULL, title text NOT NULL,
  body text NOT NULL, status text NOT NULL, visibility text NOT NULL,
  published_at timestamptz(3), author text NOT NULL,
  created_at timestamptz(3) NOT NULL, updated_at timestamptz(3) NOT NULL
)`

export function capabilities(): ContentTypeCapabilities {
  return {
    manageType:'manage_type',migrateAll:'migrate_all',manageTerms:'manage_terms',create:'create',read:'read',
    readPrivate:'read_private',readProtected:'read_protected',editOwn:'edit_own',editOthers:'edit_others',
    editPrivate:'edit_private',editPublished:'edit_published',publish:'publish',deleteOwn:'delete_own',
    deleteOthers:'delete_others',deletePrivate:'delete_private',deletePublished:'delete_published',
  }
}
function labels(): ContentTypeLabels {
  return {
    name:'Books',singularName:'Book',menuName:'Books',nameAdminBar:'Book',addNew:'Add New',addNewItem:'Add New Book',
    editItem:'Edit Book',newItem:'New Book',viewItem:'View Book',viewItems:'View Books',searchItems:'Search Books',notFound:'Not found',
    notFoundInTrash:'Not found in trash',parentItemColon:'Parent Book:',allItems:'All Books',archives:'Book Archives',attributes:'Book Attributes',
    insertIntoItem:'Insert into item',uploadedToThisItem:'Uploaded to item',featuredImage:'Featured image',setFeaturedImage:'Set featured image',
    removeFeaturedImage:'Remove featured image',useFeaturedImage:'Use featured image',filterItemsList:'Filter list',filterByDate:'Filter by date',
    itemsListNavigation:'List navigation',itemsList:'Items list',itemPublished:'Published',itemPublishedPrivately:'Published privately',
    itemRevertedToDraft:'Reverted',itemScheduled:'Scheduled',itemUpdated:'Updated',itemLink:'Item link',itemLinkDescription:'Item link description',
  }
}
export function bookType(): ContentTypeDefinition {
  return {
    key:'book',labels:labels(),public:false,hierarchical:true,excludeFromSearch:true,publiclyQueryable:false,showUi:true,showInMenu:true,
    showInNavMenus:false,showInAdminBar:true,capabilities:capabilities(),
    supports:['title','editor','author','featuredImage','excerpt','comments','revisions','pageAttributes','postFormats','trackbacks'],
    taxonomies:[],hasArchive:false,rewrite:false,queryVariable:false,canExport:true,deleteWithAuthor:false,
    rest:{base:'books',namespace:'content/v1',revisions:true,autosaves:true},defaultTemplateKey:'default',
    statusKeys:['draft','published','trashed'],active:true,
  }
}
function status(key:string): ContentStatusDefinition {
  if(key==='published') return {key,label:'Published',published:true,internal:false,excludeFromSearch:false,publiclyQueryable:true,showInAdminAll:true,showInAdminStatusFilter:true,dateLabel:'published',transitionInput:'publishedAt'}
  if(key==='trashed') return {key,label:'Trashed',published:false,internal:true,excludeFromSearch:true,publiclyQueryable:false,showInAdminAll:false,showInAdminStatusFilter:false,dateLabel:'lastModified',transitionInput:'none'}
  return {key,label:'Draft',published:false,internal:false,excludeFromSearch:true,publiclyQueryable:false,showInAdminAll:true,showInAdminStatusFilter:true,dateLabel:'lastModified',transitionInput:'none'}
}
export const admin: ContentPrincipal = Object.freeze({ id:'admin', capabilities:new Set(Object.values(capabilities())) })
export const reader: ContentPrincipal = Object.freeze({ id:'reader', capabilities:new Set(['read']) })
const definitionAuth: ContentDefinitionAuthorization = { assert: async()=>({policyVersion:'p1'}) }
const definitionEffects: ContentDefinitionEffects = { audit:{record:async()=>{}}, outbox:{enqueue:async()=>{}} }

export interface LifecycleFixture {
  db: Awaited<ReturnType<typeof startPg>>['db']
  stop(): Promise<void>
}
export async function lifecycleFixture(): Promise<LifecycleFixture> {
  const pg=await startPg()
  await pg.db.execute(sql.raw(LEGACY_PG_DDL))
  for(const statement of contentModelForwardMigrationSql('postgres')) await pg.db.execute(sql.raw(statement))
  for(const statement of contentRevisionsMigrationSql().split(';').map((x)=>x.trim()).filter(Boolean)) await pg.db.execute(sql.raw(statement))
  for(const statement of contentTaxonomyMigrationSql().split(';').map((x)=>x.trim()).filter(Boolean)) await pg.db.execute(sql.raw(statement))
  await pg.db.transaction(async(tx)=>{
    await createContentStatus(tx,admin,{definition:status('draft'),operationId:'seed:draft'},definitionAuth,definitionEffects)
    await createContentStatus(tx,admin,{definition:status('published'),operationId:'seed:published'},definitionAuth,definitionEffects)
    await createContentStatus(tx,admin,{definition:status('trashed'),operationId:'seed:trashed'},definitionAuth,definitionEffects)
    await createContentType(tx,admin,{definition:bookType(),operationId:'seed:book'},definitionAuth,definitionEffects)
  })
  return {db:pg.db,stop:pg.stop}
}

export function writeDeps(events: unknown[] = []): ContentWriteDependencies {
  const outbox: ContentOutbox={enqueue:async(_tx,event)=>{events.push(event)}}
  return {
    sanitize:(raw)=>raw.replace(/<script[^>]*>.*?<\/script>/gis,''),
    templates:{version:'v1',resolve:(type,key)=>type==='book'&&key==='default'?{key:'default',label:'Default',typeKeys:['book']}:undefined,list:()=>[{key:'default',label:'Default',typeKeys:['book']}]},
    authors:{assertAssign:async()=>{},assertTransfer:async()=>{}},
    capabilities:{validateMediaRef:async()=>{}},
    outbox,
  }
}
