import type { CollectionConfig, Field } from "payload"
import { MissingCollectionSlug } from "../core/errors/consoleErrors.js"

/**
 * A higher order function that takes the collection config for the argument
 * @param incomingCollection
 * @returns {CollectionConfig}
 */
export const withUsersCollection = (
  incomingCollection: Omit<CollectionConfig, "fields"> & {
    fields?: Field[] | undefined
  },
): CollectionConfig => {
  if (!incomingCollection.slug) {
    throw new MissingCollectionSlug()
  }

  if (incomingCollection.auth) {
  }

  const collectionConfig: CollectionConfig = {
    ...incomingCollection,
    fields: [],
  }

  const baseFields: Field[] = [
    {
      name: "hashedPassword",
      type: "text",
      unique: true,
      hidden: true,
    },
    {
      name: "hashSalt",
      type: "text",
      unique: true,
      hidden: true,
    },
    {
      name: "hashIterations",
      type: "number",
      hidden: true,
    },
    {
      name: "verificationCode",
      label: "Verification Code",
      type: "text",
      hidden: true,
      unique: true,
    },
    {
      name: "verificationHash",
      label: "Verification Hash",
      type: "text",
      hidden: true,
    },
    {
      name: "verificationTokenExpire",
      label: "Verification Token Expire",
      type: "number",
      hidden: true,
    },
    {
      name: "verificationKind",
      label: "Verification Kind",
      type: "text",
      hidden: true,
    },
    {
      name: "claims",
      label: "Claims",
      type: "json",
      hidden: true,
    },
  ]
  if (!incomingCollection.fields?.find((field) => field.type === "email")) {
    baseFields.push({
      name: "email",
      type: "email",
      unique: true,
      required: true,
    })
  }

  collectionConfig.fields = [
    ...(incomingCollection.fields ?? []),
    ...baseFields,
  ]
  collectionConfig.access = {
    admin: ({ req: { user } }) => Boolean(user),
    create: ({ req: { user } }) => Boolean(user),
    delete: ({ req: { user } }) => Boolean(user),
    read: ({ req: { user } }) => Boolean(user),
    update: ({ req: { user } }) => Boolean(user),
    ...(incomingCollection.access ?? {}),
  }
  collectionConfig.admin = {
    defaultColumns: ["name", "email"],
    useAsTitle: "name",
    ...incomingCollection.admin,
  }
  collectionConfig.timestamps = true

  return collectionConfig
}

/**
 * A higher order function that takes the collection config and a Users collection slug for the arguments
 * @param incomingCollection
 * @param userCollectionSlug
 * @returns {CollectionConfig}
 */
export const withAccountCollection = (
  incomingCollection: Omit<CollectionConfig, "fields"> & {
    fields?: Field[] | undefined
  },
  usersCollectionSlug: string,
): CollectionConfig => {
  if (!incomingCollection.slug) {
    throw new MissingCollectionSlug()
  }

  const collectionConfig: CollectionConfig = {
    ...incomingCollection,
    fields: [],
  }

  const baseFields: Field[] = [
    {
      name: "name",
      type: "text",
    },
    {
      name: "picture",
      type: "text",
    },
    {
      name: "user",
      type: "relationship",
      relationTo: usersCollectionSlug,
      hasMany: false,
      required: true,
      label: "User",
    },
    {
      name: "issuerName",
      type: "text",
      required: true,
      label: "Issuer Name",
    },
    {
      name: "scope",
      type: "text",
    },
    {
      name: "sub",
      type: "text",
      required: true,
    },
    {
      name: "access_token",
      type: "text",
    },
    {
      name: "refresh_token",
      type: "text",
    },
    {
      name: "expires_in",
      type: "number",
    },
    {
      name: "passkey",
      type: "group",
      fields: [
        {
          name: "credentialId",
          type: "text",
          required: true,
        },
        {
          name: "publicKey",
          type: "json",
          required: true,
        },
        {
          name: "counter",
          type: "number",
          required: true,
        },
        {
          name: "transports",
          type: "json",
          required: true,
        },
        {
          name: "deviceType",
          type: "text",
          required: true,
        },
        {
          name: "backedUp",
          type: "checkbox",
          required: true,
        },
      ],
      admin: {
        condition: (_data, peerData) => {
          if (peerData.issuerName === "Passkey") {
            return true
          }
          return false
        },
      },
    },
  ]

  collectionConfig.fields = [
    ...baseFields,
    ...(incomingCollection.fields ?? []),
  ]

  collectionConfig.access = {
    admin: ({ req: { user } }) => Boolean(user),
    read: ({ req: { user } }) => Boolean(user),
    create: () => false,
    update: () => false,
    delete: () => true,
    ...(incomingCollection.access ?? {}),
  }
  collectionConfig.admin = {
    defaultColumns: ["issuerName", "scope", "user"],
    useAsTitle: "id",
    ...incomingCollection.admin,
  }
  collectionConfig.timestamps = true
  return collectionConfig
}
