import type { CreateObjectType, ProgressStatus } from '@factor/api'
import { FactorDbCol, FactorDbTable } from '@factor/api/plugin-db'
import type { EditorState } from './site'

export const tableNames = { sites: 'factor_site', regions: 'factor_site_card' }

type st = { updatedAt?: string, createdAt?: string }

export type TableSiteConfig = CreateObjectType<typeof siteCols> & st & { regions: Partial<TableCardConfig>[] }

export type StandardUserConfig = Record<string, unknown> & { title?: string }
export type TableCardConfig<T extends StandardUserConfig = StandardUserConfig > = Partial<Omit<CreateObjectType<typeof pageCols>, 'cards' | 'userConfig'>> & st & {
  parentId?: string
  depth?: number
  userConfig?: T
  cards?: TableCardConfig[]
}

const siteCols = [
  new FactorDbCol({
    key: 'siteId',
    create: ({ schema, column, db }) => {
      schema
        .string(column.pgKey)
        .primary()
        .defaultTo(db.raw(`generate_object_id()`))
    },
    default: () => '',
  }),
  new FactorDbCol({
    key: 'userId',
    create: ({ schema, column }) => {
      schema
        .string(column.pgKey, 32)
        .references(`factor_user.user_id`)
    },
    default: () => '',
  }),
  new FactorDbCol({
    key: 'organizationId',
    create: ({ schema, column }) => {
      schema
        .string(column.pgKey, 32)
        .references(`factor_organization.organization_id`)
        .onUpdate('CASCADE')
        .notNullable()
    },
    default: () => '',
  }),
  new FactorDbCol({
    key: 'title',
    create: ({ schema, column }) => schema.string(column.pgKey).defaultTo(''),
    default: () => '',
    isSetting: true,
  }),
  new FactorDbCol({
    key: 'themeId',
    create: ({ schema, column }) => schema.string(column.pgKey).notNullable(),
    default: () => '',
    isSetting: true,
  }),

  new FactorDbCol({
    key: 'slug',
    create: ({ schema, column, db }) => schema.string(column.pgKey).unique().notNullable().defaultTo(db.raw(`short_id(9)`)),
    default: () => '',
    isSetting: true,
    prepare: ({ value }) =>
      (value as string).replaceAll(/[^\dA-Za-z-_]+/g, '').toLowerCase(),
  }),
  new FactorDbCol({
    key: 'domain',
    create: ({ schema, column }) => schema.string(column.pgKey).defaultTo(''),
    default: () => '',
    isSetting: true,
  }),
  new FactorDbCol({
    key: 'status',
    create: ({ schema, column }) => schema.string(column.pgKey).notNullable().defaultTo('pending'),
    default: () => '' as ProgressStatus,
  }),

  new FactorDbCol({
    key: 'userConfig',
    create: ({ schema, column }) => schema.jsonb(column.pgKey).defaultTo({}),
    prepare: ({ value }) => JSON.stringify(value),
    isSetting: true,
    default: () => ({}),
  }),
  new FactorDbCol({
    key: 'editor',
    create: ({ schema, column }) => schema.jsonb(column.pgKey).defaultTo({}),
    prepare: ({ value }) => JSON.stringify(value),
    isSetting: true,
    default: () => ({} as EditorState),
  }),

] as const

const pageCols = [
  new FactorDbCol({
    key: 'cardId',
    create: ({ schema, column, db }) => {
      schema
        .string(column.pgKey)
        .primary()
        .defaultTo(db.raw(`generate_object_id('card')`))
    },
    default: () => '',
  }),
  new FactorDbCol({
    key: 'regionKey',
    create: ({ schema, column }) => schema.string(column.pgKey).notNullable().defaultTo('page'),
    default: () => '' as 'header' | 'footer' | 'page',
    isSetting: true,
  }),
  new FactorDbCol({
    key: 'templateKey',
    create: ({ schema, column }) => schema.string(column.pgKey).notNullable().defaultTo('region'),
    default: () => '',
    isSetting: true,
  }),
  new FactorDbCol({
    key: 'siteId',
    create: ({ schema, column }) => {
      schema
        .string(column.pgKey, 32)
        .references(`${tableNames.sites}.site_id`)
        .onUpdate('CASCADE')
        .notNullable()
    },
    default: () => '',
  }),
  new FactorDbCol({
    key: 'userId',
    create: ({ schema, column }) => {
      schema
        .string(column.pgKey, 32)
        .references(`factor_user.user_id`)
    },
    default: () => '',
  }),
  new FactorDbCol({
    key: 'organizationId',
    create: ({ schema, column }) => {
      schema
        .string(column.pgKey, 32)
        .references(`factor_organization.organization_id`)
        .onUpdate('CASCADE')
        .notNullable()
    },
    default: () => '',
  }),
  new FactorDbCol({
    key: 'title',
    create: ({ schema, column }) => schema.string(column.pgKey).defaultTo(''),
    default: () => '',
    isSetting: true,
  }),
  new FactorDbCol({
    key: 'slug',
    create: ({ schema, column, db }) => schema.string(column.pgKey).defaultTo(db.raw(`short_id(6)`)),
    default: () => '' as string | '_home' | '_404' | '',
    isSetting: true,
    prepare: ({ value }) =>
      (value as string).replaceAll(/[\s]+/g, '-') // Replace one or more spaces with a hyphen
        .replaceAll(/[^\dA-Za-z-_]+/g, '') // Remove non-allowed characters
        .toLowerCase(),
  }),
  new FactorDbCol({
    key: 'cards',
    create: ({ schema, column }) => schema.jsonb(column.pgKey).defaultTo([]),
    prepare: ({ value }) => JSON.stringify(value),
    isSetting: true,
    default: () => ([]),
  }),
  new FactorDbCol({
    key: 'userConfig',
    create: ({ schema, column }) => schema.jsonb(column.pgKey).defaultTo({}),
    prepare: ({ value }) => JSON.stringify(value),
    isSetting: true,
    default: () => ({}),
  }),
  new FactorDbCol({
    key: 'editor',
    create: ({ schema, column }) => schema.jsonb(column.pgKey).defaultTo({}),
    prepare: ({ value }) => JSON.stringify(value),
    isSetting: true,
    default: () => ({} as Record<string, unknown>),
  }),
] as const

export const tables = [
  new FactorDbTable({
    tableKey: tableNames.sites,
    timestamps: true,
    columns: siteCols,
  }),
  new FactorDbTable({
    tableKey: tableNames.regions,
    timestamps: true,
    columns: pageCols,
  }),
]
