package manage

import (
	"context"
	"database/sql"
	"log/slog"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/model"
)

const (
	timeSourceTypeOnceAbsolute = "time.one_shot_absolute"
	timeSourceTypeOnceRelative = "time.one_shot_relative"
	timeSourceTypeInterval     = "time.interval"
	timeSourceTypeCron         = "time.cron"
)

type AppPort interface {
	ValidateMessageForUser(ctx context.Context, user model.User, workspaceID string, targetRef string, content string) error
}

type MessageValidator interface {
	ValidateMessageForUser(ctx context.Context, user model.User, workspaceID string, targetRef string, content string) error
}

type ServiceOptions struct {
	Clock     func() time.Time
	Validator MessageValidator
}

type Service struct {
	logger    *slog.Logger
	db        coredb.DB
	clock     func() time.Time
	validator MessageValidator
}

func New(logger *slog.Logger, db coredb.DB, appPort AppPort, options ServiceOptions) *Service {
	clock := options.Clock
	if clock == nil {
		clock = time.Now
	}
	validator := options.Validator
	if validator == nil {
		validator = appPort
	}
	return &Service{
		logger:    logger,
		db:        db,
		clock:     clock,
		validator: validator,
	}
}

func nullableString(value sql.NullString) string {
	if !value.Valid {
		return ""
	}
	return strings.TrimSpace(value.String)
}

func nullableInt64(value sql.NullInt64) *int64 {
	if !value.Valid {
		return nil
	}
	next := value.Int64
	return &next
}

func nullableTime(value sql.NullTime) *time.Time {
	if !value.Valid {
		return nil
	}
	next := value.Time.UTC()
	return &next
}

func nullableTimeMode(mode TimeMode) any {
	if strings.TrimSpace(string(mode)) == "" {
		return nil
	}
	return string(mode)
}

func nullableBytes(value []byte) any {
	if len(value) == 0 {
		return nil
	}
	return value
}

func timePtr(value time.Time) *time.Time {
	next := value.UTC()
	return &next
}

func rollback(tx coredb.Tx, ctx context.Context) {
	if tx != nil {
		_ = tx.Rollback(ctx)
	}
}

func (service *Service) now() time.Time {
	return service.clock().UTC()
}

func triggerTimeSourceType(mode TimeMode) string {
	switch mode {
	case TimeModeOneShotAbsolute:
		return timeSourceTypeOnceAbsolute
	case TimeModeOneShotRelative:
		return timeSourceTypeOnceRelative
	case TimeModeInterval:
		return timeSourceTypeInterval
	case TimeModeCron:
		return timeSourceTypeCron
	default:
		return "time.unknown"
	}
}
