package service

import (
	"fmt"
	"time"
	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
)

type UsageAlertService struct{}

func NewUsageAlertService() *UsageAlertService {
	return &UsageAlertService{}
}

type AlertType string

const (
	AlertTypeAPICalls   AlertType = "api_calls"
	AlertTypeStorage    AlertType = "storage"
	AlertTypePackageExp AlertType = "package_expiry"
)

type AlertLevel string

const (
	AlertLevelWarning  AlertLevel = "warning"
	AlertLevelCritical AlertLevel = "critical"
)

type UsageAlert struct {
	UserID    uint       `json:"user_id"`
	Type      AlertType  `json:"type"`
	Level     AlertLevel `json:"level"`
	Message   string     `json:"message"`
	Usage     float64    `json:"usage"`
	Limit     float64    `json:"limit"`
	Percent   float64    `json:"percent"`
	CreatedAt time.Time  `json:"created_at"`
}

func (s *UsageAlertService) CheckAndCreateAlerts(userID uint) ([]UsageAlert, error) {
	var alerts []UsageAlert

	var user model.User
	if err := database.DB.Preload("CurrentPackage").First(&user, userID).Error; err != nil {
		return nil, err
	}

	if user.CurrentPackageID == nil {
		return alerts, nil
	}

	var permission model.PackagePermission
	if err := database.DB.Where("package_id = ?", user.CurrentPackageID).First(&permission).Error; err != nil {
		return nil, err
	}

	if alert := s.checkAPICallsUsage(&user, &permission); alert != nil {
		alerts = append(alerts, *alert)
	}

	if alert := s.checkStorageUsage(&user, &permission); alert != nil {
		alerts = append(alerts, *alert)
	}

	if alert := s.checkPackageExpiry(&user); alert != nil {
		alerts = append(alerts, *alert)
	}

	for _, alert := range alerts {
		s.sendNotification(&alert)
	}

	return alerts, nil
}

func (s *UsageAlertService) checkAPICallsUsage(user *model.User, permission *model.PackagePermission) *UsageAlert {
	if permission.MaxApiCalls == 0 {
		return nil
	}

	usagePercent := float64(user.ApiCallsUsed) / float64(permission.MaxApiCalls) * 100

	var lastAlert model.UsageAlertRecord
	hasRecentAlert := database.DB.Where(
		"user_id = ? AND type = ? AND created_at > ?",
		user.ID,
		AlertTypeAPICalls,
		time.Now().Add(-24*time.Hour),
	).First(&lastAlert).Error == nil

	if hasRecentAlert {
		return nil
	}

	if usagePercent >= 90 {
		return &UsageAlert{
			UserID:  user.ID,
			Type:    AlertTypeAPICalls,
			Level:   AlertLevelCritical,
			Message: fmt.Sprintf("API调用次数已使用 %.1f%%，即将达到上限", usagePercent),
			Usage:   float64(user.ApiCallsUsed),
			Limit:   float64(permission.MaxApiCalls),
			Percent: usagePercent,
		}
	}

	if usagePercent >= 80 {
		return &UsageAlert{
			UserID:  user.ID,
			Type:    AlertTypeAPICalls,
			Level:   AlertLevelWarning,
			Message: fmt.Sprintf("API调用次数已使用 %.1f%%，请注意用量", usagePercent),
			Usage:   float64(user.ApiCallsUsed),
			Limit:   float64(permission.MaxApiCalls),
			Percent: usagePercent,
		}
	}

	return nil
}

func (s *UsageAlertService) checkStorageUsage(user *model.User, permission *model.PackagePermission) *UsageAlert {
	if permission.MaxStorage == 0 {
		return nil
	}

	usagePercent := float64(user.StorageUsed) / float64(int64(permission.MaxStorage)*1024*1024) * 100

	var lastAlert model.UsageAlertRecord
	hasRecentAlert := database.DB.Where(
		"user_id = ? AND type = ? AND created_at > ?",
		user.ID,
		AlertTypeStorage,
		time.Now().Add(-24*time.Hour),
	).First(&lastAlert).Error == nil

	if hasRecentAlert {
		return nil
	}

	if usagePercent >= 90 {
		return &UsageAlert{
			UserID:  user.ID,
			Type:    AlertTypeStorage,
			Level:   AlertLevelCritical,
			Message: fmt.Sprintf("存储空间已使用 %.1f%%，即将达到上限", usagePercent),
			Usage:   float64(user.StorageUsed) / 1024 / 1024,
			Limit:   float64(permission.MaxStorage),
			Percent: usagePercent,
		}
	}

	if usagePercent >= 80 {
		return &UsageAlert{
			UserID:  user.ID,
			Type:    AlertTypeStorage,
			Level:   AlertLevelWarning,
			Message: fmt.Sprintf("存储空间已使用 %.1f%%，请注意用量", usagePercent),
			Usage:   float64(user.StorageUsed) / 1024 / 1024,
			Limit:   float64(permission.MaxStorage),
			Percent: usagePercent,
		}
	}

	return nil
}

func (s *UsageAlertService) checkPackageExpiry(user *model.User) *UsageAlert {
	var userPackage model.UserPackage
	if err := database.DB.Where(
		"user_id = ? AND package_id = ? AND status = ?",
		user.ID,
		user.CurrentPackageID,
		"active",
	).First(&userPackage).Error; err != nil {
		return nil
	}

	if userPackage.ExpiredAt == nil {
		return nil
	}

	daysUntilExpiry := time.Until(*userPackage.ExpiredAt).Hours() / 24

	var lastAlert model.UsageAlertRecord
	hasRecentAlert := database.DB.Where(
		"user_id = ? AND type = ? AND created_at > ?",
		user.ID,
		AlertTypePackageExp,
		time.Now().Add(-24*time.Hour),
	).First(&lastAlert).Error == nil

	if hasRecentAlert {
		return nil
	}

	if daysUntilExpiry <= 3 {
		return &UsageAlert{
			UserID:  user.ID,
			Type:    AlertTypePackageExp,
			Level:   AlertLevelCritical,
			Message: fmt.Sprintf("套餐将在 %.0f 天后过期，请及时续费", daysUntilExpiry),
			Usage:   daysUntilExpiry,
			Limit:   0,
			Percent: 0,
		}
	}

	if daysUntilExpiry <= 7 {
		return &UsageAlert{
			UserID:  user.ID,
			Type:    AlertTypePackageExp,
			Level:   AlertLevelWarning,
			Message: fmt.Sprintf("套餐将在 %.0f 天后过期，请及时续费", daysUntilExpiry),
			Usage:   daysUntilExpiry,
			Limit:   0,
			Percent: 0,
		}
	}

	return nil
}

func (s *UsageAlertService) sendNotification(alert *UsageAlert) {
	alertRecord := model.UsageAlertRecord{
		UserID:    alert.UserID,
		Type:      string(alert.Type),
		Level:     string(alert.Level),
		Message:   alert.Message,
		Usage:     alert.Usage,
		Limit:     alert.Limit,
		Percent:   alert.Percent,
		Status:    "sent",
		CreatedAt: time.Now(),
	}
	database.DB.Create(&alertRecord)

	notification := model.Notification{
		UserID:    alert.UserID,
		Title:     "用量告警",
		Content:   alert.Message,
		Type:      "usage_alert",
		IsRead:    false,
		CreatedAt: time.Now(),
	}
	database.DB.Create(&notification)
}

func (s *UsageAlertService) CheckAllUsers() error {
	var users []model.User
	if err := database.DB.Where("current_package_id IS NOT NULL").Find(&users).Error; err != nil {
		return err
	}

	for _, user := range users {
		_, err := s.CheckAndCreateAlerts(user.ID)
		if err != nil {
			fmt.Printf("检查用户 %d 用量告警失败: %v\n", user.ID, err)
		}
	}

	return nil
}

func (s *UsageAlertService) GetUserAlerts(userID uint, limit int) ([]model.UsageAlertRecord, error) {
	var alerts []model.UsageAlertRecord
	err := database.DB.Where("user_id = ?", userID).
		Order("created_at DESC").
		Limit(limit).
		Find(&alerts).Error
	return alerts, err
}

func (s *UsageAlertService) MarkAlertAsRead(alertID uint) error {
	return database.DB.Model(&model.UsageAlertRecord{}).
		Where("id = ?", alertID).
		Update("status", "read").Error
}
