package claudebox

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log/slog"
	"os/exec"
	"strings"
)

// SDLCRunner executes SDLC CLI commands locally.
type SDLCRunner struct {
	workDir string
	logger  *slog.Logger
}

// SDLCRunnerConfig holds configuration for the SDLC runner.
type SDLCRunnerConfig struct {
	// WorkDir is the default working directory.
	WorkDir string

	// Logger is an optional logger for debug output.
	Logger *slog.Logger
}

// NewSDLCRunner creates a new SDLC runner.
func NewSDLCRunner(cfg SDLCRunnerConfig) *SDLCRunner {
	logger := cfg.Logger
	if logger == nil {
		logger = slog.Default()
	}
	return &SDLCRunner{
		workDir: cfg.WorkDir,
		logger:  logger,
	}
}

// SDLCResult contains the result of an SDLC command.
type SDLCResult struct {
	Success bool
	Output  string
	Data    json.RawMessage // Parsed JSON from sdlc --json output
	Error   error
}

// Run executes an SDLC CLI command.
func (s *SDLCRunner) Run(ctx context.Context, workDir, command string, args []string) *SDLCResult {
	result := &SDLCResult{}

	// Ensure .sdlc/ is initialized
	if err := s.ensureInit(ctx, workDir); err != nil {
		// Log but continue - command might still work
		s.logger.Debug("sdlc init failed, continuing with command", "error", err, "work_dir", workDir)
	}

	// Build the command
	sdlcArgs := []string{command}
	sdlcArgs = append(sdlcArgs, args...)
	sdlcArgs = append(sdlcArgs, "--json")

	cmd := exec.CommandContext(ctx, "sdlc", sdlcArgs...)
	cmd.Dir = workDir

	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		result.Error = fmt.Errorf("%s: %s", err, stderr.String())
		result.Output = stdout.String()
		return result
	}

	result.Success = true
	result.Output = stdout.String()

	// Try to parse JSON output
	output := strings.TrimSpace(stdout.String())
	if output != "" && (output[0] == '{' || output[0] == '[') {
		result.Data = json.RawMessage(output)
	}

	return result
}

// ensureInit checks if .sdlc/ exists and runs `sdlc init` if it doesn't.
func (s *SDLCRunner) ensureInit(ctx context.Context, workDir string) error {
	// Check if .sdlc/ directory exists
	cmd := exec.CommandContext(ctx, "test", "-d", workDir+"/.sdlc")
	if cmd.Run() == nil {
		return nil // Already initialized
	}

	// Run sdlc init
	initCmd := exec.CommandContext(ctx, "sdlc", "init", "--json")
	initCmd.Dir = workDir
	return initCmd.Run()
}
