package httpapi

import (
	"net/http"
	"strings"
	"time"

	"github.com/easyai/easyai-ai-gateway/apps/api/internal/auth"
	"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
)

type dailyTokenUsageSummary struct {
	CumulativeTokens  int64 `json:"cumulativeTokens"`
	PeakDailyTokens   int64 `json:"peakDailyTokens"`
	CurrentStreakDays int   `json:"currentStreakDays"`
	LongestStreakDays int   `json:"longestStreakDays"`
}

// dailyTokenUsage godoc
// @Summary 查询每日 Token 与资源点用量
// @Description 按 IANA 时区返回连续自然日用量；API Key 仅统计当前 Key，JWT 统计当前用户。
// @Tags workspace
// @Produce json
// @Security BearerAuth
// @Param from query string true "开始日期 YYYY-MM-DD"
// @Param to query string true "结束日期 YYYY-MM-DD"
// @Param timezone query string false "IANA 时区" default(UTC)
// @Success 200 {object} DailyTokenUsageResponse
// @Failure 400 {object} ErrorEnvelope
// @Failure 401 {object} ErrorEnvelope
// @Failure 500 {object} ErrorEnvelope
// @Router /api/workspace/token-usage/daily [get]
func (s *Server) dailyTokenUsage(w http.ResponseWriter, r *http.Request) {
	user, ok := auth.UserFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusUnauthorized, "unauthorized")
		return
	}
	timezone := strings.TrimSpace(r.URL.Query().Get("timezone"))
	if timezone == "" {
		timezone = "UTC"
	}
	location, err := time.LoadLocation(timezone)
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid IANA timezone")
		return
	}
	from, err := time.ParseInLocation("2006-01-02", strings.TrimSpace(r.URL.Query().Get("from")), location)
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid from date")
		return
	}
	to, err := time.ParseInLocation("2006-01-02", strings.TrimSpace(r.URL.Query().Get("to")), location)
	if err != nil || to.Before(from) || to.Sub(from) > 399*24*time.Hour {
		writeError(w, http.StatusBadRequest, "invalid to date or date range exceeds 400 days")
		return
	}
	stored, err := s.store.ListDailyTokenUsage(r.Context(), user, from, to, timezone)
	if err != nil {
		s.logger.Error("list daily token usage failed", "error", err)
		writeError(w, http.StatusInternalServerError, "list daily token usage failed")
		return
	}
	byDate := make(map[string]store.DailyTokenUsage, len(stored))
	for _, item := range stored {
		byDate[item.Date] = item
	}
	items, summary := fillDailyTokenUsageDays(byDate, from, to)
	writeJSON(w, http.StatusOK, map[string]any{
		"items": items, "tokenDays": items, "summary": summary,
		"range": map[string]string{"from": from.Format("2006-01-02"), "to": to.Format("2006-01-02"), "timezone": timezone},
	})
}

func fillDailyTokenUsageDays(byDate map[string]store.DailyTokenUsage, from, to time.Time) ([]store.DailyTokenUsage, dailyTokenUsageSummary) {
	items := make([]store.DailyTokenUsage, 0, 32)
	summary := dailyTokenUsageSummary{}
	currentRun := 0
	for day := from; !day.After(to); day = day.AddDate(0, 0, 1) {
		key := day.Format("2006-01-02")
		item, found := byDate[key]
		if !found {
			item.Date = key
		}
		items = append(items, item)
		summary.CumulativeTokens += item.TotalTokens
		if item.TotalTokens > summary.PeakDailyTokens {
			summary.PeakDailyTokens = item.TotalTokens
		}
		if item.TaskCount > 0 {
			currentRun++
			if currentRun > summary.LongestStreakDays {
				summary.LongestStreakDays = currentRun
			}
		} else {
			currentRun = 0
		}
	}
	summary.CurrentStreakDays = currentRun
	return items, summary
}
