package rest

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

	"github.com/gorilla/mux"
	"github.com/ocdp/cluster-service/internal/adapter/input/http/dto"
	"github.com/ocdp/cluster-service/internal/domain/entity"
	"github.com/ocdp/cluster-service/internal/domain/service"
)

// RegistryHandler Registry Handler
type RegistryHandler struct {
	registryService *service.RegistryService
}

// NewRegistryHandler 创建 Registry Handler
func NewRegistryHandler(registryService *service.RegistryService) *RegistryHandler {
	return &RegistryHandler{
		registryService: registryService,
	}
}

// CreateRegistry 创建 Registry
// @Summary 创建 Registry
// @Description 新增 OCI Registry 配置
// @Tags Registries
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.CreateRegistryRequest true "Registry 信息"
// @Success 201 {object} dto.RegistryResponse
// @Failure 400 {object} dto.ErrorResponse
// @Router /registries [post]
func (h *RegistryHandler) CreateRegistry(w http.ResponseWriter, r *http.Request) {
	var req dto.CreateRegistryRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		respondError(w, http.StatusBadRequest, "Invalid request body", err.Error())
		return
	}

	// 创建实体
	registry := entity.NewRegistry(req.Name, req.URL)
	registry.Description = req.Description
	registry.Insecure = req.Insecure
	registry.Visibility = req.Visibility
	if req.GlobalShared || req.GlobalSharedAlt {
		registry.Visibility = "global_shared"
	}
	registry.SetCredentials(req.Username, req.Password)

	// 调用领域服务
	if err := h.registryService.CreateRegistry(r.Context(), registry); err != nil {
		respondError(w, http.StatusBadRequest, "Failed to create registry", err.Error())
		return
	}

	// 返回响应（脱敏）
	response := dto.ToRegistryResponse(registry)
	respondJSON(w, http.StatusCreated, response)
}

// GetRegistry 获取 Registry 详情
// @Summary 获取 Registry
// @Tags Registries
// @Produce json
// @Security BearerAuth
// @Param registry_id path string true "Registry ID"
// @Success 200 {object} dto.RegistryResponse
// @Failure 404 {object} dto.ErrorResponse
// @Router /registries/{registry_id} [get]
func (h *RegistryHandler) GetRegistry(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	registryID := vars["registry_id"]

	registry, err := h.registryService.GetRegistry(r.Context(), registryID)
	if err != nil {
		respondError(w, http.StatusNotFound, "Registry not found", err.Error())
		return
	}

	// 返回响应（脱敏）
	response := dto.ToRegistryResponse(registry)
	respondJSON(w, http.StatusOK, response)
}

// GetAllRegistries 获取所有 Registries
// @Summary 列出所有 Registries
// @Tags Registries
// @Produce json
// @Security BearerAuth
// @Success 200 {array} dto.RegistryResponse
// @Failure 500 {object} dto.ErrorResponse
// @Router /registries [get]
func (h *RegistryHandler) GetAllRegistries(w http.ResponseWriter, r *http.Request) {
	registries, err := h.registryService.ListRegistries(r.Context())
	if err != nil {
		respondError(w, http.StatusInternalServerError, "Failed to list registries", err.Error())
		return
	}

	// 转换为响应（脱敏）
	responses := make([]*dto.RegistryResponse, 0, len(registries))
	for _, registry := range registries {
		responses = append(responses, dto.ToRegistryResponse(registry))
	}

	respondJSON(w, http.StatusOK, responses)
}

// UpdateRegistry 更新 Registry
// @Summary 更新 Registry
// @Tags Registries
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param registry_id path string true "Registry ID"
// @Param request body dto.UpdateRegistryRequest true "更新内容"
// @Success 200 {object} dto.RegistryResponse
// @Failure 404 {object} dto.ErrorResponse
// @Router /registries/{registry_id} [put]
func (h *RegistryHandler) UpdateRegistry(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	registryID := vars["registry_id"]

	var req dto.UpdateRegistryRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		respondError(w, http.StatusBadRequest, "Invalid request body", err.Error())
		return
	}

	// 获取现有 Registry
	registry, err := h.registryService.GetRegistry(r.Context(), registryID)
	if err != nil {
		respondError(w, http.StatusNotFound, "Registry not found", err.Error())
		return
	}

	// 更新字段
	registry.Update(req.Name, req.URL, req.Description)
	registry.Insecure = req.Insecure
	if req.Visibility != "" {
		registry.Visibility = req.Visibility
	}
	if req.GlobalShared || req.GlobalSharedAlt {
		registry.Visibility = "global_shared"
	}
	if req.Username != "" || req.Password != "" {
		registry.SetCredentials(req.Username, req.Password)
	}

	// 调用领域服务
	if err := h.registryService.UpdateRegistry(r.Context(), registry); err != nil {
		respondError(w, http.StatusBadRequest, "Failed to update registry", err.Error())
		return
	}

	// 返回响应（脱敏）
	response := dto.ToRegistryResponse(registry)
	respondJSON(w, http.StatusOK, response)
}

// DeleteRegistry 删除 Registry
// @Summary 删除 Registry
// @Tags Registries
// @Produce json
// @Security BearerAuth
// @Param registry_id path string true "Registry ID"
// @Success 204 {string} string "No Content"
// @Failure 404 {object} dto.ErrorResponse
// @Router /registries/{registry_id} [delete]
func (h *RegistryHandler) DeleteRegistry(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	registryID := vars["registry_id"]

	if err := h.registryService.DeleteRegistry(r.Context(), registryID); err != nil {
		respondError(w, http.StatusNotFound, "Failed to delete registry", err.Error())
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

// GetRegistryHealth 获取 Registry 健康状态
// @Summary 检查 Registry 健康
// @Tags Registries
// @Produce json
// @Security BearerAuth
// @Param registry_id path string true "Registry ID"
// @Success 200 {object} dto.RegistryHealthResponse
// @Router /registries/{registry_id}/health [get]
func (h *RegistryHandler) GetRegistryHealth(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	registryID := vars["registry_id"]

	// 调用领域服务检查健康状态
	err := h.registryService.CheckHealth(r.Context(), registryID)

	response := &dto.RegistryHealthResponse{
		Healthy: err == nil,
	}

	if err != nil {
		response.Message = err.Error()
	} else {
		response.Message = "Registry is healthy"
	}

	respondJSON(w, http.StatusOK, response)
}
