package admin

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

	"bindbox-game/internal/code"
	"bindbox-game/internal/pkg/core"
	"bindbox-game/internal/pkg/validation"
	"bindbox-game/internal/repository/mysql/model"
)

type listShippingOrdersRequest struct {
	Page      int    `form:"page"`
	PageSize  int    `form:"page_size"`
	Status    *int32 `form:"status"` // 1待发货 2已发货 3已签收 4异常
	UserID    *int64 `form:"user_id"`
	BatchNo   string `form:"batch_no"`
	ExpressNo string `form:"express_no"`
	StartDate string `form:"start_date"`
	EndDate   string `form:"end_date"`
}

type ShippingOrderGroup struct {
	GroupKey     string     `json:"group_key"`     // 分组键（用于批量操作）
	BatchNo      string     `json:"batch_no"`      // 批次号
	ExpressCode  string     `json:"express_code"`  // 快递公司编码
	ExpressNo    string     `json:"express_no"`    // 运单号
	Status       int32      `json:"status"`        // 状态（取最大值）
	Count        int64      `json:"count"`         // 商品数量
	TotalPrice   int64      `json:"total_price"`   // 总价格
	UserID       int64      `json:"user_id"`       // 用户ID
	UserNickname string     `json:"user_nickname"` // 用户昵称
	AddressID    int64      `json:"address_id"`    // 地址ID
	AddressInfo  string     `json:"address_info"`  // 地址信息
	ShippedAt    *time.Time `json:"shipped_at,omitempty"`
	ReceivedAt   *time.Time `json:"received_at,omitempty"`
	CreatedAt    time.Time  `json:"created_at"`
	RecordIDs    []int64    `json:"record_ids"`    // 发货记录ID列表
	InventoryIDs []int64    `json:"inventory_ids"` // 资产ID列表
	ProductIDs   []int64    `json:"product_ids"`   // 商品ID列表
	Products     []struct {
		ID    int64  `json:"id"`
		Name  string `json:"name"`
		Image string `json:"image"`
		Price int64  `json:"price"`
	} `json:"products"` // 商品详情列表
}

type listShippingOrdersResponse struct {
	Page     int                   `json:"page"`
	PageSize int                   `json:"page_size"`
	Total    int64                 `json:"total"`
	List     []*ShippingOrderGroup `json:"list"`
}

// ListShippingOrders 发货订单列表（按批次号/运单号聚合）
// @Summary 发货订单列表
// @Description 按批次号或运单号聚合显示发货记录，支持筛选状态、用户、时间等
// @Tags 管理端.发货管理
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param page query int false "页码，默认1"
// @Param page_size query int false "每页数量，最多100，默认20"
// @Param status query int false "状态：1待发货 2已发货 3已签收 4异常"
// @Param user_id query int false "用户ID"
// @Param batch_no query string false "批次号"
// @Param express_no query string false "运单号"
// @Param start_date query string false "开始日期 2006-01-02"
// @Param end_date query string false "结束日期 2006-01-02"
// @Success 200 {object} listShippingOrdersResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/shipping/orders [get]
func (h *handler) ListShippingOrders() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(listShippingOrdersRequest)
		rsp := new(listShippingOrdersResponse)
		if err := ctx.ShouldBindForm(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}
		if req.Page <= 0 {
			req.Page = 1
		}
		if req.PageSize <= 0 {
			req.PageSize = 20
		}
		if req.PageSize > 100 {
			req.PageSize = 100
		}

		// 构建查询
		q := h.readDB.ShippingRecords.WithContext(ctx.RequestContext()).ReadDB()
		if req.Status != nil {
			q = q.Where(h.readDB.ShippingRecords.Status.Eq(*req.Status))
		}
		if req.UserID != nil {
			q = q.Where(h.readDB.ShippingRecords.UserID.Eq(*req.UserID))
		}
		if req.BatchNo != "" {
			q = q.Where(h.readDB.ShippingRecords.BatchNo.Eq(req.BatchNo))
		}
		if req.ExpressNo != "" {
			q = q.Where(h.readDB.ShippingRecords.ExpressNo.Eq(req.ExpressNo))
		}
		if req.StartDate != "" {
			if t, err := time.Parse("2006-01-02", req.StartDate); err == nil {
				q = q.Where(h.readDB.ShippingRecords.CreatedAt.Gte(t))
			}
		}
		if req.EndDate != "" {
			if t, err := time.Parse("2006-01-02", req.EndDate); err == nil {
				t = t.Add(24 * time.Hour).Add(-time.Second)
				q = q.Where(h.readDB.ShippingRecords.CreatedAt.Lte(t))
			}
		}

		// 获取所有符合条件的记录
		rows, err := q.Order(h.readDB.ShippingRecords.CreatedAt.Desc(), h.readDB.ShippingRecords.ID.Desc()).Find()
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, 30001, err.Error()))
			return
		}

		// 按批次号/运单号分组
		type acc struct {
			status     int32
			totalPrice int64
			shippedAt  *time.Time
			receivedAt *time.Time
			createdAt  time.Time
			userID     int64
			addressID  int64
			recordIDs  []int64
			inv        []int64
			pid        []int64
		}
		m := make(map[string]*acc)
		meta := make(map[string]struct{ code, no, batch string })
		order := make([]string, 0) // 保持顺序

		for _, r := range rows {
			// 分组优先级：运单号 > 批次号 > 记录ID
			key := ""
			if r.ExpressNo != "" {
				key = "E|" + r.ExpressCode + "|" + r.ExpressNo
			} else if r.BatchNo != "" {
				key = "B|" + r.BatchNo
			} else {
				key = "_" + strconv.FormatInt(r.ID, 10)
			}

			if _, ok := m[key]; !ok {
				m[key] = &acc{
					createdAt: r.CreatedAt,
					userID:    r.UserID,
					addressID: r.AddressID,
				}
				meta[key] = struct{ code, no, batch string }{r.ExpressCode, r.ExpressNo, r.BatchNo}
				order = append(order, key)
			}
			a := m[key]
			if a.status == 0 || r.Status >= a.status {
				a.status = r.Status
			}
			a.totalPrice += r.Price
			if !r.ShippedAt.IsZero() {
				t := r.ShippedAt
				a.shippedAt = &t
			}
			if !r.ReceivedAt.IsZero() {
				t := r.ReceivedAt
				a.receivedAt = &t
			}
			a.recordIDs = append(a.recordIDs, r.ID)
			a.inv = append(a.inv, r.InventoryID)
			if r.ProductID > 0 {
				a.pid = append(a.pid, r.ProductID)
			}
		}

		// 分页处理
		total := int64(len(order))
		start := (req.Page - 1) * req.PageSize
		end := start + req.PageSize
		if start >= len(order) {
			start = len(order)
		}
		if end > len(order) {
			end = len(order)
		}
		pageKeys := order[start:end]

		// 构建返回结果
		items := make([]*ShippingOrderGroup, 0, len(pageKeys))
		for _, k := range pageKeys {
			a := m[k]
			md := meta[k]

			// 获取用户信息
			var userNickname string
			if a.userID > 0 {
				if user, _ := h.readDB.Users.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Users.ID.Eq(a.userID)).First(); user != nil {
					userNickname = user.Nickname
				}
			}

			// 获取地址信息
			var addressInfo string
			if a.addressID > 0 {
				if addr, _ := h.readDB.UserAddresses.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.UserAddresses.ID.Eq(a.addressID)).First(); addr != nil {
					addressInfo = addr.Province + addr.City + addr.District + addr.Address + " " + addr.Name + " " + addr.Mobile
				}
			}

			// 获取商品信息（去重）
			pidSet := make(map[int64]struct{})
			for _, pid := range a.pid {
				pidSet[pid] = struct{}{}
			}
			var products []struct {
				ID    int64  `json:"id"`
				Name  string `json:"name"`
				Image string `json:"image"`
				Price int64  `json:"price"`
			}
			for pid := range pidSet {
				if prod, _ := h.readDB.Products.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Products.ID.Eq(pid)).First(); prod != nil {
					products = append(products, struct {
						ID    int64  `json:"id"`
						Name  string `json:"name"`
						Image string `json:"image"`
						Price int64  `json:"price"`
					}{
						ID:    prod.ID,
						Name:  prod.Name,
						Image: prod.ImagesJSON, // 商品图片JSON
						Price: prod.Price,
					})
				}
			}

			items = append(items, &ShippingOrderGroup{
				GroupKey:     k,
				BatchNo:      md.batch,
				ExpressCode:  md.code,
				ExpressNo:    md.no,
				Status:       a.status,
				Count:        int64(len(a.inv)),
				TotalPrice:   a.totalPrice,
				UserID:       a.userID,
				UserNickname: userNickname,
				AddressID:    a.addressID,
				AddressInfo:  addressInfo,
				ShippedAt:    a.shippedAt,
				ReceivedAt:   a.receivedAt,
				CreatedAt:    a.createdAt,
				RecordIDs:    a.recordIDs,
				InventoryIDs: a.inv,
				ProductIDs:   a.pid,
				Products:     products,
			})
		}

		rsp.Page = req.Page
		rsp.PageSize = req.PageSize
		rsp.Total = total
		rsp.List = items
		ctx.Payload(rsp)
	}
}

type updateShippingRequest struct {
	RecordIDs   []int64 `json:"record_ids"`   // 发货记录ID列表
	ExpressCode string  `json:"express_code"` // 快递公司编码
	ExpressNo   string  `json:"express_no"`   // 运单号
	Status      *int32  `json:"status"`       // 状态
}

type updateShippingResponse struct {
	Success      bool  `json:"success"`
	UpdatedCount int64 `json:"updated_count"`
}

// UpdateShippingBatch 批量更新发货信息
// @Summary 批量更新发货信息
// @Description 为多条发货记录填写运单号或更新状态
// @Tags 管理端.发货管理
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param RequestBody body updateShippingRequest true "请求参数"
// @Success 200 {object} updateShippingResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/shipping/orders/batch [put]
func (h *handler) UpdateShippingBatch() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(updateShippingRequest)
		rsp := new(updateShippingResponse)
		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}
		if len(req.RecordIDs) == 0 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "record_ids不能为空"))
			return
		}
		if len(req.RecordIDs) > 100 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "单次最多处理100条记录"))
			return
		}

		updates := make(map[string]any)
		if req.ExpressCode != "" {
			updates["express_code"] = req.ExpressCode
		}
		if req.ExpressNo != "" {
			updates["express_no"] = req.ExpressNo
		}
		if req.Status != nil {
			updates["status"] = *req.Status
			if *req.Status == 2 {
				updates["shipped_at"] = time.Now()
			} else if *req.Status == 3 {
				updates["received_at"] = time.Now()
			}
		}
		updates["updated_at"] = time.Now()

		result, err := h.writeDB.ShippingRecords.WithContext(ctx.RequestContext()).
			Where(h.writeDB.ShippingRecords.ID.In(req.RecordIDs...)).
			Updates(updates)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, 30002, err.Error()))
			return
		}

		rsp.Success = true
		rsp.UpdatedCount = result.RowsAffected
		ctx.Payload(rsp)
	}
}

// GetShippingOrderDetail 获取发货订单详情
// @Summary 获取发货订单详情
// @Description 根据发货记录ID获取详情
// @Tags 管理端.发货管理
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param id path int true "发货记录ID"
// @Success 200 {object} model.ShippingRecords
// @Failure 400 {object} code.Failure
// @Router /api/admin/shipping/orders/{id} [get]
func (h *handler) GetShippingOrderDetail() core.HandlerFunc {
	return func(ctx core.Context) {
		idStr := ctx.Param("id")
		id, err := strconv.ParseInt(idStr, 10, 64)
		if err != nil || id <= 0 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的ID"))
			return
		}

		record, err := h.readDB.ShippingRecords.WithContext(ctx.RequestContext()).ReadDB().
			Where(h.readDB.ShippingRecords.ID.Eq(id)).First()
		if err != nil || record == nil {
			ctx.AbortWithError(core.Error(http.StatusNotFound, 30003, "发货记录不存在"))
			return
		}

		// 获取关联信息
		type detailResponse struct {
			*model.ShippingRecords
			User    *model.Users         `json:"user"`
			Address *model.UserAddresses `json:"address"`
			Product *model.Products      `json:"product"`
		}

		rsp := &detailResponse{ShippingRecords: record}
		if record.UserID > 0 {
			rsp.User, _ = h.readDB.Users.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Users.ID.Eq(record.UserID)).First()
		}
		if record.AddressID > 0 {
			rsp.Address, _ = h.readDB.UserAddresses.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.UserAddresses.ID.Eq(record.AddressID)).First()
		}
		if record.ProductID > 0 {
			rsp.Product, _ = h.readDB.Products.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Products.ID.Eq(record.ProductID)).First()
		}

		ctx.Payload(rsp)
	}
}
