package models

import (
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/DrmagicE/gmqtt"
	_ "github.com/DrmagicE/gmqtt/persistence"
	"github.com/DrmagicE/gmqtt/pkg/packets"
	mqttServer "github.com/DrmagicE/gmqtt/server"
	_ "github.com/DrmagicE/gmqtt/topicalias/fifo"
)

type MqttServerZ struct {
	CertFile string
	KeyFile  string
}

var postUrl = "http://localhost/api/mqttserver_state"

func (ggg *MqttServerZ) MqttServerTLS() {
	// 加载TLS证书和私钥
	cert, err := tls.LoadX509KeyPair(ggg.CertFile, ggg.KeyFile)
	if err != nil {
		fmt.Printf("加载TLS证书失败: %v\n", err)
		return
	}

	// 创建TLS配置
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		ClientAuth:   tls.NoClientCert, // 单向认证
		MinVersion:   tls.VersionTLS12, // 最低TLS版本
	}

	//创建TLS监听器，监听8083端口
	ln, err := tls.Listen("tcp", ":8883", tlsConfig)
	if err != nil {
		fmt.Printf("创建TLS监听器失败: %v\n", err)
		return
	}
	// 设置MQTT钩子
	hooks := mqttServer.Hooks{
		//账号密码认证
		OnBasicAuth: func(ctx context.Context, client mqttServer.Client, req *mqttServer.ConnectRequest) error {
			username := string(req.Connect.Username)
			password := string(req.Connect.Password)
			clientId := string(req.Connect.ClientID)
			fmt.Println(username, password, clientId)
			if Db.conn != nil {
				fmt.Println("数据库连接成功")
				id := 0
				Db.Sql("SELECT id FROM MqttServer WHERE username=? AND password=?", username, password).Row(&id)
				if id == 0 {
					client.Close()
					return fmt.Errorf("账号密码错误")
				} else {
					client.ClientOptions().Username = username
					ggg.RequestPost(postUrl, "username="+username+"&message=connect")
					return nil
				}
			} else {
				client.Close()
				fmt.Println("数据库连接失败")
				return fmt.Errorf("数据库连接失败")
			}

		},
		// 连接处理钩子（可访问完整的ConnectRequest）
		OnConnected: func(ctx context.Context, client mqttServer.Client) {
			fmt.Printf("客户端已连接: %s\n", client.ClientOptions().ClientID)
		},

		OnClosed: func(ctx context.Context, client mqttServer.Client, err error) {
			fmt.Printf("客户端已断开: %s, 错误: %v\n", client.ClientOptions().Username, err)
			ggg.RequestPost(postUrl, "username="+client.ClientOptions().Username+"&message=disconnect")
		},
	}

	// 创建MQTT服务器
	srv := mqttServer.New(
		mqttServer.WithTCPListener(ln),
		mqttServer.WithHook(hooks),
	)

	// 添加保留消息
	retainedService := srv.RetainedService()
	retainedService.AddOrReplace(&gmqtt.Message{
		QoS:      packets.Qos1,
		Retained: true,
		Topic:    "a/b/c",
		Payload:  []byte("retained message"),
	})

	// 启动服务器
	go func() {
		signalCh := make(chan os.Signal, 1)
		signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
		<-signalCh
		srv.Stop(context.Background())
	}()

	fmt.Println("MQTT服务器已启动，监听TLS端口: 8083")
	if err := srv.Run(); err != nil {
		panic(fmt.Sprintf("服务器运行失败: %v", err))
	}
}
func (ggg *MqttServerZ) MqttServer() {

	ln, err := net.Listen("tcp", ":1883")
	if err != nil {
		fmt.Printf("创建TLS监听器失败: %v\n", err)
		return
	}
	defer ln.Close()
	// 设置MQTT钩子
	hooks := mqttServer.Hooks{
		//账号密码认证
		OnBasicAuth: func(ctx context.Context, client mqttServer.Client, req *mqttServer.ConnectRequest) error {
			username := string(req.Connect.Username)
			password := string(req.Connect.Password)
			clientId := string(req.Connect.ClientID)
			fmt.Println(username, password, clientId)
			if Db.conn != nil {
				fmt.Println("数据库连接成功")
				id := 0
				Db.Sql("SELECT id FROM MqttServer WHERE username=? AND password=?", username, password).Row(&id)
				if id == 0 {
					client.Close()
					return fmt.Errorf("账号密码错误")
				} else {
					// 保存用户名到客户端属性
					client.ClientOptions().Username = username
					ggg.RequestPost(postUrl, "username="+username+"&message=connect")
					return nil
				}
			} else {
				client.Close()
				fmt.Println("数据库连接失败")
				return fmt.Errorf("数据库连接失败")
			}
		},
		OnConnected: func(ctx context.Context, client mqttServer.Client) {
			fmt.Printf("客户端已连接: %s\n", client.ClientOptions().ClientID)
		},

		OnClosed: func(ctx context.Context, client mqttServer.Client, err error) {
			fmt.Printf("客户端已断开: %s, 错误: %v\n", client.ClientOptions().Username, err)
			ggg.RequestPost(postUrl, "username="+client.ClientOptions().Username+"&message=disconnect")
		},
	}

	// 创建MQTT服务器
	srv := mqttServer.New(
		mqttServer.WithTCPListener(ln),
		mqttServer.WithHook(hooks),
	)

	// 添加保留消息
	retainedService := srv.RetainedService()
	retainedService.AddOrReplace(&gmqtt.Message{
		QoS:      packets.Qos1,
		Retained: true,
		Topic:    "a/b/c",
		Payload:  []byte("retained message"),
	})

	// 启动服务器
	go func() {
		signalCh := make(chan os.Signal, 1)
		signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
		<-signalCh
		srv.Stop(context.Background())
	}()

	fmt.Println("MQTT服务器已启动，监听TLS端口: 1883")
	if err := srv.Run(); err != nil {
		panic(fmt.Sprintf("服务器运行失败: %v", err))
	}
}
func (ggg *MqttServerZ) RequestPost(url string, KVstring string) (string, error) {
	myhttp := &http.Client{}
	myhttp.Timeout = time.Duration(3 * time.Second)
	resp, err1 := myhttp.Post(url, "application/x-www-form-urlencoded; charset=UTF-8", strings.NewReader(KVstring))
	if err1 != nil {
		return "", errors.New("服务器未响应")
	}
	defer resp.Body.Close()
	body, err2 := io.ReadAll(resp.Body)
	if err2 != nil {
		return "", errors.New("读取数据fail")
	}
	return string(body), nil
}
func IsValidMAC(mac string) bool {
	_, err := net.ParseMAC(mac)
	return err == nil
}
