package uhf

import (
	"errors"
	"github.com/tarm/serial"
	"io"
	"os"
	"time"
)

type SerialReader struct {
	COMPort     string
	BaudRate    int
	port        *serial.Port
	isConnected bool
	buffer      []byte // 拼包缓冲区
}

func NewSerialReader(comPort string, baudRate int) *SerialReader {
	return &SerialReader{
		COMPort:  comPort,
		BaudRate: baudRate,
	}
}

func (s *SerialReader) Connect() error {
	cfg := &serial.Config{
		Name:        s.COMPort,
		Baud:        s.BaudRate,
		ReadTimeout: 1 * time.Second,
		Size:        8,
		Parity:      serial.ParityNone,
		StopBits:    serial.Stop1,
	}
	port, err := serial.OpenPort(cfg)
	if err != nil {
		s.isConnected = false
		return err
	}
	s.port = port
	s.isConnected = true
	return nil
}

func (s *SerialReader) Disconnect() error {
	if s.port != nil {
		_ = s.port.Close()
	}
	s.isConnected = false
	s.buffer = nil
	return nil
}

func (s *SerialReader) IsConnected() bool {
	return s.isConnected
}

func (s *SerialReader) SendData(data []byte) error {
	if !s.isConnected {
		return errors.New("串口未连接")
	}
	n, err := s.port.Write(data)
	if err != nil {
		return err
	}
	if n != len(data) {
		return errors.New("发送不完整")
	}
	return nil
}

// ==============================
// 🔥 关键修复：串口返回完整25字节帧
// ==============================
func (s *SerialReader) ReadData() ([]byte, error) {
	if !s.isConnected {
		return nil, errors.New("串口未连接")
	}

	buf := make([]byte, 1024)
	for {
		n, err := s.port.Read(buf)
		if err != nil {
			if err == io.EOF || os.IsTimeout(err) {
				break
			}
			s.isConnected = false
			return nil, err
		}
		if n > 0 {
			s.buffer = append(s.buffer, buf[:n]...)
		}

		// 找25字节完整帧
		for len(s.buffer) >= 25 {
			if s.buffer[0] == 0xCF {
				frame := s.buffer[:25]
				s.buffer = s.buffer[25:]
				return frame, nil
			} else {
				s.buffer = s.buffer[1:]
			}
		}

		// 超时退出
		if len(s.buffer) == 0 {
			break
		}
	}

	return nil, errors.New("等待完整帧")
}

func (s *SerialReader) SendAndRecv(data []byte) ([]byte, error) {
	_ = s.SendData(data)
	time.Sleep(100 * time.Millisecond)
	return s.ReadData()
}
