package Admin

import (
	dto "astrology-api/dto_admin"
	"astrology-api/middleware"
	"astrology-api/services_admin"
	"astrology-api/utils"
	"strconv"
	"strings"

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

type ConsultationController struct {
	monitorService services_admin.ConsultationMonitorService
}

func NewConsultationController(
	monitorService services_admin.ConsultationMonitorService,
) *ConsultationController {

	return &ConsultationController{monitorService: monitorService}
}

//------------------------------------------------
// Filters
//------------------------------------------------

func liveFilterFrom(ctx *gin.Context) dto.LiveConsultationFilter {

	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))

	if page <= 0 {
		page = 1
	}

	if limit <= 0 {
		limit = 10
	}

	astrologerID, _ := strconv.ParseUint(ctx.DefaultQuery("astrologer_id", "0"), 10, 64)
	userID, _ := strconv.ParseUint(ctx.DefaultQuery("user_id", "0"), 10, 64)

	return dto.LiveConsultationFilter{
		Search:       strings.TrimSpace(ctx.Query("search")),
		Status:       ctx.DefaultQuery("status", "LIVE"),
		Medium:       ctx.DefaultQuery("medium", "ALL"),
		AstrologerID: uint(astrologerID),
		UserID:       uint(userID),
		StalledOnly:  ctx.Query("stalled_only") == "true",
		FreeOnly:     ctx.Query("free_only") == "true",
		SortBy:       ctx.Query("sort_by"),
		SortDir:      ctx.DefaultQuery("sort_dir", "desc"),
		Page:         page,
		Limit:        limit,
	}
}

//------------------------------------------------
// Live monitoring
//------------------------------------------------

func (c *ConsultationController) GetLive(ctx *gin.Context) {

	response, err := c.monitorService.ListLive(liveFilterFrom(ctx))

	if err != nil {
		utils.InternalServerError(ctx, err)
		return
	}

	utils.Success(ctx, "Live consultations", response)
}

// GET /api/admin/consultation/live-summary
func (c *ConsultationController) GetLiveSummary(ctx *gin.Context) {

	response, err := c.monitorService.LiveSummary()

	if err != nil {
		utils.InternalServerError(ctx, err)
		return
	}

	utils.Success(ctx, "Live consultation summary", response)
}

// GET /api/admin/consultation/live/:id
func (c *ConsultationController) GetLiveDetail(ctx *gin.Context) {

	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)

	if err != nil || id == 0 {
		utils.BadRequest(ctx, "Invalid consultation id")
		return
	}

	response, err := c.monitorService.GetLiveDetail(uint(id))

	if err != nil {

		if strings.Contains(err.Error(), "not found") {
			utils.NotFound(ctx, err.Error())
			return
		}

		utils.InternalServerError(ctx, err)
		return
	}

	utils.Success(ctx, "Consultation detail", response)
}

//------------------------------------------------
// Force end
//------------------------------------------------

// ForceEnd closes sessions from the panel.
//
// Works on a healthy, ticking session as well as a stuck one — the case it
// exists for is support with the customer on the phone, and waiting for the
// sweeper's idea of stale would be useless there.
//
// POST /api/admin/consultation/force-end
func (c *ConsultationController) ForceEnd(ctx *gin.Context) {

	var request dto.ForceEndRequest

	if err := ctx.ShouldBindJSON(&request); err != nil {
		utils.BadRequest(ctx, err.Error())
		return
	}

	response, err := c.monitorService.ForceEnd(
		request,
		middleware.GetAdminID(ctx),
		middleware.IsSystemCaller(ctx),
	)

	if err != nil {
		utils.BadRequest(ctx, err.Error())
		return
	}

	utils.Success(ctx, "Consultations force-ended", response)
}

//------------------------------------------------
// Transcript
//------------------------------------------------

// GetTranscript reads a stored chat back, for dispute handling.
//
// Only what the apps uploaded exists: Agora RTM keeps no history, so a session
// where neither app managed to flush its buffer comes back empty with
// upload_status NONE. That is information, not an error.
//
// GET /api/admin/consultation/transcript/:id
func (c *ConsultationController) GetTranscript(ctx *gin.Context) {

	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)

	if err != nil || id == 0 {
		utils.BadRequest(ctx, "Invalid consultation id")
		return
	}

	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "200"))

	response, err := c.monitorService.GetTranscript(uint(id), page, limit)

	if err != nil {

		if strings.Contains(err.Error(), "not found") {
			utils.NotFound(ctx, err.Error())
			return
		}

		utils.InternalServerError(ctx, err)
		return
	}

	utils.Success(ctx, "Consultation transcript", response)
}
