package converter

import (
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
)

// ToReviewContext converts a store review context to its API DTO shape.
func ToReviewContext(rc *agent.ReviewContext) *dto.ReviewContext {
	if rc == nil {
		return nil
	}
	return &dto.ReviewContext{
		ID:                rc.ID,
		WorkspaceID:       rc.WorkspaceID,
		ThreadID:          strings.TrimSpace(rc.ThreadID),
		TaskScopeID:       strings.TrimSpace(rc.TaskScopeID),
		MachineID:         rc.MachineID,
		SourceAgentID:     rc.SourceAgentID,
		Kind:              "git_repo",
		RootPath:          rc.RootPath,
		DisplayName:       rc.DisplayName,
		HeadRef:           rc.HeadRef,
		BaseRef:           rc.BaseRef,
		PRURL:             rc.PRURL,
		ProjectID:         rc.ProjectID,
		CreatedByMemberID: rc.CreatedByMember,
		UpdatedByMemberID: rc.UpdatedByMember,
		CreatedAt:         rc.CreatedAt,
		UpdatedAt:         rc.UpdatedAt,
	}
}

// ToReviewContexts converts store review contexts to API DTOs.
func ToReviewContexts(contexts []agent.ReviewContext) []dto.ReviewContext {
	if len(contexts) == 0 {
		return []dto.ReviewContext{}
	}
	items := make([]dto.ReviewContext, 0, len(contexts))
	for i := range contexts {
		if converted := ToReviewContext(&contexts[i]); converted != nil {
			items = append(items, *converted)
		}
	}
	return items
}

// ToReview projects a review context onto the Review Center DTO shape.
func ToReview(rc *agent.ReviewContext) *dto.Review {
	if rc == nil {
		return nil
	}
	out := &dto.Review{
		ID:            rc.ID,
		WorkspaceID:   rc.WorkspaceID,
		ProjectID:     strings.TrimSpace(rc.ProjectID),
		ThreadID:      strings.TrimSpace(rc.ThreadID),
		TaskScopeID:   strings.TrimSpace(rc.TaskScopeID),
		SourceAgentID: strings.TrimSpace(rc.SourceAgentID),
		MachineID:     rc.MachineID,
		RootPath:      rc.RootPath,
		BaseRef:       rc.BaseRef,
		HeadRef:       rc.HeadRef,
		DisplayName:   rc.DisplayName,
		PRURL:         rc.PRURL,
		CreatedAt:     rc.CreatedAt,
	}
	return out
}

func ToWorkspaceFile(file agent.WorkspaceFile) dto.WorkspaceFile {
	return dto.WorkspaceFile{
		Name:           file.Name,
		Path:           file.Path,
		IsDirectory:    file.IsDirectory,
		Size:           file.Size,
		ModifiedAt:     file.ModifiedAt,
		ChildDirCount:  file.ChildDirCount,
		ChildFileCount: file.ChildFileCount,
	}
}

func ToWorkspaceFiles(files []agent.WorkspaceFile) []dto.WorkspaceFile {
	if len(files) == 0 {
		return []dto.WorkspaceFile{}
	}
	items := make([]dto.WorkspaceFile, 0, len(files))
	for _, file := range files {
		items = append(items, ToWorkspaceFile(file))
	}
	return items
}

func ToWorkspaceFileContent(content agent.WorkspaceFileContent) dto.WorkspaceFileContent {
	return dto.WorkspaceFileContent{Content: content.Content, Binary: content.Binary}
}

func ToWorkspaceDirectory(directory agent.WorkspaceDirectory) dto.WorkspaceDirectory {
	return dto.WorkspaceDirectory{
		DirectoryName:  directory.DirectoryName,
		TotalSizeBytes: directory.TotalSizeBytes,
		LastModified:   directory.LastModified,
		FileCount:      directory.FileCount,
	}
}

func ToWorkspaceDirectories(directories []agent.WorkspaceDirectory) []dto.WorkspaceDirectory {
	if len(directories) == 0 {
		return []dto.WorkspaceDirectory{}
	}
	items := make([]dto.WorkspaceDirectory, 0, len(directories))
	for _, directory := range directories {
		items = append(items, ToWorkspaceDirectory(directory))
	}
	return items
}

func ToAgentReviewSummary(summary agent.AgentReviewSummary) dto.AgentReviewSummary {
	return dto.AgentReviewSummary{
		Status:               summary.Status,
		Message:              summary.Message,
		RepositoryRoot:       summary.RepositoryRoot,
		Branch:               summary.Branch,
		DefaultBranch:        summary.DefaultBranch,
		BaseRef:              summary.BaseRef,
		HeadRef:              summary.HeadRef,
		ComparisonMode:       summary.ComparisonMode,
		AvailableRefs:        summary.AvailableRefs,
		CompareRef:           summary.CompareRef,
		AvailableCompareRefs: summary.AvailableCompareRefs,
		HeadCommit:           summary.HeadCommit,
		MergeBaseCommit:      summary.MergeBaseCommit,
		AheadCount:           summary.AheadCount,
		BehindCount:          summary.BehindCount,
		Dirty:                summary.Dirty,
		BranchFileCount:      summary.BranchFileCount,
		BranchAdditionCount:  summary.BranchAdditionCount,
		BranchDeletionCount:  summary.BranchDeletionCount,
		WorkingAdditionCount: summary.WorkingAdditionCount,
		WorkingDeletionCount: summary.WorkingDeletionCount,
		StagedFileCount:      summary.StagedFileCount,
		UnstagedFileCount:    summary.UnstagedFileCount,
		LastScannedAt:        summary.LastScannedAt,
	}
}

func ToAgentReviewFile(file agent.AgentReviewFile) dto.AgentReviewFile {
	return dto.AgentReviewFile{
		Path:               file.Path,
		OldPath:            file.OldPath,
		ChangeType:         file.ChangeType,
		Staged:             file.Staged,
		Unstaged:           file.Unstaged,
		StagedChangeType:   file.StagedChangeType,
		UnstagedChangeType: file.UnstagedChangeType,
		Token:              file.Token,
	}
}

func ToAgentReviewFiles(files []agent.AgentReviewFile) []dto.AgentReviewFile {
	if len(files) == 0 {
		return []dto.AgentReviewFile{}
	}
	items := make([]dto.AgentReviewFile, 0, len(files))
	for _, file := range files {
		items = append(items, ToAgentReviewFile(file))
	}
	return items
}

func ToAgentReviewSnapshot(snapshot agent.AgentReviewSnapshot) dto.AgentReviewSnapshot {
	return dto.AgentReviewSnapshot{
		Summary:             ToAgentReviewSummary(snapshot.Summary),
		Files:               ToAgentReviewFiles(snapshot.Files),
		WorkingFiles:        ToAgentReviewFiles(snapshot.WorkingFiles),
		InitialDiffs:        ToAgentReviewDiffMap(snapshot.InitialDiffs),
		InitialWorkingDiffs: ToAgentReviewDiffMap(snapshot.InitialWorkingDiffs),
	}
}

func ToAgentReviewFingerprint(fingerprint agent.AgentReviewFingerprint) dto.AgentReviewFingerprint {
	return dto.AgentReviewFingerprint{
		HeadCommit:        fingerprint.HeadCommit,
		BaseRef:           fingerprint.BaseRef,
		HeadRef:           fingerprint.HeadRef,
		ComparisonMode:    fingerprint.ComparisonMode,
		RepositoryToken:   fingerprint.RepositoryToken,
		BranchToken:       fingerprint.BranchToken,
		WorkingToken:      fingerprint.WorkingToken,
		WorkingStrength:   fingerprint.WorkingStrength,
		ObservedAt:        fingerprint.ObservedAt,
		NextRefreshAt:     fingerprint.NextRefreshAt,
		WorkingStateFresh: fingerprint.WorkingStateFresh,
		BranchFileCount:   fingerprint.BranchFileCount,
		StagedFileCount:   fingerprint.StagedFileCount,
		UnstagedFileCount: fingerprint.UnstagedFileCount,
	}
}

func ToAgentReviewDiffSection(section agent.AgentReviewDiffSection) dto.AgentReviewDiffSection {
	return dto.AgentReviewDiffSection{
		Key:        section.Key,
		Label:      section.Label,
		Diff:       section.Diff,
		OldText:    section.OldText,
		NewText:    section.NewText,
		ChangeType: section.ChangeType,
		Message:    section.Message,
		Binary:     section.Binary,
		TooLarge:   section.TooLarge,
	}
}

func ToAgentReviewDiffSections(sections []agent.AgentReviewDiffSection) []dto.AgentReviewDiffSection {
	if len(sections) == 0 {
		return nil
	}
	items := make([]dto.AgentReviewDiffSection, 0, len(sections))
	for _, section := range sections {
		items = append(items, ToAgentReviewDiffSection(section))
	}
	return items
}

func ToAgentReviewDiff(diff agent.AgentReviewDiff) dto.AgentReviewDiff {
	return dto.AgentReviewDiff{
		Status:     diff.Status,
		Message:    diff.Message,
		Path:       diff.Path,
		OldPath:    diff.OldPath,
		ChangeType: diff.ChangeType,
		Sections:   ToAgentReviewDiffSections(diff.Sections),
	}
}

func ToAgentReviewDiffMap(diffs map[string]agent.AgentReviewDiff) map[string]dto.AgentReviewDiff {
	if len(diffs) == 0 {
		return nil
	}
	items := make(map[string]dto.AgentReviewDiff, len(diffs))
	for path, diff := range diffs {
		items[path] = ToAgentReviewDiff(diff)
	}
	return items
}
