package httpapi

import (
	"encoding/json"
	"errors"
	"net/http"
	"strings"

	"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
)

// listCatalogProviders godoc
// @Summary 列出目录供应商
// @Description 返回模型目录使用的供应商元数据；公共路径和管理路径返回同一结构。
// @Tags catalog
// @Produce json
// @Success 200 {object} CatalogProviderListResponse
// @Failure 500 {object} ErrorEnvelope
// @Router /api/v1/public/catalog/providers [get]
// @Router /api/admin/catalog/providers [get]
func (s *Server) listCatalogProviders(w http.ResponseWriter, r *http.Request) {
	items, err := s.store.ListCatalogProviders(r.Context())
	if err != nil {
		s.logger.Error("list catalog providers failed", "error", err)
		writeError(w, http.StatusInternalServerError, "list catalog providers failed")
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"items": items})
}

// createCatalogProvider godoc
// @Summary 创建目录供应商
// @Description 管理端新增模型目录供应商，providerKey 和 displayName 必填。
// @Tags catalog
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param input body store.CatalogProviderInput true "目录供应商请求"
// @Success 201 {object} store.CatalogProvider
// @Failure 400 {object} ErrorEnvelope
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 409 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/admin/catalog/providers [post]
func (s *Server) createCatalogProvider(w http.ResponseWriter, r *http.Request) {
	var input store.CatalogProviderInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid json body")
		return
	}
	if strings.TrimSpace(input.ProviderKey) == "" || strings.TrimSpace(input.DisplayName) == "" {
		writeError(w, http.StatusBadRequest, "providerKey and displayName are required")
		return
	}
	item, err := s.store.CreateCatalogProvider(r.Context(), input)
	if err != nil {
		if store.IsUniqueViolation(err) {
			writeError(w, http.StatusConflict, "provider key or code already exists")
			return
		}
		s.logger.Error("create catalog provider failed", "error", err)
		writeError(w, http.StatusInternalServerError, "create catalog provider failed")
		return
	}
	writeJSON(w, http.StatusCreated, item)
}

// updateCatalogProvider godoc
// @Summary 更新目录供应商
// @Description 管理端更新目录供应商展示信息、图标和元数据。
// @Tags catalog
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param providerID path string true "目录供应商 ID"
// @Param input body store.CatalogProviderInput true "目录供应商请求"
// @Success 200 {object} store.CatalogProvider
// @Failure 400 {object} ErrorEnvelope
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 404 {object} ErrorEnvelope
// @Failure 409 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/admin/catalog/providers/{providerID} [patch]
func (s *Server) updateCatalogProvider(w http.ResponseWriter, r *http.Request) {
	var input store.CatalogProviderInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid json body")
		return
	}
	if strings.TrimSpace(input.ProviderKey) == "" || strings.TrimSpace(input.DisplayName) == "" {
		writeError(w, http.StatusBadRequest, "providerKey and displayName are required")
		return
	}
	item, err := s.store.UpdateCatalogProvider(r.Context(), r.PathValue("providerID"), input)
	if err != nil {
		if store.IsNotFound(err) {
			writeError(w, http.StatusNotFound, "catalog provider not found")
			return
		}
		if store.IsUniqueViolation(err) {
			writeError(w, http.StatusConflict, "provider key or code already exists")
			return
		}
		s.logger.Error("update catalog provider failed", "error", err)
		writeError(w, http.StatusInternalServerError, "update catalog provider failed")
		return
	}
	writeJSON(w, http.StatusOK, item)
}

// deleteCatalogProvider godoc
// @Summary 删除目录供应商
// @Description 管理端删除目录供应商。
// @Tags catalog
// @Produce json
// @Security BearerAuth
// @Param providerID path string true "目录供应商 ID"
// @Success 204 "No Content"
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 404 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/admin/catalog/providers/{providerID} [delete]
func (s *Server) deleteCatalogProvider(w http.ResponseWriter, r *http.Request) {
	if err := s.store.DeleteCatalogProvider(r.Context(), r.PathValue("providerID")); err != nil {
		if store.IsNotFound(err) {
			writeError(w, http.StatusNotFound, "catalog provider not found")
			return
		}
		s.logger.Error("delete catalog provider failed", "error", err)
		writeError(w, http.StatusInternalServerError, "delete catalog provider failed")
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// listBaseModels godoc
// @Summary 列出基础模型
// @Description 返回基础模型目录；公共路径和管理路径返回同一结构。
// @Tags catalog
// @Produce json
// @Success 200 {object} BaseModelListResponse
// @Failure 500 {object} ErrorEnvelope
// @Router /api/v1/public/catalog/base-models [get]
// @Router /api/admin/catalog/base-models [get]
func (s *Server) listBaseModels(w http.ResponseWriter, r *http.Request) {
	items, err := s.store.ListBaseModels(r.Context())
	if err != nil {
		s.logger.Error("list base models failed", "error", err)
		writeError(w, http.StatusInternalServerError, "list base models failed")
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"items": items})
}

// createBaseModel godoc
// @Summary 创建基础模型
// @Description 管理端新增基础模型目录项，providerKey、providerModelName 和 modelType 必填。
// @Tags catalog
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param input body store.BaseModelInput true "基础模型请求"
// @Success 201 {object} store.BaseModel
// @Failure 400 {object} ErrorEnvelope
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 409 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/admin/catalog/base-models [post]
func (s *Server) createBaseModel(w http.ResponseWriter, r *http.Request) {
	var input store.BaseModelInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid json body")
		return
	}
	if !validBaseModelInput(input) {
		writeError(w, http.StatusBadRequest, "providerKey, providerModelName and modelType are required")
		return
	}
	item, err := s.store.CreateBaseModel(r.Context(), input)
	if err != nil {
		if errors.Is(err, store.ErrModelAliasConflict) {
			writeError(w, http.StatusConflict, err.Error(), "model_alias_conflict")
			return
		}
		if store.IsUniqueViolation(err) {
			writeError(w, http.StatusConflict, "canonical model key already exists")
			return
		}
		s.logger.Error("create base model failed", "error", err)
		writeError(w, http.StatusInternalServerError, "create base model failed")
		return
	}
	writeJSON(w, http.StatusCreated, item)
}

// updateBaseModel godoc
// @Summary 更新基础模型
// @Description 管理端更新基础模型目录项及能力、图标、默认快照等元数据。
// @Tags catalog
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param baseModelID path string true "基础模型 ID"
// @Param input body store.BaseModelInput true "基础模型请求"
// @Success 200 {object} store.BaseModel
// @Failure 400 {object} ErrorEnvelope
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 404 {object} ErrorEnvelope
// @Failure 409 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/admin/catalog/base-models/{baseModelID} [patch]
func (s *Server) updateBaseModel(w http.ResponseWriter, r *http.Request) {
	var input store.BaseModelInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid json body")
		return
	}
	if !validBaseModelInput(input) {
		writeError(w, http.StatusBadRequest, "providerKey, providerModelName and modelType are required")
		return
	}
	item, err := s.store.UpdateBaseModel(r.Context(), r.PathValue("baseModelID"), input)
	if err != nil {
		if store.IsNotFound(err) {
			writeError(w, http.StatusNotFound, "base model not found")
			return
		}
		if store.IsUniqueViolation(err) {
			writeError(w, http.StatusConflict, "canonical model key already exists")
			return
		}
		if errors.Is(err, store.ErrModelAliasConflict) {
			writeError(w, http.StatusConflict, err.Error(), "model_alias_conflict")
			return
		}
		s.logger.Error("update base model failed", "error", err)
		writeError(w, http.StatusInternalServerError, "update base model failed")
		return
	}
	writeJSON(w, http.StatusOK, item)
}

// resetBaseModel godoc
// @Summary 重置基础模型
// @Description 将指定基础模型恢复为系统默认快照；无默认快照时返回 409。
// @Tags catalog
// @Produce json
// @Security BearerAuth
// @Param baseModelID path string true "基础模型 ID"
// @Success 200 {object} store.BaseModel
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 404 {object} ErrorEnvelope
// @Failure 409 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/admin/catalog/base-models/{baseModelID}/reset [post]
func (s *Server) resetBaseModel(w http.ResponseWriter, r *http.Request) {
	item, err := s.store.ResetBaseModelToDefault(r.Context(), r.PathValue("baseModelID"))
	if err != nil {
		if store.IsNotFound(err) {
			writeError(w, http.StatusNotFound, "base model not found")
			return
		}
		if errors.Is(err, store.ErrProtectedDefault) {
			writeError(w, http.StatusConflict, "base model has no system default snapshot")
			return
		}
		s.logger.Error("reset base model failed", "error", err)
		writeError(w, http.StatusInternalServerError, "reset base model failed")
		return
	}
	writeJSON(w, http.StatusOK, item)
}

// resetAllBaseModels godoc
// @Summary 重置全部基础模型
// @Description 将所有具备系统默认快照的基础模型恢复为默认配置。
// @Tags catalog
// @Produce json
// @Security BearerAuth
// @Success 200 {object} BaseModelListResponse
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/admin/catalog/base-models/reset-all [post]
func (s *Server) resetAllBaseModels(w http.ResponseWriter, r *http.Request) {
	items, err := s.store.ResetAllBaseModelsToDefault(r.Context())
	if err != nil {
		s.logger.Error("reset all base models failed", "error", err)
		writeError(w, http.StatusInternalServerError, "reset all base models failed")
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"items": items})
}

// deleteBaseModel godoc
// @Summary 删除基础模型
// @Description 管理端删除基础模型目录项。
// @Tags catalog
// @Produce json
// @Security BearerAuth
// @Param baseModelID path string true "基础模型 ID"
// @Success 204 "No Content"
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 404 {object} ErrorEnvelope
// @Failure 409 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/admin/catalog/base-models/{baseModelID} [delete]
func (s *Server) deleteBaseModel(w http.ResponseWriter, r *http.Request) {
	if err := s.store.DeleteBaseModel(r.Context(), r.PathValue("baseModelID")); err != nil {
		if store.IsNotFound(err) {
			writeError(w, http.StatusNotFound, "base model not found")
			return
		}
		if errors.Is(err, store.ErrBaseModelInUse) {
			writeError(w, http.StatusConflict, "base model is still referenced by platform models", "base_model_in_use")
			return
		}
		s.logger.Error("delete base model failed", "error", err)
		writeError(w, http.StatusInternalServerError, "delete base model failed")
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

func validBaseModelInput(input store.BaseModelInput) bool {
	return strings.TrimSpace(input.ProviderKey) != "" &&
		strings.TrimSpace(input.ProviderModelName) != "" &&
		len(input.ModelType) > 0
}
