package handler

import (
	"fmt"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"

	"github.com/user-management-system/internal/service"
)

// LogHandler handles log requests
type LogHandler struct {
	loginLogService     *service.LoginLogService
	operationLogService *service.OperationLogService
}

// NewLogHandler creates a new LogHandler
func NewLogHandler(loginLogService *service.LoginLogService, operationLogService *service.OperationLogService) *LogHandler {
	return &LogHandler{
		loginLogService:     loginLogService,
		operationLogService: operationLogService,
	}
}

// GetMyLoginLogs 获取我的登录日志
// @Summary 获取登录日志
// @Description 获取当前用户的登录日志
// @Tags 日志
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} Response{data=LoginLogListResponse} "登录日志列表"
// @Failure 401 {object} Response "未认证"
// @Router /api/v1/users/me/login-logs [get]
func (h *LogHandler) GetMyLoginLogs(c *gin.Context) {
	userID, ok := getUserIDFromContext(c)
	if !ok {
		c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "unauthorized"})
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	logs, total, err := h.loginLogService.GetMyLoginLogs(c.Request.Context(), userID, page, pageSize)
	if err != nil {
		handleError(c, err)
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "success",
		"data": gin.H{
			"list":      logs,
			"total":     total,
			"page":      page,
			"page_size": pageSize,
		},
	})
}

// GetMyOperationLogs 获取我的操作日志
// @Summary 获取操作日志
// @Description 获取当前用户的操作日志
// @Tags 日志
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} Response{data=OperationLogListResponse} "操作日志列表"
// @Failure 401 {object} Response "未认证"
// @Router /api/v1/users/me/operation-logs [get]
func (h *LogHandler) GetMyOperationLogs(c *gin.Context) {
	userID, ok := getUserIDFromContext(c)
	if !ok {
		c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "unauthorized"})
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	logs, total, err := h.operationLogService.GetMyOperationLogs(c.Request.Context(), userID, page, pageSize)
	if err != nil {
		handleError(c, err)
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "success",
		"data": gin.H{
			"list":      logs,
			"total":     total,
			"page":      page,
			"page_size": pageSize,
		},
	})
}

// GetLoginLogs 获取登录日志列表
// @Summary 获取登录日志列表
// @Description 获取所有登录日志（仅管理员），支持游标分页和偏移分页
// @Tags 日志
// @Produce json
// @Security BearerAuth
// @Param cursor query string false "游标分页游标"
// @Param size query int false "每页数量（游标模式）"
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} Response{data=LoginLogListResponse} "登录日志列表"
// @Failure 403 {object} Response "无权限"
// @Router /api/v1/admin/logs/login [get]
func (h *LogHandler) GetLoginLogs(c *gin.Context) {
	var req service.ListLoginLogRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
		return
	}

	// Use cursor-based pagination when cursor is provided
	if req.Cursor != "" || req.Size > 0 {
		result, err := h.loginLogService.GetLoginLogsCursor(c.Request.Context(), &req)
		if err != nil {
			handleError(c, err)
			return
		}
		c.JSON(http.StatusOK, gin.H{
			"code":    0,
			"message": "success",
			"data":    result,
		})
		return
	}

	// Fallback to legacy offset-based pagination
	logs, total, err := h.loginLogService.GetLoginLogs(c.Request.Context(), &req)
	if err != nil {
		handleError(c, err)
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "success",
		"data": gin.H{
			"list":      logs,
			"total":     total,
			"page":      req.Page,
			"page_size": req.PageSize,
		},
	})
}

// GetOperationLogs 获取操作日志列表
// @Summary 获取操作日志列表
// @Description 获取所有操作日志（仅管理员），支持游标分页和偏移分页
// @Tags 日志
// @Produce json
// @Security BearerAuth
// @Param cursor query string false "游标分页游标"
// @Param size query int false "每页数量（游标模式）"
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} Response{data=OperationLogListResponse} "操作日志列表"
// @Failure 403 {object} Response "无权限"
// @Failure 500 {object} Response "服务器错误"
// @Router /api/v1/admin/logs/operation [get]
func (h *LogHandler) GetOperationLogs(c *gin.Context) {
	var req service.ListOperationLogRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
		return
	}

	// Use cursor-based pagination when cursor is provided
	if req.Cursor != "" || req.Size > 0 {
		result, err := h.operationLogService.GetOperationLogsCursor(c.Request.Context(), &req)
		if err != nil {
			handleError(c, err)
			return
		}
		c.JSON(http.StatusOK, gin.H{
			"code":    0,
			"message": "success",
			"data":    result,
		})
		return
	}

	// Fallback to legacy offset-based pagination
	logs, total, err := h.operationLogService.GetOperationLogs(c.Request.Context(), &req)
	if err != nil {
		handleError(c, err)
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "success",
		"data": gin.H{
			"list":      logs,
			"total":     total,
			"page":      req.Page,
			"page_size": req.PageSize,
		},
	})
}

// ExportLoginLogs 导出登录日志
// @Summary 导出登录日志
// @Description 导出登录日志为 CSV 文件
// @Tags 日志
// @Produce json
// @Security BearerAuth
// @Param start_time query string false "开始时间"
// @Param end_time query string false "结束时间"
// @Param user_id query int64 false "用户ID"
// @Success 200 {file} file "CSV文件"
// @Failure 403 {object} Response "无权限"
// @Failure 500 {object} Response "服务器错误"
// @Router /api/v1/admin/logs/login/export [get]
func (h *LogHandler) ExportLoginLogs(c *gin.Context) {
	var req service.ExportLoginLogRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
		return
	}

	data, filename, contentType, err := h.loginLogService.ExportLoginLogs(c.Request.Context(), &req)
	if err != nil {
		handleError(c, err)
		return
	}

	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
	c.Data(http.StatusOK, contentType, data)
}
