package brc

import (
	"errors"
	"ffie-admin/server/global"
	"ffie-admin/server/model/brc"
	brcReq "ffie-admin/server/model/brc/request"
	"ffie-admin/server/model/common/request"
	"ffie-admin/server/model/common/response"
	"ffie-admin/server/service"
	"ffie-admin/server/utils"
	"fmt"

	"github.com/btcsuite/btcd/btcutil"
	"github.com/btcsuite/btcd/btcutil/psbt"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcd/wire"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type BrcLockApi struct {
}

var brcLockService = service.ServiceGroupApp.BrcServiceGroup.BrcLockService

// CreateBrcLock 创建BrcLock
// @Tags BrcLock
// @Summary 创建BrcLock
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body brc.BrcLock true "创建BrcLock"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /brcLock/createBrcLock [post]
func (brcLockApi *BrcLockApi) CreateBrcLock(c *gin.Context) {
	var brcLock brc.BrcLock
	err := c.ShouldBindJSON(&brcLock)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	verify := utils.Rules{
		"Period":    {utils.NotEmpty()},
		"Amount":    {utils.NotEmpty()},
		"StartTime": {utils.NotEmpty()},
		"Addr":      {utils.NotEmpty()},
		"LockAddr":  {utils.NotEmpty()},
	}
	if err := utils.Verify(brcLock, verify); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := brcLockService.CreateBrcLock(brcLock); err != nil {
		global.GVA_LOG.Error("创建失败!", zap.Error(err))
		response.FailWithMessage("创建失败", c)
	} else {
		response.OkWithMessage("创建成功", c)
	}
}

// DeleteBrcLock 删除BrcLock
// @Tags BrcLock
// @Summary 删除BrcLock
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body brc.BrcLock true "删除BrcLock"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /brcLock/deleteBrcLock [delete]
func (brcLockApi *BrcLockApi) DeleteBrcLock(c *gin.Context) {
	var brcLock brc.BrcLock
	err := c.ShouldBindJSON(&brcLock)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := brcLockService.DeleteBrcLock(brcLock); err != nil {
		global.GVA_LOG.Error("删除失败!", zap.Error(err))
		response.FailWithMessage("删除失败", c)
	} else {
		response.OkWithMessage("删除成功", c)
	}
}

// DeleteBrcLockByIds 批量删除BrcLock
// @Tags BrcLock
// @Summary 批量删除BrcLock
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.IdsReq true "批量删除BrcLock"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"批量删除成功"}"
// @Router /brcLock/deleteBrcLockByIds [delete]
func (brcLockApi *BrcLockApi) DeleteBrcLockByIds(c *gin.Context) {
	var IDS request.IdsReq
	err := c.ShouldBindJSON(&IDS)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := brcLockService.DeleteBrcLockByIds(IDS); err != nil {
		global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
		response.FailWithMessage("批量删除失败", c)
	} else {
		response.OkWithMessage("批量删除成功", c)
	}
}

// UpdateBrcLock 更新BrcLock
// @Tags BrcLock
// @Summary 更新BrcLock
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body brc.BrcLock true "更新BrcLock"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /brcLock/updateBrcLock [put]
func (brcLockApi *BrcLockApi) UpdateBrcLock(c *gin.Context) {
	var brcLock brc.BrcLock
	err := c.ShouldBindJSON(&brcLock)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	verify := utils.Rules{
		"Period":    {utils.NotEmpty()},
		"Amount":    {utils.NotEmpty()},
		"StartTime": {utils.NotEmpty()},
		"Addr":      {utils.NotEmpty()},
		"LockAddr":  {utils.NotEmpty()},
	}
	if err := utils.Verify(brcLock, verify); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := brcLockService.UpdateBrcLock(brcLock); err != nil {
		global.GVA_LOG.Error("更新失败!", zap.Error(err))
		response.FailWithMessage("更新失败", c)
	} else {
		response.OkWithMessage("更新成功", c)
	}
}

// UpdateLock 更新BrcLock
// @Tags BrcLock
// @Summary 更新BrcLock
// @accept application/json
// @Produce application/json
// @Param data body brc.BrcLock true "更新BrcLock"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /brcLock/updateLock [post]
func (brcLockApi *BrcLockApi) UpdateLock(c *gin.Context) {
	var brcLock brc.BrcLock
	err := c.ShouldBindJSON(&brcLock)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	verify := utils.Rules{
		"Status": {utils.NotEmpty()},
	}
	if err := utils.Verify(brcLock, verify); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if err := brcLockService.UpdateBrcLock(brcLock); err != nil {
		global.GVA_LOG.Error("更新失败!", zap.Error(err))
		response.FailWithMessage("更新失败", c)
	} else {
		response.OkWithMessage("更新成功", c)
	}
}

// FindBrcLock 用id查询BrcLock
// @Tags BrcLock
// @Summary 用id查询BrcLock
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query brc.BrcLock true "用id查询BrcLock"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /brcLock/findBrcLock [get]
func (brcLockApi *BrcLockApi) FindBrcLock(c *gin.Context) {
	var brcLock brc.BrcLock
	err := c.ShouldBindQuery(&brcLock)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if rebrcLock, err := brcLockService.GetBrcLock(brcLock.ID); err != nil {
		global.GVA_LOG.Error("查询失败!", zap.Error(err))
		response.FailWithMessage("查询失败", c)
	} else {
		response.OkWithData(gin.H{"rebrcLock": rebrcLock}, c)
	}
}

// GetBrcLockList 分页获取BrcLock列表
// @Tags BrcLock
// @Summary 分页获取BrcLock列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query brcReq.BrcLockSearch true "分页获取BrcLock列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /brcLock/getBrcLockList [get]
func (brcLockApi *BrcLockApi) GetBrcLockList(c *gin.Context) {
	var pageInfo brcReq.BrcLockSearch
	err := c.ShouldBindQuery(&pageInfo)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if list, total, err := brcLockService.GetBrcLockInfoList(pageInfo); err != nil {
		global.GVA_LOG.Error("获取失败!", zap.Error(err))
		response.FailWithMessage("获取失败", c)
	} else {
		response.OkWithDetailed(response.PageResult{
			List:     list,
			Total:    total,
			Page:     pageInfo.Page,
			PageSize: pageInfo.PageSize,
		}, "获取成功", c)
	}
}

// GetLockList 分页获取BrcLock列表
// @Tags BrcLock
// @Summary 分页获取BrcLock列表
// @accept application/json
// @Produce application/json
// @Param data query brcReq.BrcLockSearch true "分页获取BrcLock列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /brcLock/getLockList [get]
func (brcLockApi *BrcLockApi) GetLockList(c *gin.Context) {
	var pageInfo brcReq.BrcLockSearch
	err := c.ShouldBindQuery(&pageInfo)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if list, total, err := brcLockService.GetBrcLockInfoList(pageInfo); err != nil {
		global.GVA_LOG.Error("获取失败!", zap.Error(err))
		response.FailWithMessage("获取失败", c)
	} else {
		response.OkWithDetailed(response.PageResult{
			List:     list,
			Total:    total,
			Page:     pageInfo.Page,
			PageSize: pageInfo.PageSize,
		}, "获取成功", c)
	}
}

// CreateBrc20Tx 创建brx20交易
// @Tags BrcLock
// @Summary 创建brx20交易
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body brcReq.CreateBrx20TxReq true "创建brx20交易"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /brcLock/createBrc20Tx2 [post]
func (brcLockApi *BrcLockApi) CreateBrc20Tx(c *gin.Context) {
	var req brcReq.CreateBrx20TxReq
	err := c.ShouldBindJSON(&req)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	// 验证参数
	verify := utils.Rules{
		"Sender":   {utils.NotEmpty()},
		"Receiver": {utils.NotEmpty()},
		"Ticker":   {utils.NotEmpty()},
		"Amount":   {utils.NotEmpty()},
	}
	if err := utils.Verify(req, verify); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	psbtStr, err := BuildPSBT(req)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	response.OkWithData(psbtStr, c)
}

func BuildPSBT(params brcReq.CreateBrx20TxReq) (string, error) {
	// 1. 验证铭文UTXO有效性
	utxo, err := queryInscriptionUTXO(params.UtxoHash, params.UtxoIndex) // 需实现UTXO查询逻辑‌:ml-citation{ref="2,3" data="citationList"}
	if err != nil {
		return "", err
	}
	if !utxo {
		return "", errors.New("未找到未花费的UTXO")
	}
	// 2. 初始化PSBT
	packet, _ := psbt.New(nil, nil, 2, 0, nil)
	hash, _ := chainhash.NewHashFromStr(params.UtxoHash)
	packet.UnsignedTx.TxIn = []*wire.TxIn{{
		PreviousOutPoint: wire.OutPoint{
			Hash:  *hash,
			Index: uint32(params.UtxoIndex),
		},
	}}

	// 3. 设置输出（铭文转移+找零）
	receiverAddr, _ := btcutil.DecodeAddress(params.Receiver, &chaincfg.TestNet3Params)
	receiverScript, _ := txscript.PayToAddrScript(receiverAddr)
	buildInscriptionScript, _ := buildInscriptionScript([]byte("hello"))
	packet.UnsignedTx.TxOut = append(packet.UnsignedTx.TxOut,
		&wire.TxOut{
			Value:    546,
			PkScript: buildInscriptionScript,
		},
		&wire.TxOut{
			Value:    int64(params.Amount), // 铭文必须保持546聪‌:ml-citation{ref="1,2" data="citationList"}
			PkScript: receiverScript,
		},
	)

	// 4. 设置手续费
	//packet.SetFeeRate(btcutil.Amount(params.FeeRate)) // 单位：sat/vB‌:ml-citation{ref="2" data="citationList"}

	return packet.B64Encode()
}

func queryInscriptionUTXO(hash string, index int) (bool, error) {
	tx, err := global.GVA_GOBCY.GetTX(hash, nil)
	if err != nil {
		return false, err
	}
	if index >= len(tx.Outputs) {
		return false, errors.New("UTXO索引超出范围")
	}
	// 遍历交易输出，收集未花费的UTXO
	for _, output := range tx.Outputs {
		if output.SpentBy == "" {
			// 这里可以根据需求处理UTXO数据，当前函数返回布尔值，检测到未花费输出则返回true
			return true, nil
		}
	}
	return false, errors.New("未找到未花费的UTXO")
}

// 生成铭文载体脚本（固定546聪）
func buildInscriptionScript(content []byte) ([]byte, error) {
	builder := txscript.NewScriptBuilder()
	builder.AddOp(txscript.OP_FALSE)
	builder.AddOp(txscript.OP_IF)
	builder.AddData([]byte("ord")) // Ordinals协议标识
	builder.AddData([]byte{0x01})  // 数据推送
	builder.AddData(content)
	builder.AddOp(txscript.OP_ENDIF)
	return builder.Script()
}

// 生成找零脚本（新UTXO）
// func buildChangeScript(wallet *btcec.PrivateKey) ([]byte, error) {
// 	pubKey := wallet.PubKey()
// 	hash := btcutil.Hash160(pubKey.SerializeCompressed())
// 	return txscript.NewScriptBuilder().
// 		AddOp(txscript.OP_0).
// 		AddData(hash).
// 		Script()
// }

// BuildBrc20Tx 创建brx20交易
// @Tags BrcLock
// @Summary 创建brx20交易
// @accept application/json
// @Produce application/json
// @Param data body brcReq.InscriptionTransferRequest true "创建brx20交易"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /brcLock/createBrx20Tx [post]
func (brcLockApi *BrcLockApi) BuildBrc20Tx(c *gin.Context) {
	var req brcReq.InscriptionTransferRequest
	err := c.ShouldBindJSON(&req)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	// 验证参数
	verify := utils.Rules{
		"FromAddress": {utils.NotEmpty()},
		"ToAddress":   {utils.NotEmpty()},
		"Ticker":      {utils.NotEmpty()},
		"Amount":      {utils.NotEmpty()},
		"UTXOs":       {utils.NotEmpty()},
	}
	if err := utils.Verify(req, verify); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	psbtStr, err := BuildInscriptionPSBT(req)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	response.OkWithData(psbtStr, c)
}

func BuildInscriptionPSBT(req brcReq.InscriptionTransferRequest) (*brcReq.PSBTResponse, error) {
	// 1. 参数校验
	if err := validateRequest(req); err != nil {
		return nil, err
	}

	// 2. 获取UTXO数据（实际应从区块链节点获取）
	utxos, err := fetchInscriptionUTXOs(req.FromAddress, req.Ticker)
	if err != nil {
		return nil, err
	}

	// 3. 选择足够金额的UTXO组合
	selectedUTXOs, changeAmount := selectUTXOs(utxos, req.Amount)
	if len(selectedUTXOs) == 0 {
		return nil, errors.New("insufficient inscription balance")
	}

	// 4. 构造PSBT交易
	psbt, err := constructPSBTTx(selectedUTXOs, req.ToAddress, req.FromAddress,
		req.Amount, changeAmount, req.FeeRate)
	if err != nil {
		return nil, err
	}

	return &brcReq.PSBTResponse{
		UnsignedPSBT: psbt,
		UsedUTXOs:    getUTXOIdentifiers(selectedUTXOs),
		ChangeAmount: changeAmount,
	}, nil
}

// PSBT交易构造
func constructPSBTTx(utxos []brcReq.InscriptionUTXO, toAddr, fromAddr string,

	amount uint64, change int64, feeRate uint64) (string, error) {

	msgTx := wire.NewMsgTx(wire.TxVersion)

	// 添加输入
	for _, utxo := range utxos {
		hash, _ := chainhash.NewHashFromStr(utxo.TxID)
		outPoint := wire.NewOutPoint(hash, utxo.Vout)
		txIn := wire.NewTxIn(outPoint, nil, nil)
		msgTx.AddTxIn(txIn)
	}

	// 添加输出（接收方）
	toScript, _ := btcutil.DecodeAddress(toAddr, &chaincfg.MainNetParams)
	msgTx.AddTxOut(wire.NewTxOut(int64(amount), toScript.ScriptAddress()))

	// 添加找零输出
	if change > 0 {
		fromScript, _ := btcutil.DecodeAddress(fromAddr, &chaincfg.MainNetParams)
		msgTx.AddTxOut(wire.NewTxOut(change, fromScript.ScriptAddress()))
	}

	// 转换为PSBT
	psbt, err := psbt.NewFromUnsignedTx(msgTx)
	if err != nil {
		return "", err
	}

	// 返回Base64编码的PSBT
	return psbt.B64Encode()
}

func selectUTXOs(utxos []brcReq.InscriptionUTXO, amount uint64) ([]brcReq.InscriptionUTXO, int64) {
	var selected []brcReq.InscriptionUTXO
	var total uint64

	for _, utxo := range utxos {
		if utxo.Amount >= amount {
			return []brcReq.InscriptionUTXO{utxo}, int64(utxo.Amount - amount)
		}
		selected = append(selected, utxo)
		total += utxo.Amount
		if total >= amount {
			return selected, int64(total - amount)
		}
	}
	return nil, 0
}

func fetchInscriptionUTXOs(address string, ticker string) ([]brcReq.InscriptionUTXO, error) {
	api := global.GVA_GOBCY
	resp, err := api.GetAddr(address, nil)
	if err != nil {
		return nil, err
	}
	utxos := make([]brcReq.InscriptionUTXO, 0)
	for _, v := range resp.TXRefs {
		if !v.Spent && v.Script != "" {
			utxo := brcReq.InscriptionUTXO{
				TxID:   v.TXHash,
				Amount: uint64(v.Value.Int64()),
				Script: v.Script,
			}
			utxos = append(utxos, utxo)
		}
	}
	return utxos, nil
}

func getUTXOIdentifiers(utxos []brcReq.InscriptionUTXO) []string {
	var ids []string
	for _, u := range utxos {
		ids = append(ids, fmt.Sprintf("%s:%d", u.TxID, u.Vout))
	}
	return ids
}

// 参数验证函数
func validateRequest(req brcReq.InscriptionTransferRequest) error {
	if req.Amount == 0 {
		return errors.New("amount cannot be zero")
	}
	if len(req.UTXOs) == 0 {
		return errors.New("no UTXOs provided")
	}
	return nil
}

func isInscriptionUTXO(utxo brcReq.InscriptionUTXO) bool {
	return utxo.Amount == 546 &&
		len(utxo.Script) > 20 &&
		utxo.Script[:4] == "0063" // OP_FALSE OP_IF的hex编码
}
