package service

import (
	"context"
	"fmt"
	"gemini-balancer/internal/models"
	"strconv"
	"strings"

	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

type LogService struct {
	db     *gorm.DB
	logger *logrus.Entry
}

func NewLogService(db *gorm.DB, logger *logrus.Logger) *LogService {
	return &LogService{
		db:     db,
		logger: logger.WithField("component", "LogService"),
	}
}

func (s *LogService) Record(ctx context.Context, log *models.RequestLog) error {
	return s.db.WithContext(ctx).Create(log).Error
}

// LogQueryParams 解耦 Gin，使用结构体传参
type LogQueryParams struct {
	Page        int
	PageSize    int
	ModelName   string
	IsSuccess   *bool // 使用指针区分"未设置"和"false"
	StatusCode  *int
	KeyIDs      []string
	GroupIDs    []string
	Q           string
	ErrorCodes  []string
	StatusCodes []string
}

func (s *LogService) GetLogs(ctx context.Context, params LogQueryParams) ([]models.RequestLog, int64, error) {
	// 参数校验
	if params.Page < 1 {
		params.Page = 1
	}
	if params.PageSize < 1 || params.PageSize > 100 {
		params.PageSize = 20
	}

	var logs []models.RequestLog
	var total int64

	// 构建基础查询
	query := s.db.WithContext(ctx).Model(&models.RequestLog{})
	query = s.applyFilters(query, params)
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("failed to count logs: %w", err)
	}
	if total == 0 {
		return []models.RequestLog{}, 0, nil
	}
	offset := (params.Page - 1) * params.PageSize
	if err := query.Order("request_time DESC").
		Limit(params.PageSize).
		Offset(offset).
		Find(&logs).Error; err != nil {
		return nil, 0, fmt.Errorf("failed to query logs: %w", err)
	}
	return logs, total, nil
}

func (s *LogService) applyFilters(query *gorm.DB, params LogQueryParams) *gorm.DB {
	if params.ModelName != "" {
		query = query.Where("model_name = ?", params.ModelName)
	}
	if params.IsSuccess != nil {
		query = query.Where("is_success = ?", *params.IsSuccess)
	}
	if params.StatusCode != nil {
		query = query.Where("status_code = ?", *params.StatusCode)
	}
	if len(params.KeyIDs) > 0 {
		query = query.Where("key_id IN (?)", params.KeyIDs)
	}
	if len(params.GroupIDs) > 0 {
		query = query.Where("group_id IN (?)", params.GroupIDs)
	}
	if len(params.ErrorCodes) > 0 {
		query = query.Where("error_code IN (?)", params.ErrorCodes)
	}
	if len(params.StatusCodes) > 0 {
		query = query.Where("status_code IN (?)", params.StatusCodes)
	}
	if params.Q != "" {
		searchQuery := "%" + params.Q + "%"
		query = query.Where(
			"model_name LIKE ? OR error_code LIKE ? OR error_message LIKE ? OR CAST(status_code AS CHAR) LIKE ?",
			searchQuery, searchQuery, searchQuery, searchQuery,
		)
	}
	return query
}

// ParseLogQueryParams 在 Handler 层调用，解析 Gin 参数
func ParseLogQueryParams(queryParams map[string]string) (LogQueryParams, error) {
	params := LogQueryParams{
		Page:     1,
		PageSize: 20,
	}

	if pageStr, ok := queryParams["page"]; ok {
		if page, err := strconv.Atoi(pageStr); err == nil && page > 0 {
			params.Page = page
		}
	}

	if pageSizeStr, ok := queryParams["page_size"]; ok {
		if pageSize, err := strconv.Atoi(pageSizeStr); err == nil && pageSize > 0 {
			params.PageSize = pageSize
		}
	}

	if modelName, ok := queryParams["model_name"]; ok {
		params.ModelName = modelName
	}

	if isSuccessStr, ok := queryParams["is_success"]; ok {
		if isSuccess, err := strconv.ParseBool(isSuccessStr); err == nil {
			params.IsSuccess = &isSuccess
		} else {
			return params, fmt.Errorf("invalid is_success parameter: %s", isSuccessStr)
		}
	}

	if statusCodeStr, ok := queryParams["status_code"]; ok {
		if statusCode, err := strconv.Atoi(statusCodeStr); err == nil {
			params.StatusCode = &statusCode
		} else {
			return params, fmt.Errorf("invalid status_code parameter: %s", statusCodeStr)
		}
	}

	if keyIDsStr, ok := queryParams["key_ids"]; ok {
		params.KeyIDs = strings.Split(keyIDsStr, ",")
	}

	if groupIDsStr, ok := queryParams["group_ids"]; ok {
		params.GroupIDs = strings.Split(groupIDsStr, ",")
	}

	if errorCodesStr, ok := queryParams["error_codes"]; ok {
		params.ErrorCodes = strings.Split(errorCodesStr, ",")
	}
	if statusCodesStr, ok := queryParams["status_codes"]; ok {
		params.StatusCodes = strings.Split(statusCodesStr, ",")
	}
	if q, ok := queryParams["q"]; ok {
		params.Q = q
	}
	return params, nil
}
