package cmd

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os/exec"

	"github.com/spf13/cobra"
)

const desloppifyAttribution = "Powered by peteromallet/desloppify"

const missingDesloppifyGuidance = `desloppify was not found in PATH.

Install or update desloppify, then scan this codebase for code quality issues
(dead code, duplication, complexity, smells). It tracks findings persistently
across sessions and reports a health score.

Requires Python 3.11+. Install from PyPI:
  pip install --upgrade desloppify
  pip install --upgrade "desloppify[full]"
  desloppify update-skill codex

Use Devour wrappers (delegates to desloppify):
  devour quality scan --path .
  devour quality status
  devour quality next

Direct equivalent commands:
  desloppify scan --path .
  desloppify status
  desloppify next

--path is the directory to scan ("." for project root).
Language is auto-detected. To override:
  desloppify --lang python scan --path .
Note: --lang goes BEFORE the subcommand.

Fix findings, then resolve and rescan:
  desloppify resolve fixed <id> --note "what changed" --attest "I have actually [DESCRIBE THE CONCRETE CHANGE YOU MADE] and I am not gaming the score by resolving without fixing."

For false positives or intentional debt:
  desloppify resolve wontfix <id> --note "reason" --attest "I have actually verified this is intentional/false-positive and I am not gaming the score by resolving without fixing."

If subjective scores feel stale or inflated:
  desloppify scan --path . --reset-subjective

Run regularly (for example before each push). If desloppify itself looks wrong
or confusing, capture a repro and consider filing upstream:
  git clone https://github.com/peteromallet/desloppify.git /tmp/desloppify`

func runDesloppifyFromCommand(cmd *cobra.Command, args []string, withAttribution bool) error {
	return runDesloppifyWithIO(
		cmd.Context(),
		cmd.InOrStdin(),
		cmd.OutOrStdout(),
		cmd.ErrOrStderr(),
		args,
		withAttribution,
	)
}

func runDesloppifyWithIO(
	ctx context.Context,
	stdin io.Reader,
	stdout io.Writer,
	stderr io.Writer,
	args []string,
	withAttribution bool,
) error {
	if withAttribution {
		fmt.Fprintf(stderr, "devour quality/review is %s\n", desloppifyAttribution)
	}

	binaryPath, err := exec.LookPath("desloppify")
	if err != nil {
		printDesloppifyInstallGuidance(stderr)
		return fmt.Errorf("desloppify is required: %w", err)
	}

	run := exec.CommandContext(ctx, binaryPath, args...)
	run.Stdin = stdin
	run.Stdout = stdout
	run.Stderr = stderr

	if err := run.Run(); err != nil {
		var exitErr *exec.ExitError
		if errors.As(err, &exitErr) {
			return err
		}
		return fmt.Errorf("failed to run desloppify: %w", err)
	}

	return nil
}

func printDesloppifyInstallGuidance(stderr io.Writer) {
	fmt.Fprintln(stderr, missingDesloppifyGuidance)
}
