package doctor

import (
	"fmt"
	"path/filepath"
	"strings"

	"github.com/steveyegge/gastown/internal/beads"
	"github.com/steveyegge/gastown/internal/rig"
)

// RigBeadsCheck verifies that rig identity beads exist for all rigs.
// Rig identity beads track rig metadata like git URL, prefix, and operational state.
// They are created by gt rig add (see gt-zmznh) but may be missing for legacy rigs.
type RigBeadsCheck struct {
	FixableCheck
}

// NewRigBeadsCheck creates a new rig identity beads check.
func NewRigBeadsCheck() *RigBeadsCheck {
	return &RigBeadsCheck{
		FixableCheck: FixableCheck{
			BaseCheck: BaseCheck{
				CheckName:        "rig-beads-exist",
				CheckDescription: "Verify rig identity beads exist for all rigs",
			},
		},
	}
}

// Run checks if rig identity beads exist for all rigs.
func (c *RigBeadsCheck) Run(ctx *CheckContext) *CheckResult {
	// Load routes to get rig info
	townBeadsDir := filepath.Join(ctx.TownRoot, ".beads")
	routes, err := beads.LoadRoutes(townBeadsDir)
	if err != nil {
		return &CheckResult{
			Name:    c.Name(),
			Status:  StatusWarning,
			Message: "Could not load routes.jsonl",
		}
	}

	// Build unique rig list from routes
	// Routes have format: prefix "gt-" -> path "gastown/mayor/rig"
	rigSet := make(map[string]struct {
		prefix    string
		beadsPath string
	})
	for _, r := range routes {
		// Extract rig name from path (first component)
		parts := strings.Split(r.Path, "/")
		if len(parts) >= 1 && parts[0] != "." {
			rigName := parts[0]
			prefix := strings.TrimSuffix(r.Prefix, "-")
			if _, exists := rigSet[rigName]; !exists {
				rigSet[rigName] = struct {
					prefix    string
					beadsPath string
				}{
					prefix:    prefix,
					beadsPath: r.Path,
				}
			}
		}
	}

	if len(rigSet) == 0 {
		return &CheckResult{
			Name:    c.Name(),
			Status:  StatusOK,
			Message: "No rigs to check",
		}
	}

	var missing []string
	var checked int

	// Check each rig for its identity bead
	for rigName, info := range rigSet {
		rigBeadsPath := filepath.Join(ctx.TownRoot, info.beadsPath)
		bd := beads.New(rigBeadsPath)

		rigBeadID := beads.RigBeadIDWithPrefix(info.prefix, rigName)
		if _, err := bd.Show(rigBeadID); err != nil {
			missing = append(missing, rigBeadID)
		}
		checked++
	}

	if len(missing) == 0 {
		return &CheckResult{
			Name:    c.Name(),
			Status:  StatusOK,
			Message: fmt.Sprintf("All %d rig identity beads exist", checked),
		}
	}

	return &CheckResult{
		Name:    c.Name(),
		Status:  StatusError,
		Message: fmt.Sprintf("%d rig identity bead(s) missing", len(missing)),
		Details: missing,
		FixHint: "Run 'gt doctor --fix' to create missing rig identity beads",
	}
}

// Fix creates missing rig identity beads.
func (c *RigBeadsCheck) Fix(ctx *CheckContext) error {
	// Load routes to get rig info
	townBeadsDir := filepath.Join(ctx.TownRoot, ".beads")
	routes, err := beads.LoadRoutes(townBeadsDir)
	if err != nil {
		return fmt.Errorf("loading routes.jsonl: %w", err)
	}

	// Build unique rig list from routes
	rigSet := make(map[string]struct {
		prefix    string
		beadsPath string
	})
	for _, r := range routes {
		parts := strings.Split(r.Path, "/")
		if len(parts) >= 1 && parts[0] != "." {
			rigName := parts[0]
			prefix := strings.TrimSuffix(r.Prefix, "-")
			if _, exists := rigSet[rigName]; !exists {
				rigSet[rigName] = struct {
					prefix    string
					beadsPath string
				}{
					prefix:    prefix,
					beadsPath: r.Path,
				}
			}
		}
	}

	if len(rigSet) == 0 {
		return nil // No rigs to process
	}

	// Create missing rig identity beads
	for rigName, info := range rigSet {
		rigBeadsPath := filepath.Join(ctx.TownRoot, info.beadsPath)
		bd := beads.New(rigBeadsPath)

		rigBeadID := beads.RigBeadIDWithPrefix(info.prefix, rigName)
		if _, err := bd.Show(rigBeadID); err != nil {
			// Bead doesn't exist - create it
			// Try to get git URL from rig config
			rigPath := filepath.Join(ctx.TownRoot, rigName)
			gitURL := ""
			if cfg, err := rig.LoadRigConfig(rigPath); err == nil {
				gitURL = cfg.GitURL
			}

			fields := &beads.RigFields{
				Repo:   gitURL,
				Prefix: info.prefix,
				State:  "active",
			}

			if _, err := bd.CreateRigBead(rigBeadID, rigName, fields); err != nil {
				return fmt.Errorf("creating %s: %w", rigBeadID, err)
			}
		}
	}

	return nil
}
