package dto

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/schedule/manage"
	"github.com/tidbcloud/AgentTeam/internal/trigger"
)

// AgentTriggerMutationRequest creates or updates an agent-owned trigger.
type AgentTriggerMutationRequest struct {
	Name                  string                        `json:"name"`
	Source                trigger.SourceInput           `json:"source"`
	Target                string                        `json:"target"`
	MessageTemplate       string                        `json:"messageTemplate"`
	Mentions              []MessageMentionHint          `json:"mentions,omitempty"`
	HumanNotificationMode trigger.HumanNotificationMode `json:"humanNotificationMode,omitempty"`
}

// AgentTriggerValidateRequest validates a trigger mutation, optionally against an existing trigger id.
type AgentTriggerValidateRequest struct {
	TriggerID string `json:"triggerId"`
	AgentTriggerMutationRequest
}

// AgentTriggerDeleteResponse reports successful trigger deletion.
type AgentTriggerDeleteResponse struct {
	Deleted bool `json:"deleted"`
}

// AgentScheduleTiming is the canonical schedule timing contract. Kind selects
// one closed branch: "at" (absolute time), "after" (relative seconds),
// "every" (interval seconds from an optional anchor), or "cron"
// (expression + optional timezone). It converts to the scheduler SourceInput
// without changing scheduler semantics.
type AgentScheduleTiming struct {
	Kind       string     `json:"kind"`                 // at | after | every | cron
	At         *time.Time `json:"at,omitempty"`         // kind=at
	Seconds    *int64     `json:"seconds,omitempty"`    // kind=after | every
	Anchor     *time.Time `json:"anchor,omitempty"`     // kind=every
	Expression string     `json:"expression,omitempty"` // kind=cron
	Timezone   string     `json:"timezone,omitempty"`   // kind=cron
}

// ToSourceInput converts the canonical timing into the scheduler SourceInput.
func (t AgentScheduleTiming) ToSourceInput() (manage.SourceInput, error) {
	switch strings.ToLower(strings.TrimSpace(t.Kind)) {
	case "at":
		if t.At == nil {
			return manage.SourceInput{}, errors.New("schedule kind \"at\" requires \"at\"")
		}
		at := *t.At
		return manage.SourceInput{
			SourceKind:  manage.SourceKindTime,
			TimeMode:    manage.TimeModeOneShotAbsolute,
			ScheduledAt: &at,
		}, nil
	case "after":
		if t.Seconds == nil || *t.Seconds <= 0 {
			return manage.SourceInput{}, errors.New("schedule kind \"after\" requires positive \"seconds\"")
		}
		seconds := *t.Seconds
		return manage.SourceInput{
			SourceKind:      manage.SourceKindTime,
			TimeMode:        manage.TimeModeOneShotRelative,
			RelativeSeconds: &seconds,
		}, nil
	case "every":
		if t.Seconds == nil || *t.Seconds <= 0 {
			return manage.SourceInput{}, errors.New("schedule kind \"every\" requires positive \"seconds\"")
		}
		seconds := *t.Seconds
		return manage.SourceInput{
			SourceKind:      manage.SourceKindTime,
			TimeMode:        manage.TimeModeInterval,
			IntervalSeconds: &seconds,
			AnchorAt:        t.Anchor,
		}, nil
	case "cron":
		if strings.TrimSpace(t.Expression) == "" {
			return manage.SourceInput{}, errors.New("schedule kind \"cron\" requires \"expression\"")
		}
		return manage.SourceInput{
			SourceKind:     manage.SourceKindTime,
			TimeMode:       manage.TimeModeCron,
			CronExpression: t.Expression,
			Timezone:       t.Timezone,
		}, nil
	default:
		return manage.SourceInput{}, fmt.Errorf("unsupported schedule kind %q", t.Kind)
	}
}

// AgentScheduleMutationRequest creates or updates an agent-owned schedule.
type AgentScheduleMutationRequest struct {
	Name                  string                       `json:"name"`
	Schedule              AgentScheduleTiming          `json:"schedule"`
	Target                string                       `json:"target"`
	Template              string                       `json:"template"`
	Mentions              []MessageMentionHint         `json:"mentions,omitempty"`
	StartThread           bool                         `json:"startThread,omitempty"`
	HumanNotificationMode manage.HumanNotificationMode `json:"humanNotificationMode,omitempty"`
	IdempotencyKey        string                       `json:"idempotencyKey,omitempty"`
	ExpectedUpdatedAt     *time.Time                   `json:"expectedUpdatedAt,omitempty"`
}

// AgentScheduleValidateRequest validates a schedule mutation, optionally against an existing schedule id.
type AgentScheduleValidateRequest struct {
	ScheduleID string `json:"scheduleId"`
	// TriggerID is accepted while old trigger_* MCP tools still pass triggerId.
	TriggerID string `json:"triggerId,omitempty"`
	AgentScheduleMutationRequest
}

func (request AgentScheduleValidateRequest) ExistingID() string {
	if request.ScheduleID != "" {
		return request.ScheduleID
	}
	return request.TriggerID
}

// AgentScheduleDeleteResponse reports successful schedule deletion.
type AgentScheduleDeleteResponse struct {
	Deleted bool `json:"deleted"`
}
