package dashboard

import (
	"strconv"
	"tm/pkg/response"

	"github.com/labstack/echo/v4"
)

// Handler handles dashboard HTTP requests.
type Handler struct {
	service Service
}

// NewHandler creates a dashboard handler.
func NewHandler(service Service) *Handler {
	return &Handler{service: service}
}

// Summary returns top-level dashboard counters.
// @Summary Dashboard summary
// @Description Top-level counters for hero pills and stat cards
// @Tags Admin-Dashboard
// @Produce json
// @Param closing_window query int false "Hours considered closing soon (default 168)"
// @Success 200 {object} response.APIResponse{data=SummaryResponse}
// @Failure 500 {object} response.APIResponse
// @Router /admin/v1/dashboard/summary [get]
// @Security BearerAuth
func (h *Handler) Summary(c echo.Context) error {
	query := SummaryQuery{
		ClosingWindow: parseIntQuery(c, "closing_window", 0),
	}

	out, err := h.service.Summary(c.Request().Context(), query)
	if err != nil {
		return response.InternalServerError(c, "Failed to load dashboard summary")
	}

	setPrivateCache(c, 60)
	return response.Success(c, out, "Dashboard summary retrieved successfully")
}

// Trend returns per-day tender counts for the flow chart.
// @Summary Dashboard trend
// @Description Per-day counts for the tender flow chart
// @Tags Admin-Dashboard
// @Produce json
// @Param days query int false "Days back (default 14, max 90)"
// @Param metric query string false "created|published|awarded (default created)"
// @Success 200 {object} response.APIResponse{data=TrendResponse}
// @Failure 500 {object} response.APIResponse
// @Router /admin/v1/dashboard/trend [get]
// @Security BearerAuth
func (h *Handler) Trend(c echo.Context) error {
	query := TrendQuery{
		Days:   parseIntQuery(c, "days", 0),
		Metric: c.QueryParam("metric"),
	}

	out, err := h.service.Trend(c.Request().Context(), query)
	if err != nil {
		return response.InternalServerError(c, "Failed to load dashboard trend")
	}

	setPrivateCache(c, 60)
	return response.Success(c, out, "Dashboard trend retrieved successfully")
}

// Countries returns country distribution buckets.
// @Summary Dashboard countries
// @Description Country distribution for donut and ranking list
// @Tags Admin-Dashboard
// @Produce json
// @Param limit query int false "Top N countries (default 6)"
// @Success 200 {object} response.APIResponse{data=CountriesResponse}
// @Failure 500 {object} response.APIResponse
// @Router /admin/v1/dashboard/countries [get]
// @Security BearerAuth
func (h *Handler) Countries(c echo.Context) error {
	query := CountriesQuery{
		Limit: parseIntQuery(c, "limit", 0),
	}

	out, err := h.service.Countries(c.Request().Context(), query)
	if err != nil {
		return response.InternalServerError(c, "Failed to load dashboard countries")
	}

	setPrivateCache(c, 60)
	return response.Success(c, out, "Dashboard countries retrieved successfully")
}

// NoticeTypes returns notice type distribution.
// @Summary Dashboard notice types
// @Description Notice type mix for stacked bars
// @Tags Admin-Dashboard
// @Produce json
// @Success 200 {object} response.APIResponse{data=NoticeTypesResponse}
// @Failure 500 {object} response.APIResponse
// @Router /admin/v1/dashboard/notice-types [get]
// @Security BearerAuth
func (h *Handler) NoticeTypes(c echo.Context) error {
	out, err := h.service.NoticeTypes(c.Request().Context())
	if err != nil {
		return response.InternalServerError(c, "Failed to load dashboard notice types")
	}

	setPrivateCache(c, 60)
	return response.Success(c, out, "Dashboard notice types retrieved successfully")
}

// ClosingSoon returns tenders closing within the configured window.
// @Summary Dashboard closing soon
// @Description Actionable tenders sorted by urgency
// @Tags Admin-Dashboard
// @Produce json
// @Param limit query int false "Max rows (default 5, max 20)"
// @Param window query int false "Hours horizon (default 168)"
// @Success 200 {object} response.APIResponse{data=ClosingSoonResponse}
// @Failure 500 {object} response.APIResponse
// @Router /admin/v1/dashboard/closing-soon [get]
// @Security BearerAuth
func (h *Handler) ClosingSoon(c echo.Context) error {
	query := ClosingSoonQuery{
		Limit:  parseIntQuery(c, "limit", 0),
		Window: parseIntQuery(c, "window", 0),
	}

	out, err := h.service.ClosingSoon(c.Request().Context(), query)
	if err != nil {
		return response.InternalServerError(c, "Failed to load closing soon tenders")
	}

	return response.Success(c, out, "Closing soon tenders retrieved successfully")
}

// Recent returns the most recently created tenders.
// @Summary Dashboard recent tenders
// @Description Recent tenders feed sorted by created_at
// @Tags Admin-Dashboard
// @Produce json
// @Param limit query int false "Max rows (default 5, max 20)"
// @Param cursor query string false "Opaque pagination cursor"
// @Success 200 {object} response.APIResponse{data=RecentResponse}
// @Failure 500 {object} response.APIResponse
// @Router /admin/v1/dashboard/recent [get]
// @Security BearerAuth
func (h *Handler) Recent(c echo.Context) error {
	query := RecentQuery{
		Limit:  parseIntQuery(c, "limit", 0),
		Cursor: c.QueryParam("cursor"),
	}

	out, err := h.service.Recent(c.Request().Context(), query)
	if err != nil {
		return response.InternalServerError(c, "Failed to load recent tenders")
	}

	setPrivateCache(c, 60)
	return response.Success(c, out, "Recent tenders retrieved successfully")
}

// Statistics returns scraping and translation statistics for charts.
// @Summary Dashboard statistics report
// @Description Daily and lifetime statistics for TED scraping, document scraping, and AI translation
// @Tags Admin-Dashboard
// @Produce json
// @Param days query int false "Days back for daily series (default 14, max 90)"
// @Success 200 {object} response.APIResponse{data=StatisticsReportResponse}
// @Failure 500 {object} response.APIResponse
// @Router /admin/v1/dashboard/statistics [get]
// @Security BearerAuth
func (h *Handler) Statistics(c echo.Context) error {
	query := StatisticsQuery{
		Days: parseIntQuery(c, "days", 0),
	}

	out, err := h.service.Statistics(c.Request().Context(), query)
	if err != nil {
		return response.InternalServerError(c, "Failed to load dashboard statistics")
	}

	setPrivateCache(c, 60)
	return response.Success(c, out, "Dashboard statistics retrieved successfully")
}

func parseIntQuery(c echo.Context, name string, fallback int) int {
	raw := c.QueryParam(name)
	if raw == "" {
		return fallback
	}
	v, err := strconv.Atoi(raw)
	if err != nil {
		return fallback
	}
	return v
}

func setPrivateCache(c echo.Context, maxAge int) {
	c.Response().Header().Set("Cache-Control", "private, max-age="+strconv.Itoa(maxAge))
}
