package api

import (
	"context"
	"log/slog"
	"net/http"
	"strconv"
	"time"

	"github.com/TopherMayor/unified-media-manager/internal/service"
	"github.com/labstack/echo/v4"
)

type discoverResponse struct {
	Data []service.DiscoverItem `json:"data"`
	Page int                    `json:"page"`
}

type addFromDiscoverRequest struct {
	TMDBID    int    `json:"tmdb_id"`
	MediaType string `json:"media_type"`
}

type addFromDiscoverResponse struct {
	ID       int64 `json:"id"`
	Existing bool  `json:"existing,omitempty"`
}

func listTrending(svc *service.DiscoverService) echo.HandlerFunc {
	return func(c echo.Context) error {
		ctx, cancel := context.WithTimeout(c.Request().Context(), 15*time.Second)
		defer cancel()

		mediaType := c.QueryParam("type")
		if mediaType == "" {
			mediaType = "movie"
		}
		if mediaType != "movie" && mediaType != "series" {
			return c.JSON(http.StatusBadRequest, map[string]string{"error": "type must be 'movie' or 'series'"})
		}

		page, _ := strconv.Atoi(c.QueryParam("page"))
		if page < 1 {
			page = 1
		}
		if page > 10 {
			page = 10
		}

		items, err := svc.Trending(ctx, mediaType, page)
		if err != nil {
			slog.Error("list trending failed", "error", err)
			return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to fetch trending content"})
		}

		return c.JSON(http.StatusOK, discoverResponse{
			Data: items,
			Page: page,
		})
	}
}

func listPopular(svc *service.DiscoverService) echo.HandlerFunc {
	return func(c echo.Context) error {
		ctx, cancel := context.WithTimeout(c.Request().Context(), 15*time.Second)
		defer cancel()

		mediaType := c.QueryParam("type")
		if mediaType == "" {
			mediaType = "movie"
		}
		if mediaType != "movie" && mediaType != "series" {
			return c.JSON(http.StatusBadRequest, map[string]string{"error": "type must be 'movie' or 'series'"})
		}

		page, _ := strconv.Atoi(c.QueryParam("page"))
		if page < 1 {
			page = 1
		}
		if page > 10 {
			page = 10
		}

		items, err := svc.Popular(ctx, mediaType, page)
		if err != nil {
			slog.Error("list popular failed", "error", err)
			return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to fetch popular content"})
		}

		return c.JSON(http.StatusOK, discoverResponse{
			Data: items,
			Page: page,
		})
	}
}

func addFromDiscover(svc *service.DiscoverService) echo.HandlerFunc {
	return func(c echo.Context) error {
		ctx, cancel := context.WithTimeout(c.Request().Context(), 15*time.Second)
		defer cancel()

		var req addFromDiscoverRequest
		if err := c.Bind(&req); err != nil {
			return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request body"})
		}

		if req.TMDBID <= 0 {
			return c.JSON(http.StatusBadRequest, map[string]string{"error": "tmdb_id must be a positive integer"})
		}
		if req.MediaType != "movie" && req.MediaType != "series" {
			return c.JSON(http.StatusBadRequest, map[string]string{"error": "media_type must be 'movie' or 'series'"})
		}

		id, existing, err := svc.AddToLibrary(ctx, req.TMDBID, req.MediaType)
		if err != nil {
			slog.Error("add from discover failed", "tmdb_id", req.TMDBID, "error", err)
			return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to add item to library"})
		}

		status := http.StatusCreated
		if existing {
			status = http.StatusOK
		}

		return c.JSON(status, addFromDiscoverResponse{
			ID:       id,
			Existing: existing,
		})
	}
}
