package status

import (
	"context"
	"fmt"
	"path/filepath"

	"iop/apps/node/internal/runtime"
	"iop/packages/go/config"
)

// UsageStatus represents the parsed usage limits of a CLI target.
type UsageStatus struct {
	RawOutput       string            `json:"raw_output"`
	DailyLimit      string            `json:"daily_limit,omitempty"`
	DailyResetTime  string            `json:"daily_reset_time,omitempty"`
	WeeklyLimit     string            `json:"weekly_limit,omitempty"`
	WeeklyResetTime string            `json:"weekly_reset_time,omitempty"`
	Metadata        map[string]string `json:"metadata,omitempty"`
}

// ToRuntime converts UsageStatus to the runtime domain type.
func (s *UsageStatus) ToRuntime() *runtime.AgentUsageStatus {
	if s == nil {
		return nil
	}
	var meta map[string]string
	if len(s.Metadata) > 0 {
		meta = make(map[string]string, len(s.Metadata))
		for k, v := range s.Metadata {
			meta[k] = v
		}
	}
	return &runtime.AgentUsageStatus{
		RawOutput:       s.RawOutput,
		DailyLimit:      s.DailyLimit,
		DailyResetTime:  s.DailyResetTime,
		WeeklyLimit:     s.WeeklyLimit,
		WeeklyResetTime: s.WeeklyResetTime,
		Metadata:        meta,
	}
}

// Checker defines the interface for checking CLI status/usage.
type Checker interface {
	Check(ctx context.Context) (*UsageStatus, error)
}

// CheckUsage creates the appropriate checker and executes it.
func CheckUsage(ctx context.Context, target string, profile config.CLIProfileConf) (*UsageStatus, error) {
	checker, err := NewChecker(target, profile)
	if err != nil {
		return nil, err
	}

	return checker.Check(ctx)
}

// NewChecker creates the appropriate checker for the given target and profile.
func NewChecker(target string, profile config.CLIProfileConf) (Checker, error) {
	cmdBase := filepath.Base(profile.Command)
	switch {
	case target == "codex" || cmdBase == "codex":
		return NewCodexChecker(profile.Command), nil
	case target == "claude" || target == "claude-tui" || cmdBase == "claude":
		return NewClaudeChecker(profile.Command), nil
	case target == "antigravity" || cmdBase == "agy" || cmdBase == "antigravity":
		return NewAntigravityChecker(profile.Command), nil
	default:
		return nil, fmt.Errorf("status check not supported for target %q (command %q)", target, profile.Command)
	}
}
