package api

import (
	"context"
	"fmt"
	"time"

	"github.com/yaoapp/yao/agent/robot/store"
	"github.com/yaoapp/yao/agent/robot/types"
)

// ==================== Result Types ====================

// ResultQuery - query parameters for listing results
type ResultQuery struct {
	TriggerType types.TriggerType `json:"trigger_type,omitempty"` // clock | human | event
	Keyword     string            `json:"keyword,omitempty"`      // Search in name/summary
	Page        int               `json:"page,omitempty"`
	PageSize    int               `json:"pagesize,omitempty"`
}

// ResultItem - result list item (subset of execution)
type ResultItem struct {
	ID             string            `json:"id"`
	MemberID       string            `json:"member_id"`
	TriggerType    types.TriggerType `json:"trigger_type"`
	Status         types.ExecStatus  `json:"status"`
	Name           string            `json:"name"`
	Summary        string            `json:"summary"`
	StartTime      time.Time         `json:"start_time"`
	EndTime        *time.Time        `json:"end_time,omitempty"`
	HasAttachments bool              `json:"has_attachments"`
}

// ResultDetail - full result with delivery content
type ResultDetail struct {
	ID          string                `json:"id"`
	MemberID    string                `json:"member_id"`
	TriggerType types.TriggerType     `json:"trigger_type"`
	Status      types.ExecStatus      `json:"status"`
	Name        string                `json:"name"`
	Delivery    *types.DeliveryResult `json:"delivery,omitempty"`
	StartTime   time.Time             `json:"start_time"`
	EndTime     *time.Time            `json:"end_time,omitempty"`
}

// ResultListResponse - paginated response
type ResultListResponse struct {
	Data     []*ResultItem `json:"data"`
	Total    int           `json:"total"`
	Page     int           `json:"page"`
	PageSize int           `json:"pagesize"`
}

// ==================== Result API Functions ====================

// ListResults returns completed executions with delivery content for a robot
func ListResults(ctx *types.Context, memberID string, query *ResultQuery) (*ResultListResponse, error) {
	if memberID == "" {
		return nil, fmt.Errorf("member_id is required")
	}

	if query == nil {
		query = &ResultQuery{}
	}
	query.applyDefaults()

	opts := &store.ResultListOptions{
		MemberID: memberID,
		Page:     query.Page,
		PageSize: query.PageSize,
	}

	if query.TriggerType != "" {
		opts.TriggerType = query.TriggerType
	}
	if query.Keyword != "" {
		opts.Keyword = query.Keyword
	}

	// Query from store
	result, err := getExecutionStore().ListResults(context.Background(), opts)
	if err != nil {
		return nil, fmt.Errorf("failed to list results: %w", err)
	}

	// Transform to ResultItem slice
	items := make([]*ResultItem, 0, len(result.Data))
	for _, record := range result.Data {
		item := recordToResultItem(record)
		if item != nil {
			items = append(items, item)
		}
	}

	return &ResultListResponse{
		Data:     items,
		Total:    result.Total,
		Page:     result.Page,
		PageSize: result.PageSize,
	}, nil
}

// GetResult returns a single result by execution ID
func GetResult(ctx *types.Context, execID string) (*ResultDetail, error) {
	if execID == "" {
		return nil, fmt.Errorf("execution_id is required")
	}

	// Get from store
	record, err := getExecutionStore().Get(context.Background(), execID)
	if err != nil {
		return nil, fmt.Errorf("failed to get result: %w", err)
	}
	if record == nil {
		return nil, fmt.Errorf("result not found: %s", execID)
	}

	// Verify it has delivery content
	if record.Delivery == nil || record.Delivery.Content == nil {
		return nil, fmt.Errorf("result not found: %s (no delivery content)", execID)
	}

	return recordToResultDetail(record), nil
}

// ==================== Helper Functions ====================

// applyDefaults applies default values to ResultQuery
func (q *ResultQuery) applyDefaults() {
	if q.Page <= 0 {
		q.Page = 1
	}
	if q.PageSize <= 0 {
		q.PageSize = 20
	}
	if q.PageSize > 100 {
		q.PageSize = 100
	}
}

// recordToResultItem converts ExecutionRecord to ResultItem
func recordToResultItem(record *store.ExecutionRecord) *ResultItem {
	if record == nil {
		return nil
	}

	item := &ResultItem{
		ID:          record.ExecutionID,
		MemberID:    record.MemberID,
		TriggerType: record.TriggerType,
		Status:      record.Status,
		Name:        record.Name,
	}

	// Set times
	if record.StartTime != nil {
		item.StartTime = *record.StartTime
	}
	item.EndTime = record.EndTime

	// Extract summary and attachments from delivery
	if record.Delivery != nil && record.Delivery.Content != nil {
		item.Summary = record.Delivery.Content.Summary
		item.HasAttachments = len(record.Delivery.Content.Attachments) > 0
	}

	return item
}

// recordToResultDetail converts ExecutionRecord to ResultDetail
func recordToResultDetail(record *store.ExecutionRecord) *ResultDetail {
	if record == nil {
		return nil
	}

	detail := &ResultDetail{
		ID:          record.ExecutionID,
		MemberID:    record.MemberID,
		TriggerType: record.TriggerType,
		Status:      record.Status,
		Name:        record.Name,
		Delivery:    record.Delivery,
	}

	// Set times
	if record.StartTime != nil {
		detail.StartTime = *record.StartTime
	}
	detail.EndTime = record.EndTime

	return detail
}
