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

/**
 * Base Tag Schema - Fields common to all operations
 */
const baseTagSchema = {
  project: Type.Optional(Type.String()),
  title: Type.Optional(Type.String({ maxLength: 200, default: null })),
  tags: Type.Optional(Type.Array(Type.String(), { default: [] })),
  locked: Type.Optional(Type.Boolean({ default: false })),
  color: Type.Optional(
    Type.String({ pattern: "^#([0-9a-fA-F]{3}){1,2}$", default: "#CCCCCC" }),
  ),
  type: Type.Optional(
    Type.String({ enum: tagTypes, maxLength: 50, default: "system" }),
  ),
}

/**
 * Full Tag Schema - Used for response serialization and database model
 */
export const tagSchema = Type.Object(
  {
    _id: Type.String(),
    ...baseTagSchema,
    owner: Type.String(),
    order: Type.Optional(Type.Number({ default: 0 })),
    isDeleted: Type.Boolean({ default: false }),
    createdAt: Type.String({ format: "date-time" }),
    updatedAt: Type.String({ format: "date-time" }),
  },
  {
    $id: "#tag/base",
    title: "core/tag",
  },
)

/**
 * Tag Create Schema - For POST operations
 */
export const tagCreateSchema = Type.Object(
  {
    _id: Type.Optional(Type.String()),
    ...baseTagSchema,
  },
  {
    $id: "#tag/create",
    title: "core/tag-create",
  },
)

/**
 * Tag Update Schema - For PATCH operations
 */
export const tagUpdateSchema = Type.Object(
  {
    project: Type.Optional(Type.String()),
    title: Type.Optional(Type.String({ maxLength: 200 })),
    tags: Type.Optional(Type.Array(Type.String())),
    color: Type.Optional(Type.String({ pattern: "^#([0-9a-fA-F]{3}){1,2}$" })),
    type: Type.Optional(Type.String({ enum: tagTypes, maxLength: 50 })),
    owner: Type.Optional(Type.String()),
    order: Type.Optional(Type.Number()),
    locked: Type.Optional(Type.Boolean()),
  },
  {
    $id: "#tag/update",
    title: "core/tag-update",
  },
)

/**
 * Type Utilities
 */

type DateTimeFields = {
  createdAt: Date
  updatedAt: Date
}

type RawTag = Static<typeof tagSchema>
export type Tag = Omit<RawTag, keyof DateTimeFields> & DateTimeFields

type RawTagCreate = Static<typeof tagCreateSchema>
export type TagCreate = RawTagCreate

type RawTagUpdate = Static<typeof tagUpdateSchema>
export type TagUpdate = RawTagUpdate

export interface TagDoc extends Document, Tag {
  _id: string
}
export type AnyTag = Tag | TagDoc

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

  fastify.registerSchema({
    schema: tagCreateSchema,
    name: "TagCreate",
  })

  fastify.registerSchema({
    schema: tagUpdateSchema,
    name: "TagUpdate",
  })
}
