package handlers

import (
	"context"
	"os"

	"Yimaru-Backend/internal/domain"
	"github.com/gofiber/fiber/v2"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// GetLogsHandler godoc
// @Summary Retrieve application logs with filtering and pagination
// @Description Fetches application logs from MongoDB with pagination, level filtering, and search
// @Tags Logs
// @Produce json
// @Param level query string false "Filter logs by level (debug, info, warn, error, dpanic, panic, fatal)"
// @Param search query string false "Search term to match against message or fields"
// @Param page query int false "Page number for pagination (default: 1)" default(1)
// @Param limit query int false "Number of items per page (default: 50, max: 100)" default(50)
// @Success 200 {object} domain.LogResponse "Paginated list of application logs"
// @Failure 400 {object} domain.ErrorResponse "Invalid request parameters"
// @Failure 500 {object} domain.ErrorResponse "Internal server error"
// @Router /api/v1/logs [get]
func GetLogsHandler(appCtx context.Context) fiber.Handler {
	return func(c *fiber.Ctx) error {
		// Get query parameters
		levelFilter := c.Query("level")
		searchTerm := c.Query("search")
		page := c.QueryInt("page", 1)
		limit := c.QueryInt("limit", 50)

		// Validate pagination parameters
		if page < 1 {
			page = 1
		}
		if limit < 1 || limit > 100 {
			limit = 50
		}

		// Calculate skip value for pagination
		skip := (page - 1) * limit

		client, err := mongo.Connect(appCtx, options.Client().ApplyURI(os.Getenv("MONGODB_URL")))
		if err != nil {
			return fiber.NewError(fiber.StatusInternalServerError, "MongoDB connection failed: "+err.Error())
		}
		defer client.Disconnect(appCtx)

		collection := client.Database("logdb").Collection("applogs")

		// Build filter
		filter := bson.M{}

		// Add level filter if specified
		if levelFilter != "" {
			validLevels := map[string]bool{
				"debug":  true,
				"info":   true,
				"warn":   true,
				"error":  true,
				"dpanic": true,
				"panic":  true,
				"fatal":  true,
			}

			if !validLevels[levelFilter] {
				return fiber.NewError(fiber.StatusBadRequest, "Invalid log level specified")
			}
			filter["level"] = levelFilter
		}

		// Add search filter if specified
		if searchTerm != "" {
			filter["$or"] = []bson.M{
				{"message": bson.M{"$regex": searchTerm, "$options": "i"}},
				{"fields": bson.M{"$elemMatch": bson.M{"$regex": searchTerm, "$options": "i"}}},
			}
		}

		// Find options with pagination and sorting
		opts := options.Find().
			SetSort(bson.D{{Key: "timestamp", Value: -1}}).
			SetSkip(int64(skip)).
			SetLimit(int64(limit))

		// Get total count for pagination metadata
		total, err := collection.CountDocuments(appCtx, filter)
		if err != nil {
			return fiber.NewError(fiber.StatusInternalServerError, "Failed to count logs: "+err.Error())
		}

		// Find logs
		cursor, err := collection.Find(appCtx, filter, opts)
		if err != nil {
			return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch logs: "+err.Error())
		}
		defer cursor.Close(appCtx)

		var logs []domain.LogEntry = make([]domain.LogEntry, 0)
		if err := cursor.All(appCtx, &logs); err != nil {
			return fiber.NewError(fiber.StatusInternalServerError, "Cursor decoding error: "+err.Error())
		}

		// Calculate pagination metadata
		totalPages := int(total) / limit
		if int(total)%limit != 0 {
			totalPages++
		}

		// Prepare response
		response := domain.LogResponse{
			Message: "Logs fetched successfully",
			Data:    logs,
			Pagination: domain.Pagination{
				Total:       int(total),
				TotalPages:  totalPages,
				CurrentPage: page,
				Limit:       limit,
			},
		}

		return c.JSON(response)
	}
}
