package session

import (
	"context"

	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"go.uber.org/dig"
	"google.golang.org/grpc"

	sessionapi "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/api/agent-gateway/session/v1"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/rpcserver"
	"github.com/tidbcloud/aisupport/services/agent-gateway/internal/app"
	serviceapi "github.com/tidbcloud/aisupport/services/agent-gateway/internal/services/session/api"
)

type HandlerParam struct {
	dig.In

	Service serviceapi.Service
}

type Handler struct {
	sessionapi.UnimplementedSessionServiceServer

	service serviceapi.Service
}

func NewHandler(param HandlerParam) app.HandlerResult {
	handler := &Handler{service: param.Service}
	return app.HandlerResult{Handler: handler, GatewayHandler: handler}
}

func (h *Handler) Name() string {
	return "SessionService"
}

func (h *Handler) RegisterRPC(server *grpc.Server) error {
	sessionapi.RegisterSessionServiceServer(server, h)
	return nil
}

func (h *Handler) RegisterGateway(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
	return sessionapi.RegisterSessionServiceHandler(ctx, mux, conn)
}

func (h *Handler) ListSessions(ctx context.Context, req *sessionapi.ListSessionsRequest) (*sessionapi.ListSessionsResponse, error) {
	lark := req.GetLark()
	sessions, err := h.service.ListSessions(ctx, serviceapi.ListSessionsOptions{
		SessionID:           req.SessionId,
		SourceType:          req.SourceType,
		SourceInstanceID:    req.SourceInstanceId,
		SourceSessionKey:    req.SourceSessionKey,
		InitiatorEmail:      req.InitiatorEmail,
		LarkChatID:          lark.GetChatId(),
		LarkThreadID:        lark.GetThreadId(),
		LarkAnchorMessageID: lark.GetAnchorMessageId(),
		LarkEntryMessageID:  lark.GetEntryMessageId(),
		Status:              req.Status,
		Page:                int(req.Page),
		PageSize:            int(req.PageSize),
	})
	if err != nil {
		return nil, err
	}
	return &sessionapi.ListSessionsResponse{Sessions: sessions}, nil
}

func (h *Handler) GetSession(ctx context.Context, req *sessionapi.GetSessionRequest) (*sessionapi.GetSessionResponse, error) {
	item, found, err := h.service.GetSession(ctx, req.SessionId)
	if err != nil {
		return nil, err
	}
	return &sessionapi.GetSessionResponse{Session: item, Found: found}, nil
}

func (h *Handler) ListSessionTasks(ctx context.Context, req *sessionapi.ListSessionTasksRequest) (*sessionapi.ListSessionTasksResponse, error) {
	tasks, err := h.service.ListSessionTasks(ctx, req.SessionId, int(req.Limit))
	if err != nil {
		return nil, err
	}
	return &sessionapi.ListSessionTasksResponse{Tasks: tasks}, nil
}

func (h *Handler) DeleteSession(ctx context.Context, req *sessionapi.DeleteSessionRequest) (*sessionapi.DeleteSessionResponse, error) {
	if err := h.service.DeleteSession(ctx, req.SessionId); err != nil {
		return nil, err
	}
	return &sessionapi.DeleteSessionResponse{}, nil
}

var _ sessionapi.SessionServiceServer = (*Handler)(nil)
var _ rpcserver.RPCHandler = (*Handler)(nil)
var _ rpcserver.GatewayHandler = (*Handler)(nil)
