package service

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"strings"
	"time"

	"licserver/internal/model"

	"gorm.io/gorm"
)

type TokenService struct {
	db *gorm.DB
}

func NewTokenService(db *gorm.DB) *TokenService {
	return &TokenService{db: db}
}

// 生成访问令牌
func generateToken() (string, error) {
	b := make([]byte, 32)
	if _, err := rand.Read(b); err != nil {
		return "", err
	}
	return hex.EncodeToString(b), nil
}

// 创建访问令牌
func (s *TokenService) CreateToken(deviceUID, tokenType string, expireTime time.Time, ipList []string, createdBy uint) (*model.AccessToken, error) {
	// 验证设备是否存在
	var device model.Device
	if err := s.db.Where("uid = ?", deviceUID).First(&device).Error; err != nil {
		return nil, errors.New("设备不存在")
	}

	// 生成令牌
	token, err := generateToken()
	if err != nil {
		return nil, err
	}

	// 创建令牌记录
	accessToken := &model.AccessToken{
		Token:      token,
		DeviceUID:  deviceUID,
		Type:       tokenType,
		Status:     "active",
		ExpireTime: expireTime,
		IPList:     strings.Join(ipList, ","),
		CreatedBy:  createdBy,
	}

	if err := s.db.Create(accessToken).Error; err != nil {
		return nil, err
	}

	// 记录日志
	tokenLog := &model.TokenLog{
		TokenID: accessToken.ID,
		Action:  "create",
		Status:  "success",
		Message: "创建访问令牌",
	}
	s.db.Create(tokenLog)

	return accessToken, nil
}

// 验证令牌
func (s *TokenService) ValidateToken(token, ip string) (*model.AccessToken, error) {
	var accessToken model.AccessToken
	if err := s.db.Where("token = ?", token).First(&accessToken).Error; err != nil {
		return nil, errors.New("无效的令牌")
	}

	// 检查令牌状态
	if accessToken.Status != "active" {
		return nil, errors.New("令牌已被撤销")
	}

	// 检查过期时间
	if time.Now().After(accessToken.ExpireTime) {
		return nil, errors.New("令牌已过期")
	}

	// 检查IP限制
	if accessToken.IPList != "" {
		allowedIPs := strings.Split(accessToken.IPList, ",")
		allowed := false
		for _, allowedIP := range allowedIPs {
			if allowedIP == ip {
				allowed = true
				break
			}
		}
		if !allowed {
			return nil, errors.New("IP地址不允许访问")
		}
	}

	// 更新使用记录
	s.db.Model(&accessToken).Updates(map[string]interface{}{
		"last_used":   time.Now(),
		"usage_count": gorm.Expr("usage_count + 1"),
	})

	// 记录日志
	tokenLog := &model.TokenLog{
		TokenID: accessToken.ID,
		Action:  "use",
		IP:      ip,
		Status:  "success",
	}
	s.db.Create(tokenLog)

	return &accessToken, nil
}

// 撤销令牌
func (s *TokenService) RevokeToken(token string, userID uint) error {
	var accessToken model.AccessToken
	if err := s.db.Where("token = ?", token).First(&accessToken).Error; err != nil {
		return errors.New("令牌不存在")
	}

	// 检查权限
	if accessToken.CreatedBy != userID {
		return errors.New("无权操作此令牌")
	}

	// 更新状态
	if err := s.db.Model(&accessToken).Update("status", "revoked").Error; err != nil {
		return err
	}

	// 记录日志
	tokenLog := &model.TokenLog{
		TokenID: accessToken.ID,
		Action:  "revoke",
		Status:  "success",
		Message: "撤销访问令牌",
	}
	s.db.Create(tokenLog)

	return nil
}

// 获取令牌列表
func (s *TokenService) GetTokens(deviceUID string, page, pageSize int) ([]model.AccessToken, int64, error) {
	var tokens []model.AccessToken
	var total int64

	query := s.db.Model(&model.AccessToken{})
	if deviceUID != "" {
		query = query.Where("device_uid = ?", deviceUID)
	}

	query.Count(&total)

	if page > 0 && pageSize > 0 {
		offset := (page - 1) * pageSize
		query = query.Offset(offset).Limit(pageSize)
	}

	err := query.Order("created_at DESC").Find(&tokens).Error
	return tokens, total, err
}

// 获取令牌日志
func (s *TokenService) GetTokenLogs(tokenID uint, page, pageSize int) ([]model.TokenLog, int64, error) {
	var logs []model.TokenLog
	var total int64

	query := s.db.Model(&model.TokenLog{}).Where("token_id = ?", tokenID)
	query.Count(&total)

	if page > 0 && pageSize > 0 {
		offset := (page - 1) * pageSize
		query = query.Offset(offset).Limit(pageSize)
	}

	err := query.Order("created_at DESC").Find(&logs).Error
	return logs, total, err
}
