package api

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

	"github.com/ez-api/ez-api/internal/model"
	"github.com/gin-gonic/gin"
)

type APIKeyStatsSummaryResponse struct {
	TotalRequests   int64   `json:"total_requests"`
	SuccessRequests int64   `json:"success_requests"`
	FailureRequests int64   `json:"failure_requests"`
	SuccessRate     float64 `json:"success_rate"`
	FailureRate     float64 `json:"failure_rate"`
}

// GetAPIKeyStatsSummary godoc
// @Summary      APIKey stats summary (admin)
// @Description  Aggregate APIKey success/failure stats across all provider groups
// @Tags         admin
// @Produce      json
// @Security     AdminAuth
// @Param        since  query     int  false  "Start time (unix seconds)"
// @Param        until  query     int  false  "End time (unix seconds)"
// @Success      200  {object}  APIKeyStatsSummaryResponse
// @Failure      500  {object}  gin.H
// @Router       /admin/apikey-stats/summary [get]
func (h *AdminHandler) GetAPIKeyStatsSummary(c *gin.Context) {
	if h == nil || h.db == nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "database not configured"})
		return
	}

	// Parse optional time range parameters
	var sinceTime, untilTime *time.Time
	if sinceStr := c.Query("since"); sinceStr != "" {
		if ts, err := strconv.ParseInt(sinceStr, 10, 64); err == nil {
			t := time.Unix(ts, 0).UTC()
			sinceTime = &t
		}
	}
	if untilStr := c.Query("until"); untilStr != "" {
		if ts, err := strconv.ParseInt(untilStr, 10, 64); err == nil {
			t := time.Unix(ts, 0).UTC()
			untilTime = &t
		}
	}

	// If time range specified, query from LogRecord table
	if sinceTime != nil || untilTime != nil {
		h.getAPIKeyStatsFromLogs(c, sinceTime, untilTime)
		return
	}

	// Default: use aggregated stats from APIKey table (all-time)
	var totals struct {
		TotalRequests   int64 `json:"total_requests"`
		SuccessRequests int64 `json:"success_requests"`
		FailureRequests int64 `json:"failure_requests"`
	}

	if err := h.db.Model(&model.APIKey{}).
		Select("COALESCE(SUM(total_requests),0) as total_requests, COALESCE(SUM(success_requests),0) as success_requests").
		Scan(&totals).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to aggregate api key stats", "details": err.Error()})
		return
	}

	total := totals.TotalRequests
	success := totals.SuccessRequests
	failure := total - success
	if failure < 0 {
		failure = 0
	}

	var successRate float64
	var failureRate float64
	if total > 0 {
		successRate = float64(success) / float64(total)
		failureRate = float64(failure) / float64(total)
	}

	c.JSON(http.StatusOK, APIKeyStatsSummaryResponse{
		TotalRequests:   total,
		SuccessRequests: success,
		FailureRequests: failure,
		SuccessRate:     successRate,
		FailureRate:     failureRate,
	})
}

// getAPIKeyStatsFromLogs calculates stats from log records for a specific time range
func (h *AdminHandler) getAPIKeyStatsFromLogs(c *gin.Context, sinceTime, untilTime *time.Time) {
	q := h.logBaseQuery()

	if sinceTime != nil {
		q = q.Where("created_at >= ?", *sinceTime)
	}
	if untilTime != nil {
		q = q.Where("created_at <= ?", *untilTime)
	}

	// Only count requests that went through a provider (provider_id > 0)
	q = q.Where("provider_id > 0")

	var result struct {
		TotalRequests   int64
		SuccessRequests int64
	}

	if err := q.Select(`
		COUNT(*) as total_requests,
		SUM(CASE WHEN status_code >= 200 AND status_code < 400 THEN 1 ELSE 0 END) as success_requests
	`).Scan(&result).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to aggregate api key stats from logs", "details": err.Error()})
		return
	}

	total := result.TotalRequests
	success := result.SuccessRequests
	failure := total - success
	if failure < 0 {
		failure = 0
	}

	var successRate float64
	var failureRate float64
	if total > 0 {
		successRate = float64(success) / float64(total)
		failureRate = float64(failure) / float64(total)
	}

	c.JSON(http.StatusOK, APIKeyStatsSummaryResponse{
		TotalRequests:   total,
		SuccessRequests: success,
		FailureRequests: failure,
		SuccessRate:     successRate,
		FailureRate:     failureRate,
	})
}
