package tianyuan

import (
	"context"
	"encoding/hex"
	"encoding/json"
	"io"
	"net/http"
	"time"

	"tyc-server/app/main/api/internal/service"
	"tyc-server/app/main/api/internal/svc"
	"tyc-server/app/main/model"
	"tyc-server/common/xerr"
	"tyc-server/pkg/lzkit/crypto"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
)

// VehicleCallbackLogic 处理天远车辆类接口的异步回调
// 设计目标：
// - 按 order_no + api_id 找到对应的查询记录
// - 解密原有 query_data（[]APIResponseData），更新或追加当前 api_id 的结果
// - 再次加密写回 query.query_data，必要时将 query_state 从 pending 更新为 success
type VehicleCallbackLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewVehicleCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VehicleCallbackLogic {
	return &VehicleCallbackLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// 与 paySuccessNotify 中一致：仅通过异步回调回写结果的车辆接口
var asyncVehicleApiIDs = map[string]bool{
	"QCXG1U4U": true, "QCXG3Y6B": true, "QCXG3Z3L": true, "QCXGP00W": true,
}

// allAsyncVehicleReceived 判断 apiList 中所有“异步车辆接口”是否均已收到回调（Success 为 true）
func allAsyncVehicleReceived(apiList []service.APIResponseData) bool {
	for _, item := range apiList {
		if asyncVehicleApiIDs[item.ApiID] && !item.Success {
			return false
		}
	}
	return true
}

// Handle 入口：直接接收原始 *http.Request，方便读取 query / body
func (l *VehicleCallbackLogic) Handle(r *http.Request) error {
	apiID := r.URL.Query().Get("api_id")
	orderNo := r.URL.Query().Get("order_no")

	if apiID == "" || orderNo == "" {
		return errors.Wrapf(
			xerr.NewErrMsg("缺少 api_id 或 order_no"),
			"tianyuan vehicle callback, api_id=%s, order_no=%s", apiID, orderNo,
		)
	}

	l.Infof("tianyuan vehicle callback start, api_id=%s, order_no=%s", apiID, orderNo)

	bodyBytes, err := io.ReadAll(r.Body)
	if err != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "读取回调 Body 失败: %v", err)
	}
	l.Infof("tianyuan vehicle callback body received, api_id=%s, order_no=%s, body_len=%d", apiID, orderNo, len(bodyBytes))

	// 回调包裹格式通常为 { code:0, msg:\"成功\", order_id:\"...\", data:{...} }，
	// 这里只把 data 字段提取出来存到 QueryData 里，便于前端直接渲染。
	type callbackWrapper struct {
		Code    json.RawMessage `json:"code"`
		Msg     json.RawMessage `json:"msg"`
		OrderID json.RawMessage `json:"order_id"`
		Data    json.RawMessage `json:"data"`
		Extra   map[string]any  `json:"-"` // 预留
	}
	var wrapper callbackWrapper
	payload := bodyBytes
	if len(bodyBytes) > 0 {
		if err := json.Unmarshal(bodyBytes, &wrapper); err != nil {
			l.Errorf("tianyuan vehicle callback unmarshal body failed, api_id=%s, order_no=%s, err=%v", apiID, orderNo, err)
		} else if len(wrapper.Data) > 0 {
			payload = wrapper.Data
			l.Infof("tianyuan vehicle callback extracted data field, api_id=%s, order_no=%s, data_len=%d", apiID, orderNo, len(payload))
		}
	}

	// 1. 根据订单号找到订单
	order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, orderNo)
	if err != nil {
		if err == model.ErrNotFound {
			return errors.Wrapf(xerr.NewErrMsg("未找到订单"), "order_no=%s", orderNo)
		}
		return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询订单失败, order_no=%s, err=%v", orderNo, err)
	}

	// 2. 根据订单ID找到对应查询记录
	query, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id)
	if err != nil {
		if err == model.ErrNotFound {
			return errors.Wrapf(xerr.NewErrMsg("未找到查询记录"), "order_no=%s, order_id=%d", orderNo, order.Id)
		}
		return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询 query 记录失败, order_id=%d, err=%v", order.Id, err)
	}

	// 3. 获取加密密钥
	secretKey := l.svcCtx.Config.Encrypt.SecretKey
	key, decodeErr := hex.DecodeString(secretKey)
	if decodeErr != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解析 AES 密钥失败: %v", decodeErr)
	}
	// 4. 解密 query_data，反序列化为 []APIResponseData
	var apiList []service.APIResponseData
	if query.QueryData.Valid && query.QueryData.String != "" {
		decrypted, decErr := crypto.AesDecrypt(query.QueryData.String, key)
		if decErr != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解密 query_data 失败: %v", decErr)
		}
		if len(decrypted) > 0 {
			if err := json.Unmarshal(decrypted, &apiList); err != nil {
				return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解析 query_data 为 APIResponseData 列表失败: %v", err)
			}
		}
	}

	// 5. 更新或追加当前 api_id 的结果
	nowStr := time.Now().Format("2006-01-02 15:04:05")
	updated := false
	for i := range apiList {
		if apiList[i].ApiID == apiID {
			apiList[i].Data = json.RawMessage(payload)
			apiList[i].Success = true
			apiList[i].Timestamp = nowStr
			apiList[i].Error = ""
			updated = true
			break
		}
	}
	if !updated {
		apiList = append(apiList, service.APIResponseData{
			ApiID:     apiID,
			Data:      json.RawMessage(payload),
			Success:   true,
			Timestamp: nowStr,
		})
	}

	// 6. 重新序列化并加密，写回查询记录
	merged, err := json.Marshal(apiList)
	if err != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "序列化合并后的 query_data 失败: %v", err)
	}
	enc, encErr := crypto.AesEncrypt(merged, key)
	if encErr != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密合并后的 query_data 失败: %v", encErr)
	}

	query.QueryData.String = enc
	query.QueryData.Valid = true
	// 仅当所有异步车辆接口均已有回调结果时，才将 pending 置为 success，并触发代理结算
	wasPending := query.QueryState == "pending"
	didSetSuccess := wasPending && allAsyncVehicleReceived(apiList)
	if didSetSuccess {
		query.QueryState = "success"
	}

	if err := l.svcCtx.QueryModel.UpdateWithVersion(l.ctx, nil, query); err != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新查询记录失败, query_id=%d, err=%v", query.Id, err)
	}

	if didSetSuccess {
		if agentErr := l.svcCtx.AgentService.AgentProcess(l.ctx, order); agentErr != nil {
			l.Errorf("tianyuan vehicle callback, AgentProcess failed, order_no=%s, err=%v", orderNo, agentErr)
			// 不因代理处理失败而整体失败，回调已成功落库
		}
	}

	l.Infof("tianyuan vehicle callback handled, order_no=%s, api_id=%s, query_id=%d", orderNo, apiID, query.Id)
	return nil
}
