package audit

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

	"aigateway.local/core/internal/identity"
	"aigateway.local/core/internal/platform/apiresponse"
)

type AdminHTTPHandler struct {
	query    *QueryService
	identity *identity.Service
	mux      *http.ServeMux
}

func NewAdminHTTPHandler(query *QueryService, identityService *identity.Service) *AdminHTTPHandler {
	h := &AdminHTTPHandler{query: query, identity: identityService, mux: http.NewServeMux()}
	h.mux.HandleFunc("GET /api/v1/admin/audit-events", h.listEvents)
	h.mux.HandleFunc("GET /api/v1/admin/usage/daily", h.listDailyUsage)
	return h
}

func (h *AdminHTTPHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	h.mux.ServeHTTP(writer, request)
}

func (h *AdminHTTPHandler) listEvents(writer http.ResponseWriter, request *http.Request) {
	if !h.requirePermission(writer, request, identity.PermissionAuditRead) {
		return
	}
	now := time.Now().UTC()
	from, err := queryTime(request, "from", now.Add(-24*time.Hour))
	if err != nil {
		apiresponse.Error(writer, http.StatusBadRequest, "from 时间无效")
		return
	}
	to, err := queryTime(request, "to", now.Add(time.Second))
	if err != nil || !to.After(from) || to.Sub(from) > 366*24*time.Hour {
		apiresponse.Error(writer, http.StatusBadRequest, "审计查询时间范围无效或超过 366 天")
		return
	}
	limit := 50
	if value := request.URL.Query().Get("limit"); value != "" {
		limit, err = strconv.Atoi(value)
		if err != nil || limit < 1 || limit > 200 {
			apiresponse.Error(writer, http.StatusBadRequest, "limit 必须在 1 到 200 之间")
			return
		}
	}
	var before *time.Time
	if value := request.URL.Query().Get("before"); value != "" {
		parsed, parseErr := time.Parse(time.RFC3339Nano, value)
		if parseErr != nil {
			apiresponse.Error(writer, http.StatusBadRequest, "before 游标无效")
			return
		}
		before = &parsed
	}
	var status *int
	if value := request.URL.Query().Get("status"); value != "" {
		parsed, parseErr := strconv.Atoi(value)
		if parseErr != nil || parsed < 100 || parsed > 599 {
			apiresponse.Error(writer, http.StatusBadRequest, "status 无效")
			return
		}
		status = &parsed
	}
	items, err := h.query.ListEvents(request.Context(), EventFilter{
		From: from, To: to, Before: before, APIKeyID: strings.TrimSpace(request.URL.Query().Get("api_key_id")),
		Provider: strings.TrimSpace(request.URL.Query().Get("provider")), Model: strings.TrimSpace(request.URL.Query().Get("model")), StatusCode: status, Limit: limit,
	})
	if err != nil {
		apiresponse.Error(writer, http.StatusServiceUnavailable, "审计查询服务暂不可用")
		return
	}
	next := ""
	if len(items) == limit {
		next = items[len(items)-1].RecordedAt.Format(time.RFC3339Nano)
	}
	apiresponse.OK(writer, map[string]any{"items": items, "next_before": next})
}

func (h *AdminHTTPHandler) listDailyUsage(writer http.ResponseWriter, request *http.Request) {
	if !h.requirePermission(writer, request, identity.PermissionUsageRead) {
		return
	}
	now := time.Now().UTC()
	from, err := queryDate(request, "from", now.AddDate(0, 0, -29))
	if err != nil {
		apiresponse.Error(writer, http.StatusBadRequest, "from 日期无效")
		return
	}
	to, err := queryDate(request, "to", now)
	if err != nil || to.Before(from) || to.Sub(from) > 366*24*time.Hour {
		apiresponse.Error(writer, http.StatusBadRequest, "usage 查询日期范围无效或超过 366 天")
		return
	}
	items, err := h.query.ListDailyUsage(request.Context(), UsageFilter{
		From: from, To: to, APIKeyID: strings.TrimSpace(request.URL.Query().Get("api_key_id")),
		Provider: strings.TrimSpace(request.URL.Query().Get("provider")), Model: strings.TrimSpace(request.URL.Query().Get("model")),
	})
	if err != nil {
		apiresponse.Error(writer, http.StatusServiceUnavailable, "usage 查询服务暂不可用")
		return
	}
	apiresponse.OK(writer, items)
}

func (h *AdminHTTPHandler) requirePermission(writer http.ResponseWriter, request *http.Request, permission string) bool {
	account, err := h.identity.Authenticate(request.Context(), identity.KindAdmin, request.Header.Get("Authorization"))
	if err != nil {
		status := http.StatusUnauthorized
		if !errors.Is(err, identity.ErrInvalidSession) && !errors.Is(err, identity.ErrNotFound) {
			status = http.StatusServiceUnavailable
		}
		apiresponse.Error(writer, status, "登录状态无效或身份服务暂不可用")
		return false
	}
	if !identity.HasPermission(account, permission) {
		apiresponse.Error(writer, http.StatusForbidden, "缺少审计或 usage 查看权限")
		return false
	}
	return true
}

func queryTime(request *http.Request, name string, fallback time.Time) (time.Time, error) {
	value := request.URL.Query().Get(name)
	if value == "" {
		return fallback, nil
	}
	return time.Parse(time.RFC3339, value)
}

func queryDate(request *http.Request, name string, fallback time.Time) (time.Time, error) {
	value := request.URL.Query().Get(name)
	if value == "" {
		value = fallback.Format("2006-01-02")
	}
	return time.Parse("2006-01-02", value)
}
