package admin

import (
	"github.com/gofiber/fiber/v2"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/service/polling"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"github.com/break/junhong_cmp_fiber/pkg/response"
)

// PollingCleanupHandler 轮询数据清理处理器
type PollingCleanupHandler struct {
	service *polling.CleanupService
}

// NewPollingCleanupHandler 创建轮询数据清理处理器
func NewPollingCleanupHandler(service *polling.CleanupService) *PollingCleanupHandler {
	return &PollingCleanupHandler{service: service}
}

// CreateConfig 创建清理配置
// @Summary 创建数据清理配置
// @Description 创建新的数据清理配置
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.CreateDataCleanupConfigReq true "创建请求"
// @Success 200 {object} response.Response{data=dto.DataCleanupConfigResp}
// @Router /api/admin/data-cleanup-configs [post]
func (h *PollingCleanupHandler) CreateConfig(c *fiber.Ctx) error {
	ctx := c.UserContext()

	var req dto.CreateDataCleanupConfigReq
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}

	config := &model.DataCleanupConfig{
		TargetTable:   req.TargetTable,
		RetentionDays: req.RetentionDays,
		BatchSize:     req.BatchSize,
		Description:   req.Description,
	}

	if err := h.service.CreateConfig(ctx, config); err != nil {
		return err
	}

	return response.Success(c, h.toConfigResp(config))
}

// ListConfigs 获取清理配置列表
// @Summary 获取数据清理配置列表
// @Description 获取所有数据清理配置
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.Response{data=dto.DataCleanupConfigListResp}
// @Router /api/admin/data-cleanup-configs [get]
func (h *PollingCleanupHandler) ListConfigs(c *fiber.Ctx) error {
	ctx := c.UserContext()

	configs, err := h.service.ListConfigs(ctx)
	if err != nil {
		return err
	}

	items := make([]*dto.DataCleanupConfigResp, 0, len(configs))
	for _, config := range configs {
		items = append(items, h.toConfigResp(config))
	}

	return response.Success(c, &dto.DataCleanupConfigListResp{Items: items})
}

// GetConfig 获取清理配置详情
// @Summary 获取数据清理配置详情
// @Description 获取指定数据清理配置的详细信息
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "配置ID"
// @Success 200 {object} response.Response{data=dto.DataCleanupConfigResp}
// @Router /api/admin/data-cleanup-configs/{id} [get]
func (h *PollingCleanupHandler) GetConfig(c *fiber.Ctx) error {
	ctx := c.UserContext()
	id, err := c.ParamsInt("id")
	if err != nil || id <= 0 {
		return errors.New(errors.CodeInvalidParam, "无效的配置ID")
	}

	config, err := h.service.GetConfig(ctx, uint(id))
	if err != nil {
		return err
	}

	return response.Success(c, h.toConfigResp(config))
}

// UpdateConfig 更新清理配置
// @Summary 更新数据清理配置
// @Description 更新指定数据清理配置
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "配置ID"
// @Param request body dto.UpdateDataCleanupConfigReq true "更新请求"
// @Success 200 {object} response.Response
// @Router /api/admin/data-cleanup-configs/{id} [put]
func (h *PollingCleanupHandler) UpdateConfig(c *fiber.Ctx) error {
	ctx := c.UserContext()
	id, err := c.ParamsInt("id")
	if err != nil || id <= 0 {
		return errors.New(errors.CodeInvalidParam, "无效的配置ID")
	}

	var req dto.UpdateDataCleanupConfigReq
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}

	updates := make(map[string]any)
	if req.RetentionDays != nil {
		updates["retention_days"] = *req.RetentionDays
	}
	if req.BatchSize != nil {
		updates["batch_size"] = *req.BatchSize
	}
	if req.Enabled != nil {
		updates["enabled"] = *req.Enabled
	}
	if req.Description != nil {
		updates["description"] = *req.Description
	}

	// 获取当前用户ID
	userID := middleware.GetUserIDFromContext(ctx)
	if userID > 0 {
		updates["updated_by"] = userID
	}

	if err := h.service.UpdateConfig(ctx, uint(id), updates); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// DeleteConfig 删除清理配置
// @Summary 删除数据清理配置
// @Description 删除指定数据清理配置
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "配置ID"
// @Success 200 {object} response.Response
// @Router /api/admin/data-cleanup-configs/{id} [delete]
func (h *PollingCleanupHandler) DeleteConfig(c *fiber.Ctx) error {
	ctx := c.UserContext()
	id, err := c.ParamsInt("id")
	if err != nil || id <= 0 {
		return errors.New(errors.CodeInvalidParam, "无效的配置ID")
	}

	if err := h.service.DeleteConfig(ctx, uint(id)); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// ListLogs 获取清理日志列表
// @Summary 获取数据清理日志列表
// @Description 获取数据清理日志记录
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param table_name query string false "表名筛选"
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} response.Response{data=dto.DataCleanupLogListResp}
// @Router /api/admin/data-cleanup-logs [get]
func (h *PollingCleanupHandler) ListLogs(c *fiber.Ctx) error {
	ctx := c.UserContext()

	var req dto.ListDataCleanupLogReq
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}

	if req.Page < 1 {
		req.Page = 1
	}
	if req.PageSize < 1 || req.PageSize > 100 {
		req.PageSize = 20
	}

	logs, total, err := h.service.ListLogs(ctx, req.Page, req.PageSize, req.TableName)
	if err != nil {
		return err
	}

	items := make([]*dto.DataCleanupLogResp, 0, len(logs))
	for _, log := range logs {
		items = append(items, h.toLogResp(log))
	}

	return response.Success(c, &dto.DataCleanupLogListResp{
		Items:    items,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	})
}

// Preview 预览待清理数据
// @Summary 预览待清理数据
// @Description 预览各表待清理的数据量
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.Response{data=dto.DataCleanupPreviewResp}
// @Router /api/admin/data-cleanup/preview [get]
func (h *PollingCleanupHandler) Preview(c *fiber.Ctx) error {
	ctx := c.UserContext()

	previews, err := h.service.Preview(ctx)
	if err != nil {
		return err
	}

	items := make([]*dto.DataCleanupPreviewItem, 0, len(previews))
	for _, p := range previews {
		items = append(items, &dto.DataCleanupPreviewItem{
			TableName:     p.TableName,
			RetentionDays: p.RetentionDays,
			RecordCount:   p.RecordCount,
			Description:   p.Description,
		})
	}

	return response.Success(c, &dto.DataCleanupPreviewResp{Items: items})
}

// GetProgress 获取清理进度
// @Summary 获取数据清理进度
// @Description 获取当前数据清理任务的进度
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.Response{data=dto.DataCleanupProgressResp}
// @Router /api/admin/data-cleanup/progress [get]
func (h *PollingCleanupHandler) GetProgress(c *fiber.Ctx) error {
	ctx := c.UserContext()

	progress, err := h.service.GetProgress(ctx)
	if err != nil {
		return err
	}

	resp := &dto.DataCleanupProgressResp{
		IsRunning:       progress.IsRunning,
		CurrentTable:    progress.CurrentTable,
		TotalTables:     progress.TotalTables,
		ProcessedTables: progress.ProcessedTables,
		TotalDeleted:    progress.TotalDeleted,
		StartedAt:       progress.StartedAt,
	}

	if progress.LastLog != nil {
		resp.LastLog = h.toLogResp(progress.LastLog)
	}

	return response.Success(c, resp)
}

// TriggerCleanup 手动触发清理
// @Summary 手动触发数据清理
// @Description 手动触发数据清理任务
// @Tags 轮询管理-数据清理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.TriggerDataCleanupReq true "触发请求"
// @Success 200 {object} response.Response
// @Router /api/admin/data-cleanup/trigger [post]
func (h *PollingCleanupHandler) TriggerCleanup(c *fiber.Ctx) error {
	ctx := c.UserContext()

	var req dto.TriggerDataCleanupReq
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}

	// 获取当前用户ID
	userID := middleware.GetUserIDFromContext(ctx)

	// 异步执行清理
	go func() {
		_ = h.service.TriggerCleanup(ctx, req.TableName, userID)
	}()

	return response.Success(c, nil)
}

func (h *PollingCleanupHandler) toConfigResp(config *model.DataCleanupConfig) *dto.DataCleanupConfigResp {
	return &dto.DataCleanupConfigResp{
		ID:            config.ID,
		TargetTable:   config.TargetTable,
		RetentionDays: config.RetentionDays,
		BatchSize:     config.BatchSize,
		Enabled:       int(config.Enabled),
		Description:   config.Description,
		CreatedAt:     config.CreatedAt,
		UpdatedAt:     config.UpdatedAt,
		UpdatedBy:     config.UpdatedBy,
	}
}

func (h *PollingCleanupHandler) toLogResp(log *model.DataCleanupLog) *dto.DataCleanupLogResp {
	return &dto.DataCleanupLogResp{
		ID:            log.ID,
		TargetTable:   log.TargetTable,
		CleanupType:   log.CleanupType,
		RetentionDays: log.RetentionDays,
		DeletedCount:  log.DeletedCount,
		DurationMs:    log.DurationMs,
		Status:        log.Status,
		ErrorMessage:  log.ErrorMessage,
		StartedAt:     log.StartedAt,
		CompletedAt:   log.CompletedAt,
		TriggeredBy:   log.TriggeredBy,
	}
}
