package authoring

import (
	"context"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/nomadcode/nomadcode-core/internal/roadmapsync"
)

var ErrNoMilestonesChanged = errors.New("no milestone files changed")
var ErrMismatchedProviderIdentity = errors.New("mismatched provider identity block")

type EnsureProviderIdentityInput struct {
	WorkspacePath string
	Identity      roadmapsync.Identity
}

type EnsureProviderIdentityResult struct {
	InjectedPaths []string
}

type IdentityWriter interface {
	EnsureProviderIdentity(ctx context.Context, in EnsureProviderIdentityInput) (EnsureProviderIdentityResult, error)
}

type LocalIdentityWriter struct{}

func NewLocalIdentityWriter() *LocalIdentityWriter {
	return &LocalIdentityWriter{}
}

func (w *LocalIdentityWriter) EnsureProviderIdentity(ctx context.Context, in EnsureProviderIdentityInput) (EnsureProviderIdentityResult, error) {
	if strings.TrimSpace(string(in.Identity.Provider)) == "" || strings.TrimSpace(in.Identity.WorkItemID) == "" {
		return EnsureProviderIdentityResult{}, roadmapsync.ErrInvalidIdentity
	}

	tempIdent := in.Identity
	if tempIdent.RoadmapMilestonePath == "" {
		tempIdent.RoadmapMilestonePath = "dummy.md"
	}
	expected, err := tempIdent.Normalize()
	if err != nil {
		return EnsureProviderIdentityResult{}, roadmapsync.ErrInvalidIdentity
	}

	cmd := exec.CommandContext(ctx, "git", "status", "--porcelain", "-uall")
	cmd.Dir = in.WorkspacePath
	out, err := cmd.Output()
	if err != nil {
		return EnsureProviderIdentityResult{}, fmt.Errorf("git status failed: %w", err)
	}

	lines := strings.Split(string(out), "\n")
	var milestoneFiles []string
	for _, line := range lines {
		if len(line) < 4 {
			continue
		}
		// Extract filepath (excluding status prefix and quotes)
		filePath := line[3:]
		filePath = strings.Trim(filePath, "\"")
		filePath = strings.TrimSpace(filePath)

		if strings.HasPrefix(filePath, "agent-roadmap/phase/") &&
			strings.Contains(filePath, "/milestones/") &&
			strings.HasSuffix(filePath, ".md") {
			milestoneFiles = append(milestoneFiles, filePath)
		}
	}

	if len(milestoneFiles) == 0 {
		return EnsureProviderIdentityResult{}, ErrNoMilestonesChanged
	}

	var injected []string
	for _, f := range milestoneFiles {
		fullPath := filepath.Join(in.WorkspacePath, f)
		contentBytes, err := os.ReadFile(fullPath)
		if err != nil {
			return EnsureProviderIdentityResult{}, fmt.Errorf("read file %s failed: %w", f, err)
		}
		content := string(contentBytes)

		existing, err := roadmapsync.ParseMilestoneIdentity(f, content)
		if err == nil {
			if existing.Provider != expected.Provider ||
				existing.Tenant != expected.Tenant ||
				existing.Project != expected.Project ||
				existing.WorkItemID != expected.WorkItemID {
				return EnsureProviderIdentityResult{}, ErrMismatchedProviderIdentity
			}
			// Already has valid and matching identity block
			continue
		}

		if errors.Is(err, roadmapsync.ErrNoProviderIdentity) {
			var sb strings.Builder
			sb.WriteString("\n\n## Provider identity\n")
			if in.Identity.Provider != "" {
				sb.WriteString(fmt.Sprintf("- provider: %s\n", in.Identity.Provider))
			}
			if in.Identity.Tenant != "" {
				sb.WriteString(fmt.Sprintf("- tenant: %s\n", in.Identity.Tenant))
			}
			if in.Identity.Project != "" {
				sb.WriteString(fmt.Sprintf("- project: %s\n", in.Identity.Project))
			}
			if in.Identity.WorkItemID != "" {
				sb.WriteString(fmt.Sprintf("- work item id: %s\n", in.Identity.WorkItemID))
			}
			if in.Identity.RoadmapItemID != "" {
				sb.WriteString(fmt.Sprintf("- milestone id: %s\n", in.Identity.RoadmapItemID))
			}

			newContent := content + sb.String()
			err = os.WriteFile(fullPath, []byte(newContent), 0644)
			if err != nil {
				return EnsureProviderIdentityResult{}, fmt.Errorf("write file %s failed: %w", f, err)
			}
			injected = append(injected, f)
		} else {
			return EnsureProviderIdentityResult{}, fmt.Errorf("parse milestone identity %s failed: %w", f, err)
		}
	}

	return EnsureProviderIdentityResult{
		InjectedPaths: injected,
	}, nil
}
