// Package carriercallback 提供运营商回调协议到内部观测模型的适配能力。
package carriercallback

import (
	"bytes"
	"context"
	"encoding/xml"
	"strings"

	"gorm.io/gorm"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	pkgvalidator "github.com/break/junhong_cmp_fiber/pkg/validator"
)

const (
	// CTCCRealnameActionVerified 表示电信实名补录已完成。
	CTCCRealnameActionVerified = "verified"
	// CTCCRealnameActionIgnored 表示报文合法但无需改变实名事实。
	CTCCRealnameActionIgnored = "ignored"
)

// CTCCRealnameTranslation 是电信 XML 回调的受控内部语义。
type CTCCRealnameTranslation struct {
	ICCID              string
	AcceptMessage      string
	ResultMessage      string
	GroupTransactionID string
	Action             string
}

type ctccContractRoot struct {
	XMLName            xml.Name `xml:"ContractRoot"`
	ICCID              string   `xml:"ICCID"`
	AcceptMessage      string   `xml:"ACCEPTMSG"`
	ResultMessage      string   `xml:"RESULTMSG"`
	GroupTransactionID string   `xml:"GROUP_TRANSACTIONID"`
}

// CTCCRealnameTranslator 解析已知电信 XML 协议字段。
type CTCCRealnameTranslator struct{}

// NewCTCCRealnameTranslator 创建电信实名回调 Translator。
func NewCTCCRealnameTranslator() *CTCCRealnameTranslator {
	return &CTCCRealnameTranslator{}
}

// Translate 将 XML 转为受控语义；未知业务结果保留为 ignored。
func (t *CTCCRealnameTranslator) Translate(body []byte) (CTCCRealnameTranslation, error) {
	var result CTCCRealnameTranslation
	if len(bytes.TrimSpace(body)) == 0 {
		return result, errors.New(errors.CodeInvalidParam, "电信实名回调报文为空")
	}
	var payload ctccContractRoot
	if err := xml.Unmarshal(body, &payload); err != nil {
		return result, errors.Wrap(errors.CodeInvalidParam, err, "电信实名回调 XML 解析失败")
	}
	result.ICCID = strings.TrimSpace(payload.ICCID)
	result.AcceptMessage = strings.TrimSpace(payload.AcceptMessage)
	result.ResultMessage = strings.TrimSpace(payload.ResultMessage)
	result.GroupTransactionID = strings.TrimSpace(payload.GroupTransactionID)
	if err := t.validateICCID(result.ICCID); err != nil {
		return result, err
	}
	result.Action = CTCCRealnameActionIgnored
	if result.ResultMessage == "成功" && strings.Contains(result.AcceptMessage, "已完成实名信息补录") {
		result.Action = CTCCRealnameActionVerified
	}
	return result, nil
}

func (t *CTCCRealnameTranslator) validateICCID(iccid string) error {
	if result := pkgvalidator.ValidateICCIDWithoutCarrier(iccid); !result.Valid {
		return errors.New(errors.CodeInvalidParam, "电信实名回调 ICCID 无效")
	}
	return nil
}

// CTCCCardResolver 使用系统级精确列查询定位电信回调卡。
type CTCCCardResolver struct {
	db *gorm.DB
}

// NewCTCCCardResolver 创建电信回调卡定位器。
func NewCTCCCardResolver(db *gorm.DB) *CTCCCardResolver {
	return &CTCCCardResolver{db: db}
}

// Resolve 按 ICCID 长度选择唯一列，禁止跨列降级。
func (r *CTCCCardResolver) Resolve(ctx context.Context, iccid string) ([]*model.IotCard, error) {
	if r == nil || r.db == nil {
		return nil, errors.New(errors.CodeInternalError, "电信实名回调卡查询能力未配置")
	}
	column := "iccid_19"
	if len(iccid) == 20 {
		column = "iccid_20"
	}
	var cards []*model.IotCard
	if err := r.db.WithContext(ctx).
		Where(column+" = ? AND deleted_at IS NULL", iccid).
		Limit(2).
		Find(&cards).Error; err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询电信实名回调卡失败")
	}
	return cards, nil
}
