package miner

import (
	"bufio"
	"encoding/json"
	"fmt"
	"net"
	"proxy/internal/msg"
	"strings"
	"sync"
)

const topic string = "[miner]:"

type Miner struct {
	sync.Mutex
	Coin        string
	ID          string // user + miner
	PoolConn    net.Conn
	MinerConn   net.Conn
	PoolAddress string
}

func NewMiner(coin string, poolAddress string, minerConn net.Conn) (*Miner, error) {
	poolConn, err := net.Dial("tcp", poolAddress)
	if err != nil {
		return nil, fmt.Errorf("pool连接失败: %v", err)
	}

	return &Miner{
		Coin:        coin,
		PoolConn:    poolConn,
		MinerConn:   minerConn,
		PoolAddress: poolAddress,
	}, nil
}

// 动态切换矿池地址并建立新连接
func (m *Miner) ChangePoolAddress(newAddress string) {
	m.Lock()
	defer m.Unlock()

	// 尝试建立新连接
	newConn, err := net.Dial("tcp", newAddress)
	if err != nil {
		fmt.Println("切换pool连接失败:", err)
		return
	}

	// 关闭旧连接
	if m.PoolConn != nil {
		_ = m.PoolConn.Close()
	}

	m.PoolConn = newConn
	m.PoolAddress = newAddress

	fmt.Println("成功切换矿池地址为:", newAddress)
}

// 矿工消息处理
func (m *Miner) HandleMinerMsg(ch chan string) {
	defer m.MinerConn.Close()
	defer m.PoolConn.Close()

	reader := bufio.NewReader(m.MinerConn)
	sent := false // 保证 userSign 只发送一次

	for {
		msgStr, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("miner消息读取失败：", err)
			return
		}
		// fmt.Println("从矿工收到消息：", msgStr)
		switch m.Coin {
		case "nexa":
			//
		default:
			var msg msg.Authorize_msg
			if err := json.Unmarshal([]byte(msgStr), &msg); err == nil &&
				msg.Method == "mining.authorize" && len(msg.Params) >= 1 && !sent {
				parts := strings.Split(msg.Params[0], ".")
				if len(parts) >= 2 {
					userSign := parts[0] + "-" + parts[1]
					select {
					case ch <- userSign:
						sent = true
					default:
					}
				} else {
					fmt.Println(topic+"mining.authorize解析user-miner错误\n", err)
				}

			}
		}

		if m.PoolConn != nil {
			_, err = m.PoolConn.Write([]byte(msgStr))
			if err != nil {
				fmt.Println("转发到pool失败：", err)
				return
			}
		}
	}
}

// 矿池消息处理
func (m *Miner) HandlePoolMsg() {
	defer m.MinerConn.Close()
	defer m.PoolConn.Close()

	reader := bufio.NewReader(m.PoolConn)
	for {
		poolMsg, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("pool消息读取失败：", err)
			return
		}
		// fmt.Println("从矿池收到消息：", poolMsg)

		if m.MinerConn != nil {
			_, err = m.MinerConn.Write([]byte(poolMsg))
			if err != nil {
				fmt.Println("转发到miner失败：", err)
				return
			}
		}
	}
}
