package adminfinance

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

	"hfb_sys/backend/internal/timeutil"
	"hfb_sys/backend/pkg/response"

	"github.com/gin-gonic/gin"
)

type Handler struct {
	service *Service
}

func NewHandler(service *Service) *Handler {
	return &Handler{service: service}
}

func (h *Handler) Dashboard(c *gin.Context) {
	query, ok := parseDashboardQuery(c)
	if !ok {
		return
	}
	item, err := h.service.Dashboard(c.Request.Context(), query)
	if err != nil {
		writeFinanceError(c, err)
		return
	}
	response.OK(c, item)
}

func (h *Handler) Details(c *gin.Context) {
	query, ok := parseDetailQuery(c)
	if !ok {
		return
	}
	result, err := h.service.Details(c.Request.Context(), query)
	if err != nil {
		writeFinanceError(c, err)
		return
	}
	response.OK(c, result)
}

func parseDashboardQuery(c *gin.Context) (DashboardQuery, bool) {
	start, end, ok := parseDateRange(c, 6)
	if !ok {
		return DashboardQuery{}, false
	}
	return DashboardQuery{StartDate: start, EndDate: end}, true
}

func parseDetailQuery(c *gin.Context) (DetailQuery, bool) {
	start, end, ok := parseDateRange(c, 29)
	if !ok {
		return DetailQuery{}, false
	}
	query := DetailQuery{
		OrderNo:          c.Query("order_no"),
		OrderStatus:      c.Query("order_status"),
		SettlementStatus: c.Query("settlement_status"),
		DateType:         c.DefaultQuery("date_type", "settled"),
		StartDate:        start,
		EndDate:          end,
	}
	if query.DateType != "created" && query.DateType != "settled" {
		response.BadRequest(c, "日期类型不正确")
		return query, false
	}
	if raw := c.Query("user_id"); raw != "" {
		value, err := strconv.ParseUint(raw, 10, 64)
		if err != nil || value == 0 {
			response.BadRequest(c, "用户 ID 不正确")
			return query, false
		}
		query.UserID = value
	}
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
	query.Page = page
	query.PageSize = pageSize
	return query, true
}

func parseDateRange(c *gin.Context, defaultLookbackDays int) (time.Time, time.Time, bool) {
	loc := timeutil.ShanghaiLocation()
	today := timeutil.ShanghaiNow()
	defaultStart := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, loc).AddDate(0, 0, -defaultLookbackDays)
	defaultEnd := time.Date(today.Year(), today.Month(), today.Day(), 23, 59, 59, int(time.Second-time.Nanosecond), loc)

	start := defaultStart
	end := defaultEnd
	if raw := c.Query("start_date"); raw != "" {
		parsed, err := time.ParseInLocation("2006-01-02", raw, loc)
		if err != nil {
			response.BadRequest(c, "开始日期不正确")
			return start, end, false
		}
		start = parsed
	}
	if raw := c.Query("end_date"); raw != "" {
		parsed, err := time.ParseInLocation("2006-01-02", raw, loc)
		if err != nil {
			response.BadRequest(c, "结束日期不正确")
			return start, end, false
		}
		end = parsed.AddDate(0, 0, 1).Add(-time.Nanosecond)
	}
	if start.After(end) {
		response.BadRequest(c, "开始日期不能晚于结束日期")
		return start, end, false
	}
	return start, end, true
}

func writeFinanceError(c *gin.Context, err error) {
	switch {
	case errors.Is(err, ErrDependencyUnavailable):
		response.ServiceUnavailable(c, "数据库未连接")
	default:
		response.Error(c, http.StatusInternalServerError, "finance_error", "财务数据暂时不可用")
	}
}
