package robot

import (
	"strconv"
	"strings"
	"sync"

	"github.com/gin-gonic/gin"
	"github.com/yaoapp/kun/log"
	robotapi "github.com/yaoapp/yao/agent/robot/api"
	robottypes "github.com/yaoapp/yao/agent/robot/types"
	"github.com/yaoapp/yao/openapi/oauth/authorized"
	"github.com/yaoapp/yao/openapi/response"
)

// ListAllRobots lists robots with pagination and filtering
// GET /v1/agent/robots
func ListAllRobots(c *gin.Context) {
	// Get authorized information
	authInfo := authorized.GetInfo(c)

	// Parse pagination parameters
	page := 1
	if pageStr := c.Query("page"); pageStr != "" {
		if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
			page = p
		}
	}

	pageSize := 20
	if pageSizeStr := c.Query("pagesize"); pageSizeStr != "" {
		if ps, err := strconv.Atoi(pageSizeStr); err == nil && ps > 0 && ps <= 100 {
			pageSize = ps
		}
	}

	// Parse filter parameters
	requestedTeamID := strings.TrimSpace(c.Query("team_id"))
	status := strings.TrimSpace(c.Query("status"))
	keywords := strings.TrimSpace(c.Query("keywords"))
	autonomousModeStr := strings.TrimSpace(c.Query("autonomous_mode"))

	// Apply permission-based filtering
	// This ensures users only see robots they have access to:
	// - No constraints: use requested team_id or no filter
	// - TeamOnly: force filter to user's team
	// - OwnerOnly: filter by user_id (personal resources)
	effectiveTeamID := BuildListFilter(c, authInfo, requestedTeamID)

	// Build query
	query := &robotapi.ListQuery{
		TeamID:   effectiveTeamID,
		Keywords: keywords,
		Page:     page,
		PageSize: pageSize,
	}
	if status != "" {
		query.Status = robottypes.RobotStatus(status)
	}
	// Parse autonomous_mode filter: "true" or "false" to filter, empty/other to show all
	if autonomousModeStr == "true" {
		autonomousMode := true
		query.AutonomousMode = &autonomousMode
	} else if autonomousModeStr == "false" {
		autonomousMode := false
		query.AutonomousMode = &autonomousMode
	}

	// Create robot context
	ctx := &robottypes.Context{}

	// Call API layer
	result, err := robotapi.ListAllRobots(ctx, query)
	if err != nil {
		log.Error("Failed to list robots: %v", err)
		errorResp := &response.ErrorResponse{
			Code:             response.ErrServerError.Code,
			ErrorDescription: "Failed to list robots: " + err.Error(),
		}
		response.RespondWithError(c, response.StatusInternalServerError, errorResp)
		return
	}

	// Convert to HTTP response format with runtime status
	robots := make([]*Response, len(result.Data))
	var wg sync.WaitGroup

	for i, r := range result.Data {
		wg.Add(1)
		go func(idx int, robot *robottypes.Robot) {
			defer wg.Done()
			resp := newResponseFromRobot(robot)

			// Fetch runtime status for each robot
			if status, err := robotapi.GetRobotStatus(ctx, robot.MemberID); err == nil && status != nil {
				resp.Running = status.Running
				resp.MaxRunning = status.MaxRunning
				resp.LastRun = status.LastRun
				resp.NextRun = status.NextRun
				// Use runtime status instead of stored status
				resp.RobotStatus = string(status.Status)
			}

			robots[idx] = resp
		}(i, r)
	}
	wg.Wait()

	resp := &ListResponse{
		Data:     robots,
		Total:    result.Total,
		Page:     result.Page,
		PageSize: result.PageSize,
	}

	response.RespondWithSuccess(c, response.StatusOK, resp)
}

// newResponseFromRobot converts types.Robot to Response
func newResponseFromRobot(r *robottypes.Robot) *Response {
	if r == nil {
		return nil
	}

	return &Response{
		Name:           r.MemberID, // Frontend mapping: name ← member_id
		Description:    r.Bio,      // Frontend mapping: description ← bio
		MemberID:       r.MemberID,
		TeamID:         r.TeamID,
		RobotStatus:    string(r.Status),
		AutonomousMode: r.AutonomousMode,
		DisplayName:    r.DisplayName,
		Bio:            r.Bio,
		SystemPrompt:   r.SystemPrompt,
		RobotEmail:     r.RobotEmail,
	}
}
