package admin

import (
	"context"
	"fmt"
	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
	adminApi "github.com/go-nunu/nunu-layout-advanced/api/v1/admin"
	"github.com/go-nunu/nunu-layout-advanced/internal/model"
	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
	"math"
	"strings"
	"time"
)

type WafLogRepository interface {
	GetWafLog(ctx context.Context, id int64) (*model.WafLog, error)
	GetWafLogList(ctx context.Context, req adminApi.SearchWafLogParams) (*v1.PaginatedResponse[model.WafLog], error)
	AddWafLog(ctx context.Context, log *model.WafLog) error
	BatchAddWafLog(ctx context.Context, logs []*model.WafLog) error
	// 导出日志
	ExportWafLog(ctx context.Context, req adminApi.ExportWafLog) ([]model.WafLog, error)
	// 支持分页的导出方法
	ExportWafLogWithPagination(ctx context.Context, req adminApi.ExportWafLog, page, pageSize int) ([]model.WafLog, error)
	// 获取导出数据总数
	GetWafLogExportCount(ctx context.Context, req adminApi.ExportWafLog) (int, error)
	// 获取网关组记录
	GetWafLogGateWayIp(ctx context.Context, hostId int64, Uid int64,createdAt time.Time) (model.WafLog, error)
	// 批量获取网关组记录
	BatchGetWafLogGateWayIps(ctx context.Context, hostIds []int64, uids []int64, maxCreatedAt time.Time) (map[string]model.WafLog, error)
}

func NewWafLogRepository(
	repository *repository.Repository,
) WafLogRepository {
	return &wafLogRepository{
		Repository: repository,
	}
}

type wafLogRepository struct {
	*repository.Repository
}

func (r *wafLogRepository) GetWafLog(ctx context.Context, id int64) (*model.WafLog, error) {
	var res model.WafLog
	return &res, r.DBWithName(ctx,"admin").Where("id = ?", id).First(&res).Error
}

func (r *wafLogRepository) GetWafLogList(ctx context.Context, req adminApi.SearchWafLogParams) (*v1.PaginatedResponse[model.WafLog], error) {
	var res []model.WafLog
	var total int64

	query := r.DBWithName(ctx,"admin").Model(&model.WafLog{})
	if  req.RequestIp != "" {
		trimmedName := strings.TrimSpace(req.RequestIp)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("request_ip LIKE CONCAT('%', ?, '%')", trimmedName)
	}


	if req.Uid != 0 {
		query = query.Where("uid = ?", req.Uid)
	}

	if req.Api != "" {
		trimmedName := strings.TrimSpace(req.Api)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("api LIKE CONCAT('%', ?, '%')", trimmedName)
	}

	if req.Name != "" {
		trimmedName := strings.TrimSpace(req.Name)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("name LIKE CONCAT('%', ?, '%')", trimmedName)
	}


	if req.RuleId != 0 {
		query = query.Where("rule_id = ?", req.RuleId)
	}

	if req.HostId != 0 {
		query = query.Where("host_id = ?", req.HostId)
	}

	if req.Api != "" {
		trimmedName := strings.TrimSpace(req.Api)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("api LIKE CONCAT('%', ?, '%')", trimmedName)
	}

	if req.UserAgent != "" {
		trimmedName := strings.TrimSpace(req.UserAgent)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("user_agent LIKE CONCAT('%', ?, '%')", trimmedName)
	}

	if req.ApiName != "" {
		trimmedName := strings.TrimSpace(req.ApiName)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("api_name LIKE CONCAT('%', ?, '%')", trimmedName)
	}

	if req.ApiType != "" {
		query = query.Where("api_type = ?", req.ApiType)
	}


	if req.Column != "" {
		query = query.Order(req.Column + " " + req.Order)
	}

	if err := query.Count(&total).Error; err != nil {
		// 如果连计数都失败了，直接返回错误
		return nil, err
	}


	page := req.Current
	pageSize := req.PageSize

	if page <= 0 {
		page = 1
	}

	if pageSize <= 0 {
		pageSize = 10 // 默认每页 10 条
	} else if pageSize > 100 {
		pageSize = 100 // 每页最多 100 条
	}

	// 计算 offset (偏移量)
	// 例如，第 1 页，offset = (1-1)*10 = 0 (从第0条开始)
	// 第 2 页，offset = (2-1)*10 = 10 (从第10条开始)
	offset := (page - 1) * pageSize
	// 3. 执行最终的查询
	// 在所有条件都添加完毕后，再执行 .Find()
	result := query.Offset(offset).Limit(pageSize).Find(&res)
	if result.Error != nil {
		// 这里的错误可能是数据库连接问题等，而不是“未找到记录”
		return nil, result.Error
	}
	return &v1.PaginatedResponse[model.WafLog]{
		Records: res,
		Page: page,
		PageSize: pageSize,
		Total: total,
		TotalPages: int(math.Ceil(float64(total) / float64(pageSize))),

	}, nil
}

func (r *wafLogRepository) AddWafLog(ctx context.Context, log *model.WafLog) error {
	return r.DBWithName(ctx,"admin").Create(log).Error
}

func (r *wafLogRepository) BatchAddWafLog(ctx context.Context, logs []*model.WafLog) error {
	if len(logs) == 0 {
		return nil
	}
	return r.DBWithName(ctx, "admin").CreateInBatches(logs, len(logs)).Error
}

func (r *wafLogRepository) ExportWafLog(ctx context.Context, req adminApi.ExportWafLog) ([]model.WafLog, error) {
	return r.ExportWafLogWithPagination(ctx, req, 0, 0)
}

// ExportWafLogWithPagination 支持分页的导出方法
func (r *wafLogRepository) ExportWafLogWithPagination(ctx context.Context, req adminApi.ExportWafLog, page, pageSize int) ([]model.WafLog, error) {
	var res []model.WafLog
	query := r.DBWithName(ctx,"admin").Model(&model.WafLog{})
	if  req.RequestIp != "" {
		trimmedName := strings.TrimSpace(req.RequestIp)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("request_ip = ?", trimmedName)
	}


	if req.Uid != 0 {
		query = query.Where("uid = ?", req.Uid)
	}

	if req.Api != "" {
		trimmedName := strings.TrimSpace(req.Api)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("api = ?", trimmedName)
	}

	if req.Name != "" {
		trimmedName := strings.TrimSpace(req.Name)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("name = ?", trimmedName)
	}


	if req.RuleId != 0 {
		query = query.Where("rule_id = ?", req.RuleId)
	}

		if len(req.HostIds) > 0 {
		query = query.Where("host_id IN ?", req.HostIds)
	}

	if req.Api != "" {
		trimmedName := strings.TrimSpace(req.Api)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("api = ?", trimmedName)
	}

	if req.UserAgent != "" {
		trimmedName := strings.TrimSpace(req.UserAgent)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("user_agent = ?", trimmedName)
	}

	if len(req.ApiNames) > 0 {
		trimmedNames := make([]string, len(req.ApiNames))
		for _, apiName := range req.ApiNames {
			trimmedNames = append(trimmedNames, strings.TrimSpace(apiName))
		}
		// 使用 LIKE 进行模糊匹配
		query = query.Where("api_name IN ?", trimmedNames)
	}

	if len(req.ApiTypes) > 0 {
		query = query.Where("api_type IN ?", req.ApiTypes)
	}


	if req.StartTime != "" {
		trimmedName := strings.TrimSpace(req.StartTime)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("create_at > ?", trimmedName)
	}

	if req.EndTime != "" {
		trimmedName := strings.TrimSpace(req.EndTime)
		// 使用 LIKE 进行模糊匹配
		query = query.Where("create_at < ?", trimmedName)
	}

	// 添加分页逻辑
	if page > 0 && pageSize > 0 {
		offset := (page - 1) * pageSize
		query = query.Offset(offset).Limit(pageSize)
	}

	result := query.Find(&res)
	if result.Error != nil {
		return nil, result.Error
	}
	return res, nil
}

// GetWafLogExportCount 获取导出数据总数
func (r *wafLogRepository) GetWafLogExportCount(ctx context.Context, req adminApi.ExportWafLog) (int, error) {
	var count int64
	query := r.DBWithName(ctx,"admin").Model(&model.WafLog{})
	
	// 复用ExportWafLog的查询条件
	if req.RequestIp != "" {
		trimmedName := strings.TrimSpace(req.RequestIp)
		query = query.Where("request_ip = ?", trimmedName)
	}

	if req.Uid != 0 {
		query = query.Where("uid = ?", req.Uid)
	}

	if req.Api != "" {
		trimmedName := strings.TrimSpace(req.Api)
		query = query.Where("api = ?", trimmedName)
	}

	if req.Name != "" {
		trimmedName := strings.TrimSpace(req.Name)
		query = query.Where("name = ?", trimmedName)
	}

	if req.RuleId != 0 {
		query = query.Where("rule_id = ?", req.RuleId)
	}

	if len(req.HostIds) > 0 {
		query = query.Where("host_id IN ?", req.HostIds)
	}

	if req.UserAgent != "" {
		trimmedName := strings.TrimSpace(req.UserAgent)
		query = query.Where("user_agent = ?", trimmedName)
	}

	if len(req.ApiNames) > 0 {
		trimmedNames := make([]string, len(req.ApiNames))
		for _, apiName := range req.ApiNames {
			trimmedNames = append(trimmedNames, strings.TrimSpace(apiName))
		}
		query = query.Where("api_name IN ?", trimmedNames)
	}

	if len(req.ApiTypes) > 0 {
		query = query.Where("api_type IN ?", req.ApiTypes)
	}

	if req.StartTime != "" {
		trimmedName := strings.TrimSpace(req.StartTime)
		query = query.Where("create_at > ?", trimmedName)
	}

	if req.EndTime != "" {
		trimmedName := strings.TrimSpace(req.EndTime)
		query = query.Where("create_at < ?", trimmedName)
	}

	result := query.Count(&count)
	if result.Error != nil {
		return 0, result.Error
	}
	return int(count), nil
}

func (r *wafLogRepository) GetWafLogGateWayIp(ctx context.Context, hostId int64, Uid int64,createdAt time.Time) (model.WafLog, error) {
	var res model.WafLog
	return res, r.DBWithName(ctx,"admin").Where("host_id = ? and uid = ? and api_name = ? and created_at < ? ", hostId, Uid, "分配网关组", createdAt).First(&res).Error
}

// BatchGetWafLogGateWayIps 批量获取网关组记录，避免N+1查询问题
func (r *wafLogRepository) BatchGetWafLogGateWayIps(ctx context.Context, hostIds []int64, uids []int64, maxCreatedAt time.Time) (map[string]model.WafLog, error) {
	if len(hostIds) == 0 || len(uids) == 0 {
		return make(map[string]model.WafLog), nil
	}

	var gateWayLogs []model.WafLog
	
	// 构建查询条件，获取所有相关的网关组记录
	query := r.DBWithName(ctx, "admin").
		Where("api_name = ?", "分配网关组").
		Where("created_at < ?", maxCreatedAt)
	
	// 如果hostIds和uids数量较少，使用IN查询
	if len(hostIds) <= 1000 && len(uids) <= 1000 {
		query = query.Where("host_id IN ? AND uid IN ?", hostIds, uids)
	}
	
	// 按创建时间倒序，确保获取最新的网关组配置
	err := query.Order("created_at DESC").Find(&gateWayLogs).Error
	if err != nil {
		return nil, err
	}

	// 构建映射表，key为"hostId_uid"，value为最新的网关组记录
	result := make(map[string]model.WafLog)
	for _, log := range gateWayLogs {
		key := fmt.Sprintf("%d_%d", log.HostId, log.Uid)
		// 由于已经按创建时间倒序排列，第一次遇到的就是最新的记录
		if _, exists := result[key]; !exists {
			result[key] = log
		}
	}

	return result, nil
}