package service

import (
	"crypto/rand"

	"encoding/hex"

	"errors"

	"fmt"

	"strings"

	"time"

	"licserver/internal/model"

	"gorm.io/gorm"
)

type LicenseService struct {
	db *gorm.DB
}

func NewLicenseService(db *gorm.DB) *LicenseService {

	return &LicenseService{db: db}

}

// 生成授权码

func generateLicenseCode() (string, error) {

	b := make([]byte, 16)

	if _, err := rand.Read(b); err != nil {

		return "", err

	}

	return hex.EncodeToString(b), nil

}

// 创建授权码

type LicenseCreateInput struct {
	LicenseType string `json:"license_type" binding:"required"`

	Duration int `json:"duration"` // 时间授权的有效期（分钟）

	MaxUses int `json:"max_uses"` // 次数授权的使用次数

	Count int `json:"count" binding:"required,min=1"` // 生成数量

	Remark string `json:"remark"` // 备注

	BindCount int `json:"bind_count"` // 可绑定次数，默认为-1（无限制）

}

func (s *LicenseService) CreateLicenses(input *LicenseCreateInput, createdBy uint) ([]model.LicenseCode, error) {

	// 验证参数

	input.LicenseType = strings.ToLower(input.LicenseType) // 转为小写

	switch input.LicenseType {
	case "time":
		if input.Duration <= 0 {
			return nil, errors.New("时间授权必须指定有效期")
		}
	case "count":
		if input.MaxUses <= 0 {
			return nil, errors.New("次数授权必须指定使用次数")
		}
	case "permanent":
		// 永久授权不需要额外参数
	default:
		return nil, errors.New("无效的授权类型")
	}

	// 如果未指定绑定次数，设置为默认值-1
	if input.BindCount == 0 {
		input.BindCount = -1
	}

	// 生成批次号

	batchNo := time.Now().Format("20060102150405")

	licenses := make([]model.LicenseCode, 0, input.Count)

	for i := 0; i < input.Count; i++ {

		code, err := generateLicenseCode()

		if err != nil {

			return nil, err

		}

		license := model.LicenseCode{

			Code: code,

			LicenseType: input.LicenseType,

			Duration: input.Duration,

			MaxUses: input.MaxUses,

			Status: "unused",

			CreatedBy: createdBy,

			BatchNo: batchNo,

			Remark: input.Remark,

			BindCount: input.BindCount,
		}

		licenses = append(licenses, license)

	}

	// 批量创建授权码

	if err := s.db.Create(&licenses).Error; err != nil {

		return nil, err

	}

	return licenses, nil

}

// 验证并使用授权码

func (s *LicenseService) UseLicense(code, deviceUID, ip string) (*model.LicenseCode, error) {

	var license model.LicenseCode

	if err := s.db.Where("code = ?", code).First(&license).Error; err != nil {

		return nil, errors.New("授权码不存在")

	}

	// 检查授权码状态

	if license.Status != "unused" {

		return nil, errors.New("授权码已被使用")

	}

	// 检查绑定次数
	if license.BindCount == 0 {
		return nil, errors.New("授权码已达到最大绑定次数限制")
	}

	// 更新授权码状态

	updates := map[string]interface{}{
		"status":  "used",
		"used_by": deviceUID,
		"used_at": time.Now(),
	}

	// 如果不是无限制，减少绑定次数
	if license.BindCount > 0 {
		updates["bind_count"] = license.BindCount - 1
	}

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

	// 记录使用日志
	log := model.LicenseLog{
		LicenseID: license.ID,
		DeviceUID: deviceUID,
		Action:    "use",
		IP:        ip,
		Status:    "success",
		Message:   fmt.Sprintf("设备 %s 使用授权码", deviceUID),
	}

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

	return &license, nil

}

// 获取授权码列表

func (s *LicenseService) GetLicenses(status, licenseType, batchNo string, page, pageSize int) ([]model.LicenseCode, int64, error) {

	var licenses []model.LicenseCode

	var total int64

	query := s.db.Model(&model.LicenseCode{})

	if status != "" {

		query = query.Where("status = ?", strings.ToLower(status))

	}

	if licenseType != "" {

		query = query.Where("license_type = ?", strings.ToLower(licenseType))

	}

	if batchNo != "" {

		query = query.Where("batch_no = ?", batchNo)

	}

	// 获取所有符合条件的授权码

	var allLicenses []model.LicenseCode

	if err := query.Find(&allLicenses).Error; err != nil {

		return nil, 0, err

	}

	// 检查每个授权码的有效性

	for i := range allLicenses {

		if allLicenses[i].Status == "used" {

			if err := s.CheckLicenseValidity(allLicenses[i].Code); err != nil {

				// 如果检查失败，更新状态

				s.db.Model(&allLicenses[i]).Update("status", "expired")

				allLicenses[i].Status = "expired"

			}

		}

	}

	total = int64(len(allLicenses))

	// 分页

	if page > 0 && pageSize > 0 {

		start := (page - 1) * pageSize

		end := start + pageSize

		if start < len(allLicenses) {

			if end > len(allLicenses) {

				end = len(allLicenses)

			}

			licenses = allLicenses[start:end]

		}

	} else {

		licenses = allLicenses

	}

	return licenses, total, nil

}

// 获取授权码使用日志

func (s *LicenseService) GetLicenseLogs(licenseID uint, page, pageSize int) ([]model.LicenseLog, int64, error) {

	var logs []model.LicenseLog

	var total int64

	query := s.db.Model(&model.LicenseLog{}).Where("license_id = ?", licenseID)

	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

}

// ExportLogs 导出授权码日志

func (s *LicenseService) ExportLogs(licenseID uint) ([]byte, error) {

	logs, _, err := s.GetLicenseLogs(licenseID, 0, 0) // 获取所有日志

	if err != nil {

		return nil, err

	}

	// 创建CSV内容

	var content strings.Builder

	content.WriteString("操作类,设备UID,IP地址,状态,详细信息,时间\n")

	for _, log := range logs {

		// 转换操作类型

		action := map[string]string{

			"create": "创建",

			"use": "使用",

			"verify": "验证",
		}[log.Action]

		// 转换状态

		status := map[string]string{

			"success": "成功",

			"failed": "失败",
		}[log.Status]

		// 写入一行记录

		content.WriteString(fmt.Sprintf("%s,%s,%s,%s,%s,%s\n",

			action,

			log.DeviceUID,

			log.IP,

			status,

			log.Message,

			log.CreatedAt.Format("2006-01-02 15:04:05"),
		))

	}

	return []byte(content.String()), nil

}

// 撤销授权码

func (s *LicenseService) RevokeLicense(code string, userID uint) error {

	var license model.LicenseCode

	if err := s.db.Where("code = ?", code).First(&license).Error; err != nil {

		return errors.New("授权码不存在")

	}

	// 检查权限

	if license.CreatedBy != userID {

		return errors.New("无权操作此授权码")

	}

	// 更新状态

	if err := s.db.Model(&license).Update("status", "revoked").Error; err != nil {

		return err

	}

	// 记录日志

	log := model.LicenseLog{

		LicenseID: license.ID,

		Action: "revoke",

		Status: "success",

		Message: "授权码已撤销",
	}

	s.db.Create(&log)

	return nil

}

// 批量撤销授权码

func (s *LicenseService) RevokeLicenses(codes []string, userID uint) error {

	return s.db.Transaction(func(tx *gorm.DB) error {

		for _, code := range codes {

			var license model.LicenseCode

			if err := tx.Where("code = ?", code).First(&license).Error; err != nil {

				continue

			}

			// 检查权限

			if license.CreatedBy != userID {

				continue

			}

			// 更新状态

			if err := tx.Model(&license).Update("status", "revoked").Error; err != nil {

				return err

			}

			// 记录日志

			log := model.LicenseLog{

				LicenseID: license.ID,

				Action: "revoke",

				Status: "success",

				Message: "授权码已撤销",
			}

			tx.Create(&log)

		}

		return nil

	})

}

// 验证授权码

func (s *LicenseService) ValidateLicense(code string) (*model.LicenseCode, error) {

	var license model.LicenseCode

	if err := s.db.Where("code = ?", code).First(&license).Error; err != nil {

		return nil, errors.New("无效的授权码")

	}

	// 检查状态

	if license.Status != "unused" {

		return nil, errors.New("授权码已被使用或已撤销")

	}

	return &license, nil

}

// 导出授权码

func (s *LicenseService) ExportLicenses(codes []string) ([]byte, error) {

	var licenses []model.LicenseCode

	if err := s.db.Where("code IN ?", codes).Find(&licenses).Error; err != nil {

		return nil, err

	}

	// 创建CSV内容

	var content strings.Builder

	content.WriteString("授权码,授权类型,有效期(天),使用次数,状态,使用设备,使用时间,批次号,备注\n")

	for _, license := range licenses {

		// 转换授权类型

		licenseType := map[string]string{

			"time": "时间授权",

			"count": "次数授权",

			"permanent": "永久授权",
		}[license.LicenseType]

		// 转换状态

		status := map[string]string{

			"unused": "未使用",

			"used": "已使用",

			"revoked": "已撤销",
		}[license.Status]

		// 写入一行记录

		content.WriteString(fmt.Sprintf("%s,%s,%d,%d,%s,%s,%s,%s,%s\n",

			license.Code,

			licenseType,

			license.Duration,

			license.MaxUses,

			status,

			license.UsedBy,

			license.UsedAt.Format("2006-01-02 15:04:05"),

			license.BatchNo,

			license.Remark,
		))

	}

	return []byte(content.String()), nil

}

// 获取授权码统计信息

func (s *LicenseService) GetLicenseStats() (map[string]interface{}, error) {

	var stats struct {
		Total int64

		Unused int64

		Used int64

		Revoked int64

		Today int64

		ThisWeek int64

		ThisMonth int64
	}

	// 获取总数

	s.db.Model(&model.LicenseCode{}).Count(&stats.Total)

	// 获取各状态数量

	s.db.Model(&model.LicenseCode{}).Where("status = ?", "unused").Count(&stats.Unused)

	s.db.Model(&model.LicenseCode{}).Where("status = ?", "used").Count(&stats.Used)

	s.db.Model(&model.LicenseCode{}).Where("status = ?", "revoked").Count(&stats.Revoked)

	// 获取今日创建数量

	today := time.Now().Format("2006-01-02")

	s.db.Model(&model.LicenseCode{}).Where("DATE(created_at) = ?", today).Count(&stats.Today)

	// 获取本周创建数量

	weekStart := time.Now().AddDate(0, 0, -int(time.Now().Weekday()))

	s.db.Model(&model.LicenseCode{}).Where("created_at >= ?", weekStart).Count(&stats.ThisWeek)

	// 获取本月创建数量

	monthStart := time.Now().Format("2006-01") + "-01"

	s.db.Model(&model.LicenseCode{}).Where("created_at >= ?", monthStart).Count(&stats.ThisMonth)

	return map[string]interface{}{

		"total": stats.Total,

		"unused": stats.Unused,

		"used": stats.Used,

		"revoked": stats.Revoked,

		"today": stats.Today,

		"this_week": stats.ThisWeek,

		"this_month": stats.ThisMonth,
	}, nil

}

// 添加检查授权码有效性的方法

func (s *LicenseService) CheckLicenseValidity(code string) error {

	var license model.LicenseCode

	if err := s.db.Where("code = ?", code).First(&license).Error; err != nil {

		return errors.New("授权码不存在")

	}

	if license.Status != "unused" && license.Status != "used" {

		return errors.New("授权码已被撤销或过期")

	}

	// 检查授权类型特定的限制

	switch license.LicenseType {
	case "time":
		// 计算过期时间

		expireTime := license.UsedAt.Add(time.Duration(license.Duration) * time.Minute)

		if time.Now().After(expireTime) {

			// 更新状态为过期

			s.db.Model(&license).Update("status", "expired")

			return errors.New("授权码已过期")

		}
	case "count":
		if license.UsedCount >= license.MaxUses {

			// 更新状态为过期

			s.db.Model(&license).Update("status", "expired")

			return errors.New("授权码使用次数已达上限")

		}
	}

	return nil

}

// GetLicenseByCode 通过授权码获取授权信息
func (s *LicenseService) GetLicenseByCode(code string) (*model.LicenseCode, error) {
	var license model.LicenseCode
	if err := s.db.Where("code = ?", code).First(&license).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("授权码不存在")
		}
		return nil, err
	}
	return &license, nil
}
