package v1

import (
	"context"
	"log/slog"
	"strings"

	"github.com/GoYoko/web"

	modelkitDomain "github.com/chaitin/ModelKit/v2/domain"
	modelkit "github.com/chaitin/ModelKit/v2/usecase"
	"github.com/chaitin/MonkeyCode/backend/domain"
	"github.com/chaitin/MonkeyCode/backend/internal/middleware"
)

type ModelHandler struct {
	usecase domain.ModelUsecase
	logger  *slog.Logger
}

func NewModelHandler(
	w *web.Web,
	usecase domain.ModelUsecase,
	auth *middleware.AuthMiddleware,
	active *middleware.ActiveMiddleware,
	readonly *middleware.ReadOnlyMiddleware,
	logger *slog.Logger,
) *ModelHandler {
	m := &ModelHandler{usecase: usecase, logger: logger.With("handler", "model")}

	g := w.Group("/api/v1/model")
	g.Use(auth.Auth(), active.Active("admin"), readonly.Guard())

	g.GET("", web.BaseHandler(m.List))
	g.GET("/provider/supported", web.BindHandler(m.GetProviderModelList))
	g.GET("/token-usage", web.BindHandler(m.GetTokenUsage))
	g.GET("/my", web.BindHandler(m.MyModelList))
	g.POST("", web.BindHandler(m.Create))
	g.POST("/check", web.BindHandler(m.Check))
	g.PUT("", web.BindHandler(m.Update))
	g.DELETE("", web.BaseHandler(m.Delete))

	return m
}

// Check 检查模型
//
//	@Tags			Model
//	@Summary		检查模型
//	@Description	检查模型
//	@ID				check-model
//	@Accept			json
//	@Produce		json
//	@Param			model	body		domain.CheckModelReq	true	"模型"
//	@Success		200		{object}	web.Resp{data=domain.CheckModelResp}
//	@Router			/api/v1/model/check [post]
func (h *ModelHandler) Check(c *web.Context, req domain.CheckModelReq) error {
	modelkitRes, err := modelkit.CheckModel(c.Request().Context(), &modelkitDomain.CheckModelReq{
		Provider:   string(req.Provider),
		Model:      req.ModelName,
		BaseURL:    req.APIBase,
		APIKey:     req.APIKey,
		APIHeader:  req.APIHeader,
		APIVersion: req.APIVersion,
		Type:       string(req.Type),
	})
	if err != nil {
		return c.Success(domain.CheckModelResp{
			Error: err.Error(),
		})
	}
	if modelkitRes.Error != "" {
		return c.Success(domain.CheckModelResp{
			Error: modelkitRes.Error,
		})
	}

	// 将输出转化为monkeycode格式
	m := &domain.Model{
		ModelType: req.Type,
		Provider:  req.Provider,
		ModelName: req.ModelName,
		APIBase:   req.APIBase,
	}
	// end

	return c.Success(domain.CheckModelResp{
		Model: m,
		Error: "",
	})
}

// List 获取模型列表
//
//	@Tags			Model
//	@Summary		获取模型列表
//	@Description	获取模型列表
//	@ID				list-model
//	@Accept			json
//	@Produce		json
//	@Success		200	{object}	web.Resp{data=domain.AllModelResp}
//	@Router			/api/v1/model [get]
func (h *ModelHandler) List(c *web.Context) error {
	models, err := h.usecase.List(c.Request().Context())
	if err != nil {
		return err
	}
	return c.Success(models)
}

// MyModelList 获取我的模型列表
//
//	@Tags			Model
//	@Summary		获取我的模型列表
//	@Description	获取我的模型列表
//	@ID				my-model-list
//	@Accept			json
//	@Produce		json
//	@Param			model_type	query		domain.MyModelListReq	true	"模型类型"
//	@Success		200			{object}	web.Resp{data=[]domain.Model}
//	@Router			/api/v1/model/my [get]
func (h *ModelHandler) MyModelList(c *web.Context, req domain.MyModelListReq) error {
	models, err := h.usecase.MyModelList(c.Request().Context(), &req)
	if err != nil {
		return err
	}
	return c.Success(models)
}

// Create 创建模型
//
//	@Tags			Model
//	@Summary		创建模型
//	@Description	创建模型
//	@ID				create-model
//	@Accept			json
//	@Produce		json
//	@Param			model	body		domain.CreateModelReq	true	"模型"
//	@Success		200		{object}	web.Resp{data=domain.Model}
//	@Router			/api/v1/model [post]
func (h *ModelHandler) Create(c *web.Context, req domain.CreateModelReq) error {
	admin := middleware.GetAdmin(c)
	req.AdminID = admin.ID
	req.APIBase = strings.TrimSuffix(req.APIBase, "/")
	m, err := h.usecase.Create(c.Request().Context(), &req)
	if err != nil {
		return err
	}
	return c.Success(m)
}

// Update 更新模型
//
//	@Tags			Model
//	@Summary		更新模型
//	@Description	更新模型
//	@ID				update-model
//	@Accept			json
//	@Produce		json
//	@Param			model	body		domain.UpdateModelReq	true	"模型"
//	@Success		200		{object}	web.Resp{data=domain.Model}
//	@Router			/api/v1/model [put]
func (h *ModelHandler) Update(c *web.Context, req domain.UpdateModelReq) error {
	m, err := h.usecase.Update(c.Request().Context(), &req)
	if err != nil {
		return err
	}
	return c.Success(m)
}

// GetTokenUsage 获取模型token使用情况
//
//	@Tags			Model
//	@Summary		获取模型token使用情况
//	@Description	获取模型token使用情况
//	@ID				get-token-usage
//	@Accept			json
//	@Produce		json
//	@Param			param	query		domain.GetTokenUsageReq	true	"模型类型"
//	@Success		200		{object}	web.Resp{data=domain.ModelTokenUsageResp}
//	@Router			/api/v1/model/token-usage [get]
func (h *ModelHandler) GetTokenUsage(c *web.Context, req domain.GetTokenUsageReq) error {
	resp, err := h.usecase.GetTokenUsage(c.Request().Context(), req.ModelType)
	if err != nil {
		return err
	}
	return c.Success(resp)
}

// GetProviderModelList 获取供应商支持的模型列表
//
//	@Tags			Model
//	@Summary		获取供应商支持的模型列表
//	@Description	获取供应商支持的模型列表
//	@ID				get-provider-model-list
//	@Accept			json
//	@Produce		json
//	@Param			param	query		domain.GetProviderModelListReq	true	"模型类型"
//	@Success		200		{object}	web.Resp{data=domain.GetProviderModelListResp}
//	@Router			/api/v1/model/provider/supported [get]
func (h *ModelHandler) GetProviderModelList(c *web.Context, req domain.GetProviderModelListReq) error {
	modelkitRes, err := modelkit.ModelList(c.Request().Context(), &modelkitDomain.ModelListReq{
		Provider:  string(req.Provider),
		Type:      string(req.Type),
		BaseURL:   req.BaseURL,
		APIKey:    req.APIKey,
		APIHeader: req.APIHeader,
	})
	if err != nil {
		res := &domain.GetProviderModelListResp{
			Error: err.Error(),
		}
		return c.Success(res)
	}

	// 将输出转化为monkeycode格式
	res := &domain.GetProviderModelListResp{
		Models: make([]domain.ProviderModelListItem, len(modelkitRes.Models)),
		Error:  modelkitRes.Error,
	}
	for i, model := range modelkitRes.Models {
		res.Models[i] = domain.ProviderModelListItem{
			Model: model.Model,
		}
	}
	// end

	return c.Success(res)
}

// Delete 删除模型
//
//	@Tags			Model
//	@Summary		删除模型
//	@Description	删除模型
//	@ID				delete-model
//	@Accept			json
//	@Produce		json
//	@Param			id	query		string	true	"模型ID"
//	@Success		200	{object}	web.Resp{}
//	@Router			/api/v1/model [delete]
func (h *ModelHandler) Delete(c *web.Context) error {
	if err := h.usecase.Delete(c.Request().Context(), c.QueryParam("id")); err != nil {
		return err
	}
	return c.Success(nil)
}

func (h *ModelHandler) InitModel() error {
	return h.usecase.InitModel(context.Background())
}
