package app

import (
	"context"
	"strconv"
	"strings"
	"time"

	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"

	"github.com/break/junhong_cmp_fiber/internal/middleware"
	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/response"
)

type ClientRechargeOrderHandler struct {
	rechargeOrderStore *postgres.RechargeOrderStore
	paymentStore       *postgres.PaymentStore
	logger             *zap.Logger
}

func NewClientRechargeOrderHandler(
	rechargeOrderStore *postgres.RechargeOrderStore,
	paymentStore *postgres.PaymentStore,
	logger *zap.Logger,
) *ClientRechargeOrderHandler {
	return &ClientRechargeOrderHandler{
		rechargeOrderStore: rechargeOrderStore,
		paymentStore:       paymentStore,
		logger:             logger,
	}
}

func (h *ClientRechargeOrderHandler) ListRechargeOrders(c *fiber.Ctx) error {
	var req dto.ClientRechargeOrderListRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}

	if req.Page < 1 {
		req.Page = 1
	}
	if req.PageSize < 1 {
		req.PageSize = constants.DefaultPageSize
	}
	if req.PageSize > constants.MaxPageSize {
		req.PageSize = constants.MaxPageSize
	}

	customerID, ok := middleware.GetCustomerID(c)
	if !ok || customerID == 0 {
		return errors.New(errors.CodeUnauthorized)
	}

	skipCtx := context.WithValue(c.UserContext(), constants.ContextKeySubordinateShopIDs, []uint{})

	params := &postgres.ListRechargeOrderParams{
		Page:     req.Page,
		PageSize: req.PageSize,
		UserID:   &customerID,
	}
	if assetType, assetID, ok := middleware.GetCurrentAsset(c); ok {
		params.ResourceType = &assetType
		params.ResourceID = &assetID
	}
	if req.Status > 0 {
		params.Status = &req.Status
	}

	orders, total, err := h.rechargeOrderStore.List(skipCtx, params)
	if err != nil {
		return errors.Wrap(errors.CodeDatabaseError, err, "查询充值订单失败")
	}

	items := make([]dto.ClientRechargeOrderListItem, 0, len(orders))
	for _, order := range orders {
		if order == nil {
			continue
		}
		items = append(items, dto.ClientRechargeOrderListItem{
			RechargeOrderID:    order.ID,
			RechargeOrderNo:    order.RechargeOrderNo,
			Amount:             order.Amount,
			Status:             order.Status,
			StatusName:         getRechargeOrderStatusName(order.Status),
			AutoPurchaseStatus: order.AutoPurchaseStatus,
			CreatedAt:          order.CreatedAt.Format(time.RFC3339),
		})
	}

	return response.SuccessWithPagination(c, items, total, req.Page, req.PageSize)
}

func (h *ClientRechargeOrderHandler) GetRechargeOrderDetail(c *fiber.Ctx) error {
	idStr := c.Params("id")
	if idStr == "" {
		return errors.New(errors.CodeInvalidParam)
	}

	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam)
	}

	customerID, ok := middleware.GetCustomerID(c)
	if !ok || customerID == 0 {
		return errors.New(errors.CodeUnauthorized)
	}

	skipCtx := context.WithValue(c.UserContext(), constants.ContextKeySubordinateShopIDs, []uint{})

	order, err := h.rechargeOrderStore.GetByID(skipCtx, uint(id))
	if err != nil {
		if strings.Contains(err.Error(), "record not found") {
			return errors.New(errors.CodeNotFound, "充值订单不存在")
		}
		return errors.Wrap(errors.CodeDatabaseError, err, "查询充值订单失败")
	}

	if order.UserID != customerID {
		return errors.New(errors.CodeForbidden, "无权访问该充值订单")
	}

	payments, _ := h.paymentStore.ListByOrderID(skipCtx, order.ID, model.PaymentOrderTypeRecharge)

	var paymentDetails []dto.ClientRechargeOrderPaymentDetail
	for _, p := range payments {
		if p == nil {
			continue
		}
		paymentDetails = append(paymentDetails, dto.ClientRechargeOrderPaymentDetail{
			PaymentID:         p.ID,
			PaymentNo:         p.PaymentNo,
			PaymentMethod:     p.PaymentMethod,
			Amount:            p.Amount,
			Status:            p.Status,
			StatusName:        getPaymentStatusName(p.Status),
			ThirdPartyTradeNo: p.ThirdPartyTradeNo,
			PaidAt:            formatTimePtr(p.PaidAt),
			CreatedAt:         p.CreatedAt.Format(time.RFC3339),
		})
	}

	resp := &dto.ClientRechargeOrderDetail{
		RechargeOrderID:    order.ID,
		RechargeOrderNo:    order.RechargeOrderNo,
		Amount:             order.Amount,
		Status:             order.Status,
		StatusName:         getRechargeOrderStatusName(order.Status),
		AutoPurchaseStatus: order.AutoPurchaseStatus,
		LinkedPackageIDs:   order.LinkedPackageIDs,
		CreatedAt:          order.CreatedAt.Format(time.RFC3339),
		PaidAt:             formatTimePtr(order.PaidAt),
		Payments:           paymentDetails,
	}

	return response.Success(c, resp)
}

func getRechargeOrderStatusName(status int) string {
	switch status {
	case model.RechargeOrderStatusPending:
		return "待支付"
	case model.RechargeOrderStatusPaid:
		return "已支付"
	case model.RechargeOrderStatusClosed:
		return "已关闭"
	case model.RechargeOrderStatusRefunded:
		return "已退款"
	default:
		return "未知"
	}
}

func getPaymentStatusName(status int) string {
	switch status {
	case model.PaymentRecordStatusPending:
		return "待支付"
	case model.PaymentRecordStatusPaid:
		return "已支付"
	case model.PaymentRecordStatusFailed:
		return "已失败"
	case model.PaymentRecordStatusRefunded:
		return "已退款"
	default:
		return "未知"
	}
}

func formatTimePtr(t *time.Time) string {
	if t == nil {
		return ""
	}
	return t.Format(time.RFC3339)
}
