import ArgumentParser
import Foundation
import Logging
import LoggingModels
import Services
import ServicesModels
import SharedConstants
// MARK: - List Frameworks Command

/// CLI command for listing available frameworks - mirrors MCP tool functionality.
@available(macOS 10.15, macCatalyst 13, iOS 13, tvOS 13, watchOS 6, *)
extension CLIImpl.Command {
    struct ListFrameworks: AsyncParsableCommand {
        static let configuration = CommandConfiguration(
            commandName: "list-frameworks",
            abstract: "List available frameworks with document counts"
        )

        @Option(
            name: .long,
            help: "Output format: text (default), json, markdown"
        )
        var format: OutputFormat = .text

        @Option(
            name: .long,
            help: "Path to search database"
        )
        var searchDb: String?

        mutating func run() async throws {
            // GoF Factory Method (1994 p. 107): construct the concrete
            // Creator at the command's composition sub-root. Stateless
            // structs need no singleton handle — per GoF p. 127, the
            // Singleton pattern is reserved for "exactly one instance"
            // semantics that stateless empty structs don't require.
            let searchDatabaseFactory: any SearchModule.DatabaseFactory = LiveSearchDatabaseFactory()

            // Path-DI composition sub-root (#535).
            let searchDBURL = searchDb.map { URL(fileURLWithPath: $0).expandingTildeInPath }
                ?? Shared.Paths.live().searchDatabase

            // Use Services.ServiceContainer for managed lifecycle
            let (frameworks, totalDocs) = try await Services.ServiceContainer.withDocsService(searchDB: searchDBURL, searchDatabaseFactory: searchDatabaseFactory) { service in
                let frameworks = try await service.listFrameworks()
                let totalDocs = try await service.documentCount()
                return (frameworks, totalDocs)
            }

            // Output results using formatters
            switch format {
            case .text:
                let formatter = Services.Formatter.Frameworks.Text(totalDocs: totalDocs)
                Cupertino.Context.composition.logging.recording.output(formatter.format(frameworks))
            case .json:
                let formatter = Services.Formatter.Frameworks.JSON()
                Cupertino.Context.composition.logging.recording.output(formatter.format(frameworks))
            case .markdown:
                let formatter = Services.Formatter.Frameworks.Markdown(totalDocs: totalDocs)
                Cupertino.Context.composition.logging.recording.output(formatter.format(frameworks))
            }
        }
    }
}

// MARK: - Output Format

extension CLIImpl.Command.ListFrameworks {
    enum OutputFormat: String, ExpressibleByArgument, CaseIterable {
        case text
        case json
        case markdown
    }
}
