import { FastifyInstance } from "fastify"
import { Server } from "http"
import { IncomingMessage, ServerResponse } from "http"
import { Connection } from "mongoose"
import { DefaultEventsMap, Socket } from "socket.io"
import EventEmitter from "@c/events/eventEmitter"
import { ValkeyService } from "@raclettejs/core/backend/lib/cache/providers/valkey/valkeyConnection"
import OpenSearchAPI from "@opensearch-project/opensearch/api/OpenSearchApi"
import { Client } from "@opensearch-project/opensearch"
import { TaskManager } from "../core/backgroundTasks/taskManagerTypes"
import { HttpService } from "../core/http/httpTypes"
import { UserDoc } from "@c/user/user.schema"
import { FrontendPayloadRequestData } from "@/utils/request.utils"
import { FastifyRequest, FastifyReply } from "fastify"
import type RateLimit from "@fastify/rate-limit"
import type { RequestWorkSession } from "@/corePlugins/raclette__core/backend/datatypes/workSession/workSession.schema"

export type { RequestWorkSession }

declare module "fastify" {
  interface FastifyInstance {
    database: Connection
    rateLimit: RateLimit
    authenticate: (req: FastifyRequest, res: FastifyReply) => Promise<void>
    authenticatedOrWorksession: (
      pluginKey: string,
    ) => (req: FastifyRequest, res: FastifyReply) => Promise<void>
    checkPermissions: (
      permissions: string,
    ) => (req: FastifyRequest, res: FastifyReply) => Promise<void>
    wss: Socket<DefaultEventsMap, DefaultEventsMap, DefaultEventsMap, any>
    eventbus: EventEmitter
    cache: ValkeyService
    os: OpenSearchAPI
    qos: Client
    uos: Client
    http: HttpService
    taskManager: TaskManager
    core: any
  }

  interface FastifyRequest {
    database: Connection
    user: UserDoc
    requestParams: FrontendPayloadRequestData
    /** Set by authenticatedOrWorksession when request is via work session */
    workSession?: RequestWorkSession
    /** Set by authenticatedOrWorksession when request is via work session */
    isWorkSession?: boolean
    /** Project ID from user (lastProjectId) or workSession.project */
    projectId?: string
  }

  interface RouteOptions {
    skipHeaderValidation?: boolean
  }

  interface FastifyContextConfig {
    type?: string
    broadcast?: string[] | boolean
    broadcastChannels?: string[]
  }
}
