import type { PluginFastifyInstance } from "types"
import mongoose, { type Connection } from "mongoose"

export interface CollectionInfo {
  name: string
  count: number
  size: number
  indexes: number
}

export class CollectionService {
  private connection: Connection

  constructor(connection: Connection) {
    this.connection = connection
  }

  /**
   * Get all collection names and their metadata
   */
  async getCollections(
    fastify: PluginFastifyInstance,
  ): Promise<CollectionInfo[]> {
    try {
      const db = this.connection.db
      const collections = await db.listCollections().toArray()

      const collectionInfos: CollectionInfo[] = []

      for (const collection of collections) {
        const collectionName = collection.name

        // Get document count
        const count = await db.collection(collectionName).countDocuments()

        // Get collection stats using MongoDB command
        const stats = await db.command({ collStats: collectionName })

        collectionInfos.push({
          name: collectionName,
          count: count || 0,
          size: stats.size || 0,
          indexes: stats.nindexes || 0,
        })
      }

      fastify.log.info(`[API] Retrieved ${collectionInfos.length} collections`)

      return collectionInfos
    } catch (error: any) {
      fastify.log.error(error.message)
      throw error
    }
  }

  /**
   * Drop specific collections
   */
  async dropCollections(
    fastify: PluginFastifyInstance,
    collectionNames: string[],
  ): Promise<{ dropped: string[]; failed: string[] }> {
    try {
      const db = this.connection.db
      const dropped: string[] = []
      const failed: string[] = []

      for (const collectionName of collectionNames) {
        try {
          // Check if collection exists
          const collections = await db
            .listCollections({ name: collectionName })
            .toArray()

          if (collections.length === 0) {
            fastify.log.warn(`Collection ${collectionName} does not exist`)
            failed.push(collectionName)
            continue
          }

          // Drop the collection
          await db.collection(collectionName).drop()
          dropped.push(collectionName)
          fastify.log.info(`[API] Dropped collection: ${collectionName}`)
        } catch (error: any) {
          fastify.log.error(
            `Failed to drop collection ${collectionName}: ${error.message}`,
          )
          failed.push(collectionName)
        }
      }

      return { dropped, failed }
    } catch (error: any) {
      fastify.log.error(error.message)
      throw error
    }
  }

  /**
   * Drop all collections (use with extreme caution!)
   */
  async dropAllCollections(
    fastify: PluginFastifyInstance,
  ): Promise<{ dropped: string[]; failed: string[] }> {
    try {
      const collections = await this.getCollections(fastify)
      const collectionNames = collections.map((c) => c.name)

      return await this.dropCollections(fastify, collectionNames)
    } catch (error: any) {
      fastify.log.error(error.message)
      throw error
    }
  }
}

export const createCollectionService = (connection: Connection) =>
  new CollectionService(connection)
