import { Effect, Schema } from "effect"
import { namedSchemaError } from "@/util/named-schema-error"
import { ModelID, ProviderID } from "./schema"
import { Model, Info, ListResult, ConfigProvidersResult, fromModelsDevProvider, sortModels, defaultModelIDs } from "./provider-schemas"
import type { State, BundledSDK } from "./provider-types"

export interface Interface {
  readonly list: () => Effect.Effect<Record<ProviderID, Info>>
  readonly getProvider: (providerID: ProviderID) => Effect.Effect<Info>
  readonly getModel: (providerID: ProviderID, modelID: ModelID) => Effect.Effect<Model>
  readonly getLanguage: (model: Model) => Effect.Effect<import("@ai-sdk/provider").LanguageModelV3>
  readonly closest: (providerID: ProviderID, query: string[]) => Effect.Effect<{ providerID: ProviderID; modelID: string } | undefined>
  readonly getSmallModel: (providerID: ProviderID) => Effect.Effect<Model | undefined>
  readonly defaultModel: () => Effect.Effect<{ providerID: ProviderID; modelID: ModelID }>
}

export { Service } from "./provider-types"

export { Model, Info, ListResult, ConfigProvidersResult, defaultModelIDs, sortModels as sort }
export type { BundledSDK } from "./provider-types"

export function parseModel(model: string) {
  const [providerID, ...rest] = model.split("/")
  return { providerID: ProviderID.make(providerID), modelID: ModelID.make(rest.join("/")) }
}

export const ModelNotFoundError = namedSchemaError("ProviderModelNotFoundError", {
  providerID: ProviderID, modelID: ModelID, suggestions: Schema.optional(Schema.Array(Schema.String)),
})

export const InitError = namedSchemaError("ProviderInitError", { providerID: ProviderID })

export { defaultLayer, list, getModelExport as getModel, getLanguage, getSmallModel, defaultModel } from "./provider-layer"
export { fromModelsDevProvider, ProviderCategory } from "./provider-schemas"
export { LOCAL_PROVIDERS, CUSTOM_PROVIDERS, CLOUD_PROVIDERS } from "./custom-loaders"

export * as Provider from "./provider"
