package paymentconfig

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

	"hfb_sys/backend/internal/middleware"
	"hfb_sys/backend/pkg/response"

	"github.com/gin-gonic/gin"
)

type Handler struct {
	service *Service
}

func NewHandler(service *Service) *Handler {
	return &Handler{service: service}
}

// List 获取支付配置列表
// @Summary 获取支付配置列表
// @Tags 管理后台-支付配置
// @Param provider query string false "支付服务商"
// @Param pay_way query string false "支付方式"
// @Param status query string false "状态"
// @Param environment query string false "环境"
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} response.Response{data=ListResponse}
// @Router /admin/payment-configs [get]
func (h *Handler) List(c *gin.Context) {
	var query ListQuery
	if err := c.ShouldBindQuery(&query); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	resp, err := h.service.List(c.Request.Context(), query)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "internal_error", "查询失败")
		return
	}

	response.OK(c, resp)
}

// Get 获取单个支付配置
// @Summary 获取单个支付配置
// @Tags 管理后台-支付配置
// @Param id path int true "配置ID"
// @Param include_secret query bool false "是否包含密钥"
// @Success 200 {object} response.Response{data=ConfigDTO}
// @Router /admin/payment-configs/{id} [get]
func (h *Handler) Get(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "无效的ID")
		return
	}

	includeSecret := c.Query("include_secret") == "true"
	var actorID uint64
	if includeSecret {
		var ok bool
		actorID, ok = currentAdminID(c)
		if !ok {
			response.Unauthorized(c, "未授权")
			return
		}
	}

	config, err := h.service.Get(c.Request.Context(), id, includeSecret, actorID, auditMeta(c))
	if err == ErrConfigNotFound {
		response.NotFound(c, "配置不存在")
		return
	}
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "internal_error", "查询失败")
		return
	}

	response.OK(c, config)
}

// ExportBackup 导出支付配置备份
// @Summary 导出支付配置备份
// @Tags 管理后台-支付配置
// @Success 200 {file} file "支付配置备份 JSON"
// @Router /admin/payment-configs/export [get]
func (h *Handler) ExportBackup(c *gin.Context) {
	adminID, ok := currentAdminID(c)
	if !ok {
		response.Unauthorized(c, "未授权")
		return
	}

	backup, err := h.service.ExportBackup(c.Request.Context(), adminID, auditMeta(c))
	if err == ErrDecryptionFailed {
		response.Error(c, http.StatusInternalServerError, "decrypt_failed", "密钥解密失败")
		return
	}
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "internal_error", "导出失败")
		return
	}

	data, err := json.MarshalIndent(backup, "", "  ")
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "internal_error", "导出失败")
		return
	}

	filename := "payment-config-backup-" + time.Now().Format("20060102-150405") + ".json"
	contentType := "application/json; charset=utf-8"
	c.Header("Content-Disposition", `attachment; filename="`+filename+`"`)
	c.Data(http.StatusOK, contentType, data)
}

// ImportBackup 导入支付配置备份
// @Summary 导入支付配置备份
// @Tags 管理后台-支付配置
// @Param body body ExportBackup true "支付配置备份 JSON"
// @Success 200 {object} response.Response{data=ImportBackupResult}
// @Router /admin/payment-configs/import [post]
func (h *Handler) ImportBackup(c *gin.Context) {
	adminID, ok := currentAdminID(c)
	if !ok {
		response.Unauthorized(c, "未授权")
		return
	}

	var backup ExportBackup
	if err := c.ShouldBindJSON(&backup); err != nil {
		response.BadRequest(c, "备份文件格式错误")
		return
	}

	result, err := h.service.ImportBackup(c.Request.Context(), backup, adminID, auditMeta(c))
	if err == ErrInvalidBackup || err == ErrEmptyBackup || err == ErrInvalidProvider ||
		err == ErrNameRequired || err == ErrMerchantIDRequired || err == ErrGatewayURLRequired ||
		err == ErrSignKeyRequired || err == ErrNotifyKeyRequired || err == ErrNotifyURLRequired ||
		err == ErrInvalidSignType || err == ErrInvalidStatus || err == ErrInvalidPayWay || err == ErrAppIDRequired ||
		err == ErrSerialNoRequired || err == ErrTermNoRequired {
		response.BadRequest(c, err.Error())
		return
	}
	if err == ErrEncryptionFailed {
		response.Error(c, http.StatusInternalServerError, "encrypt_failed", "密钥加密失败")
		return
	}
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "internal_error", "导入失败")
		return
	}

	response.OK(c, result)
}

// Create 创建支付配置
// @Summary 创建支付配置
// @Tags 管理后台-支付配置
// @Param body body CreateRequest true "创建请求"
// @Success 200 {object} response.Response{data=ConfigDTO}
// @Router /admin/payment-configs [post]
func (h *Handler) Create(c *gin.Context) {
	adminID, ok := currentAdminID(c)
	if !ok {
		response.Unauthorized(c, "未授权")
		return
	}

	var req CreateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误: "+err.Error())
		return
	}

	config, err := h.service.Create(c.Request.Context(), req, adminID, auditMeta(c))
	if err == ErrNameRequired || err == ErrMerchantIDRequired || err == ErrGatewayURLRequired ||
		err == ErrSignKeyRequired || err == ErrNotifyKeyRequired || err == ErrInvalidProvider ||
		err == ErrNotifyURLRequired || err == ErrInvalidSignType || err == ErrInvalidPayWay || err == ErrAppIDRequired ||
		err == ErrInvalidStatus || err == ErrSerialNoRequired || err == ErrTermNoRequired {
		response.BadRequest(c, err.Error())
		return
	}
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "internal_error", "创建失败")
		return
	}

	response.OK(c, config)
}

// Update 更新支付配置
// @Summary 更新支付配置
// @Tags 管理后台-支付配置
// @Param id path int true "配置ID"
// @Param body body UpdateRequest true "更新请求"
// @Success 200 {object} response.Response{data=ConfigDTO}
// @Router /admin/payment-configs/{id} [put]
func (h *Handler) Update(c *gin.Context) {
	adminID, ok := currentAdminID(c)
	if !ok {
		response.Unauthorized(c, "未授权")
		return
	}

	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "无效的ID")
		return
	}

	var req UpdateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误: "+err.Error())
		return
	}

	config, err := h.service.Update(c.Request.Context(), id, req, adminID, auditMeta(c))
	if err == ErrConfigNotFound {
		response.NotFound(c, "配置不存在")
		return
	}
	if err == ErrInvalidSignType || err == ErrInvalidStatus || err == ErrInvalidPayWay || err == ErrNotifyURLRequired {
		response.BadRequest(c, err.Error())
		return
	}
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "internal_error", "更新失败")
		return
	}

	response.OK(c, config)
}

// Delete 删除支付配置
// @Summary 删除支付配置
// @Tags 管理后台-支付配置
// @Param id path int true "配置ID"
// @Success 200 {object} response.Response
// @Router /admin/payment-configs/{id} [delete]
func (h *Handler) Delete(c *gin.Context) {
	adminID, ok := currentAdminID(c)
	if !ok {
		response.Unauthorized(c, "未授权")
		return
	}

	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "无效的ID")
		return
	}

	err = h.service.Delete(c.Request.Context(), id, adminID, auditMeta(c))
	if err == ErrConfigNotFound {
		response.NotFound(c, "配置不存在")
		return
	}
	if err == ErrCannotDeleteInUse {
		response.BadRequest(c, "配置正在使用中，无法删除")
		return
	}
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "internal_error", "删除失败")
		return
	}

	response.OK(c, gin.H{"message": "删除成功"})
}

func currentAdminID(c *gin.Context) (uint64, bool) {
	val, exists := c.Get(middleware.ContextAdminID)
	if !exists {
		return 0, false
	}
	id, ok := val.(uint64)
	return id, ok
}

func auditMeta(c *gin.Context) AuditMeta {
	return AuditMeta{
		IP:        c.ClientIP(),
		UserAgent: c.Request.UserAgent(),
	}
}
