import type { Static } from "@sinclair/typebox"
import type { Document } from "mongoose"
import { Type } from "@sinclair/typebox"
import type { PluginFastifyInstance } from "types"

/**
 * Composition Schema
 */
/**
 * Widget Schema
 */
// TODO: in progress
export const widgetSchema = Type.Object({
  uuid: Type.String(),
  name: Type.String(),
  pluginKey: Type.String(),
  config: Type.Optional(Type.Any()),
  public: Type.Optional(Type.Any()),
})

/**
 * Column Slot Schema
 */
// TODO: in progress
export const widgetLayoutSchema = Type.Object({
  column: Type.Number(),
  widget: widgetSchema,
})

/**
 * Base Composition Schema - Fields common to all operations
 */
const baseCompositionSchema = {
  title: Type.String({ minLength: 1, maxLength: 200 }),
  description: Type.Optional(Type.String()),
  tags: Type.Array(Type.String(), { default: [] }),
  icon: Type.Optional(Type.String()),
  pathname: Type.Record(Type.String(), Type.String(), { default: {} }),
  slotLayout: Type.Optional(Type.String()),
  status: Type.Enum(
    { live: "live", test: "test", inProgress: "inProgress" },
    { default: "inProgress" },
  ),
  widgetsLayout: Type.Array(Type.Array(widgetLayoutSchema), { default: [] }),
}

/**
 * Full Composition Schema - Used for response serialization and database model
 */
export const compositionSchema = Type.Object(
  {
    _id: Type.String(),
    ...baseCompositionSchema,
    author: Type.String(),
    lastEditor: Type.String(),
    createdAt: Type.String({ format: "date-time" }),
    updatedAt: Type.String({ format: "date-time" }),
    isDeleted: Type.Boolean({ default: false }),
  },
  {
    $id: "#composition/base",
    title: "core/composition",
  },
)

/**
 * Composition Create Schema - For POST operations
 */
export const compositionCreateSchema = Type.Object(baseCompositionSchema, {
  $id: "#composition/create",
  title: "core/composition-create",
})

/**
 * Composition Update Schema - For PATCH operations
 */
export const compositionUpdateSchema = Type.Object(baseCompositionSchema, {
  $id: "#composition/update",
  title: "core/composition-update",
})

/**
 * Type Utilities
 */

type DateTimeFields = {
  createdAt: Date
  updatedAt: Date
}

type RawComposition = Static<typeof compositionSchema>

export type Composition = Omit<RawComposition, keyof DateTimeFields> &
  DateTimeFields

export interface CompositionDoc
  extends Document<string, unknown, Composition>,
    Composition {
  _id: string
}

export type AnyComposition = Composition | CompositionDoc

/**
 * Register Schema/Type Generation for Shared Folder
 */
export const registerSchemas = (fastify: PluginFastifyInstance) => {
  fastify.registerSchema({
    schema: compositionSchema,
    name: "Composition",
  })

  fastify.registerSchema({
    schema: compositionCreateSchema,
    name: "CompositionCreate",
  })

  fastify.registerSchema({
    schema: compositionUpdateSchema,
    name: "CompositionUpdate",
  })

  fastify.registerSchema({
    schema: widgetSchema,
    name: "Widget",
  })

  fastify.registerSchema({
    schema: widgetLayoutSchema,
    name: "WidgetLayout",
  })
}
