package service

import (
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"net"
	"strconv"

	"git.zkcoi.com/zkcoi/meshray/internal/ctr"
	"git.zkcoi.com/zkcoi/meshray/internal/model"
	"git.zkcoi.com/zkcoi/meshray/internal/store/sqlite"
	"golang.org/x/crypto/curve25519"
	"gorm.io/gorm"
)

// DeviceService 设备管理服务
type DeviceService struct {
	store     *sqlite.Store
	ctrClient ctr.Client // meshray-ctr 客户端
}

// NewDeviceService 创建设备服务实例
func NewDeviceService(store *sqlite.Store, ctrClient ctr.Client) *DeviceService {
	return &DeviceService{
		store:     store,
		ctrClient: ctrClient,
	}
}

// GetDevice 获取设备详情
func (s *DeviceService) GetDevice(id uint64) (*model.Device, error) {
	var device model.Device
	err := s.store.DB().First(&device, id).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("设备不存在")
		}
		return nil, err
	}
	return &device, nil
}

// ListAllDevices 获取所有设备列表
func (s *DeviceService) ListAllDevices() ([]model.Device, error) {
	var devices []model.Device
	err := s.store.DB().Find(&devices).Error
	return devices, err
}

// ListDevicesByNetwork 获取网络下的设备列表
func (s *DeviceService) ListDevicesByNetwork(networkID uint64) ([]model.Device, error) {
	var devices []model.Device
	err := s.store.DB().Where("network_id = ?", networkID).Find(&devices).Error
	return devices, err
}

// CreateDeviceRequest 创建设备请求
type CreateDeviceRequest struct {
	NetworkID   uint64 `json:"network_id"`
	Name        string `json:"name"`
	VirtualIP   string `json:"virtual_ip"`  // 可选，留空则自动分配
	Description string `json:"description"` // 可选
}

// CreateDeviceResult 创建设备结果
type CreateDeviceResult struct {
	Device     *model.Device `json:"device"`
	PrivateKey string        `json:"private_key"` // 仅首次返回
	ConfigText string        `json:"config_text"` // WireGuard 配置文本
}

// CreateDevice 创建设备
func (s *DeviceService) CreateDevice(req *CreateDeviceRequest) (*CreateDeviceResult, error) {
	// 验证网络是否存在
	var network model.Network
	if err := s.store.DB().First(&network, req.NetworkID).Error; err != nil {
		return nil, errors.New("网络不存在")
	}

	// 检查设备名称是否重复
	var existing model.Device
	if err := s.store.DB().Where("network_id = ? AND name = ?", req.NetworkID, req.Name).First(&existing).Error; err == nil {
		return nil, errors.New("设备名称已存在")
	}

	// 生成 WireGuard 密钥对（同时获取私钥）
	privateKey, publicKey, err := generateWireGuardKeys()
	if err != nil {
		return nil, fmt.Errorf("生成密钥失败：%w", err)
	}

	// 生成预共享密钥
	preSharedKey := generatePreSharedKey()

	// 自动分配 IP（如果未提供）
	virtualIP := req.VirtualIP
	if virtualIP == "" {
		virtualIP, err = s.allocateIP(req.NetworkID, network.SubnetIPv4)
		if err != nil {
			return nil, fmt.Errorf("分配 IP 失败：%w", err)
		}
	}

	// 创建设备
	device := &model.Device{
		NetworkID:    req.NetworkID,
		Name:         req.Name,
		VirtualIP:    virtualIP,
		PublicKey:    publicKey,
		PresharedKey: preSharedKey,
		Status:       "offline",
	}

	if err := s.store.DB().Create(device).Error; err != nil {
		return nil, err
	}

	// P2 阶段 - 调用 meshray-ctr 添加 Peer
	if s.ctrClient != nil {
		allowedIP := device.VirtualIP + "/32"
		if err := s.ctrClient.AddPeer(device.NetworkID, device.PublicKey, allowedIP); err != nil {
			// 记录错误但不影响数据库操作（允许降级）
		}
	}

	// 生成 WireGuard 配置文本
	configText := s.deviceGenerateConfig(device, &network, privateKey)

	return &CreateDeviceResult{
		Device:     device,
		PrivateKey: privateKey,
		ConfigText: configText,
	}, nil
}

// UpdateDevice 更新设备
func (s *DeviceService) UpdateDevice(id uint64, updates map[string]interface{}) (*model.Device, error) {
	var device model.Device
	if err := s.store.DB().First(&device, id).Error; err != nil {
		return nil, errors.New("设备不存在")
	}

	if err := s.store.DB().Model(&device).Updates(updates).Error; err != nil {
		return nil, err
	}

	return &device, nil
}

// DeleteDevice 删除设备
func (s *DeviceService) DeleteDevice(id uint64) error {
	// ✅ 使用事务保证数据一致性
	tx := s.store.DB().Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	var device model.Device
	if err := tx.First(&device, id).Error; err != nil {
		tx.Rollback()
		return errors.New("设备不存在")
	}

	// ✅ 如果设备在线，先断开连接（P2 阶段）
	if s.ctrClient != nil {
		if err := s.ctrClient.RemovePeer(device.NetworkID, device.PublicKey); err != nil {
			// 记录警告但不阻断删除流程
			fmt.Printf("⚠️ 从 WireGuard 移除 Peer 失败：network_id=%d, error=%v\n", device.NetworkID, err)
		}
	}

	// ✅ 清理相关路由和配置（P2 阶段）
	// ✅ P3 阶段 - 当前无额外路由配置，暂不实现
	// 未来如果需要，可以在这里添加

	// 删除设备
	if err := tx.Delete(&device, id).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return err
	}

	return nil
}

// allocateIP 自动分配 IP 地址
func (s *DeviceService) allocateIP(networkID uint64, subnet string) (string, error) {
	// 解析子网
	_, ipNet, err := net.ParseCIDR(subnet)
	if err != nil {
		return "", fmt.Errorf("解析子网失败：%w", err)
	}

	// 检查是否是 IPv4 地址
	if ipNet.IP.To4() == nil {
		return "", errors.New("暂不支持 IPv6 地址分配")
	}

	// 查询已分配的所有 IP
	var devices []model.Device
	if err := s.store.DB().Where("network_id = ?", networkID).Find(&devices).Error; err != nil {
		return "", fmt.Errorf("查询已分配 IP 失败：%w", err)
	}

	// 构建已占用 IP 集合
	occupiedIPs := make(map[string]bool)
	for _, device := range devices {
		occupiedIPs[device.VirtualIP] = true
	}

	// 从 .2 开始分配（.1 通常留给网关）
	// 遍历整个子网范围查找可用 IP
	ip := ipNet.IP.To4()
	startIP := ip.Mask(ipNet.Mask).To4()
	startIP[3]++ // 从 .1 开始

	// 最多尝试 254 个 IP（/24 子网）
	for i := 1; i < 255; i++ {
		candidateIP := make(net.IP, len(startIP))
		copy(candidateIP, startIP)
		candidateIP[3] = byte(i + 1) // 从 .2 开始

		// 检查是否被占用
		if !occupiedIPs[candidateIP.String()] {
			return candidateIP.String(), nil
		}
	}

	return "", errors.New("IP 地址已耗尽")
}

// getSettings 获取系统设置（辅助方法）
func (s *DeviceService) getSettings() (*model.SystemSetting, error) {
	var setting model.SystemSetting
	err := s.store.DB().First(&setting, 1).Error
	if err != nil {
		// 如果不存在，返回默认值
		return &model.SystemSetting{
			ServerPort: 51820,
		}, nil
	}
	return &setting, nil
}

// generateWireGuardKeys 生成 WireGuard 密钥对
func generateWireGuardKeys() (privateKey, publicKey string, err error) {
	// 生成私钥（32 字节随机数）
	var privKeyBytes [32]byte
	if _, err := rand.Read(privKeyBytes[:]); err != nil {
		return "", "", err
	}

	// 确保私钥符合 Curve25519 要求
	privKeyBytes[0] &= 248
	privKeyBytes[31] &= 127
	privKeyBytes[31] |= 64

	// 从私钥推导公钥
	var pubKeyBytes [32]byte
	curve25519.ScalarBaseMult(&pubKeyBytes, &privKeyBytes)

	// Base64 编码
	privateKey = base64.StdEncoding.EncodeToString(privKeyBytes[:])
	publicKey = base64.StdEncoding.EncodeToString(pubKeyBytes[:])

	return privateKey, publicKey, nil
}

// generatePreSharedKey 生成预共享密钥
func generatePreSharedKey() string {
	bytes := make([]byte, 32)
	rand.Read(bytes)
	return base64.StdEncoding.EncodeToString(bytes)
}

// deviceGenerateConfig 生成 WireGuard 配置文本（设备创建时使用）
func (s *DeviceService) deviceGenerateConfig(device *model.Device, network *model.Network, privateKey string) string {
	settings, _ := s.getSettings()

	config := "[Interface]\n"
	config += "PrivateKey = " + privateKey + "\n"
	config += "Address = " + device.VirtualIP + "/32\n"
	config += fmt.Sprintf("MTU = %d\n\n", network.MTU)

	config += "[Peer]\n"
	if settings.ServerPublicKey != "" {
		config += "PublicKey = " + settings.ServerPublicKey + "\n"
	} else {
		config += "PublicKey = <SERVER_PUBLIC_KEY>\n"
	}
	if settings.ServerIP != "" {
		config += "Endpoint = " + settings.ServerIP + ":" + strconv.Itoa(settings.ServerPort) + "\n"
	} else {
		config += fmt.Sprintf("Endpoint = <SERVER_IP>:%d\n", settings.ServerPort)
	}
	config += "AllowedIPs = " + network.SubnetIPv4 + "\n"
	config += "PersistentKeepalive = 25\n"

	return config
}

// GenerateDeviceConfig 生成设备配置文件
func (s *DeviceService) GenerateDeviceConfig(deviceID uint64) (string, error) {
	// 获取设备信息（包含网络）
	device, err := s.GetDevice(deviceID)
	if err != nil {
		return "", err
	}

	// 生成 WireGuard 密钥对
	privateKey, publicKey, err := generateWireGuardKeys()
	if err != nil {
		return "", fmt.Errorf("生成密钥失败：%w", err)
	}

	// 更新设备的公钥到数据库
	if err := s.store.DB().Model(device).Update("public_key", publicKey).Error; err != nil {
		return "", fmt.Errorf("保存公钥失败：%w", err)
	}

	// 生成完整的 WireGuard 配置
	config := "# MeshRay Generated Configuration\n"
	config += "# Device: " + device.Name + "\n"
	config += "# Created: " + device.CreatedAt.Format("2006-01-02 15:04:05") + "\n\n"

	// [Interface] 部分
	config += "[Interface]\n"
	config += "PrivateKey = " + privateKey + "\n"
	config += "Address = " + device.VirtualIP + "/32\n"
	config += "DNS = 8.8.8.8, 8.8.4.4\n\n"

	// [Peer] 部分（服务端配置）
	config += "# Server (MeshRay)\n"
	config += "[Peer]\n"

	// 从 Settings 读取服务端公钥
	settings, _ := s.getSettings()
	if settings.ServerPublicKey == "" {
		return "", errors.New("请先在系统设置中配置服务端公钥")
	}
	config += "PublicKey = " + settings.ServerPublicKey + "\n"

	if device.PresharedKey != "" {
		config += "PresharedKey = " + device.PresharedKey + "\n"
	}
	config += "AllowedIPs = 0.0.0.0/0\n"

	// 使用 Settings 中的 ServerIP 和 ServerPort
	if settings.ServerIP == "" {
		return "", errors.New("请先在系统设置中配置服务端 IP 地址")
	}
	config += "Endpoint = " + settings.ServerIP + ":" + strconv.Itoa(settings.ServerPort) + "\n"
	config += "PersistentKeepalive = 25\n"

	return config, nil
}
