package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

type WriteReportsOptions struct {
	AllowBlockedApplyPack bool
}

func WriteReports(report *Report, outputDir string) error {
	return WriteReportsWithOptions(report, outputDir, WriteReportsOptions{})
}

func WriteReportsWithOptions(report *Report, outputDir string, opts WriteReportsOptions) error {
	if report == nil {
		return fmt.Errorf("report is required")
	}
	if strings.TrimSpace(outputDir) == "" {
		return fmt.Errorf("output directory is required")
	}
	if err := os.MkdirAll(outputDir, 0o755); err != nil {
		return fmt.Errorf("create output directory: %w", err)
	}
	jsonBytes, err := json.MarshalIndent(report, "", "  ")
	if err != nil {
		return fmt.Errorf("marshal migration_report.json: %w", err)
	}
	jsonBytes = append(jsonBytes, '\n')
	if err := os.WriteFile(filepath.Join(outputDir, "migration_report.json"), jsonBytes, 0o644); err != nil {
		return fmt.Errorf("write migration_report.json: %w", err)
	}
	if err := os.WriteFile(filepath.Join(outputDir, "migration_report.md"), []byte(RenderMarkdown(report)), 0o644); err != nil {
		return fmt.Errorf("write migration_report.md: %w", err)
	}
	if report.ApplyPack == nil {
		if report.Mode == ModeVerifyZero {
			return nil
		}
		return clearApplyPackFiles(&ApplyPackPlan{PackPath: applyPackPath}, outputDir)
	}
	if report.ApplyPack != nil {
		if report.CutoverBlocked && !opts.AllowBlockedApplyPack {
			if err := clearApplyPackFiles(report.ApplyPack, outputDir); err != nil {
				return err
			}
			return fmt.Errorf("apply-pack artifact generation blocked by %d unsupported item(s); inspect migration reports and rerun with --allow-blockers to emit a partial generated pack", report.Summary.BlockerCount)
		}
		if err := writeApplyPackFiles(report.ApplyPack, outputDir); err != nil {
			return err
		}
	}
	return nil
}

func RenderMarkdown(report *Report) string {
	var b strings.Builder
	fmt.Fprintf(&b, "# WorkflowAlert Migration %s Report\n\n", report.Mode)
	fmt.Fprintf(&b, "- Generated: `%s`\n", report.GeneratedAt)
	fmt.Fprintf(&b, "- Cutover blocked: `%t`\n", report.CutoverBlocked)
	fmt.Fprintf(&b, "- WorkflowAlerts: `%d` active / `%d` total\n", report.Summary.ActiveWorkflowAlertCount, report.Summary.WorkflowAlertCount)
	if report.Summary.HistoricalWorkflowAlertCount > 0 {
		fmt.Fprintf(&b, "- Historical WorkflowAlert inventory rows: `%d`\n", report.Summary.HistoricalWorkflowAlertCount)
	}
	fmt.Fprintf(&b, "- ProcessAction.Alert: `%d` active / `%d` total\n", report.Summary.ActiveProcessActionCount, report.Summary.ProcessActionAlertCount)
	fmt.Fprintf(&b, "- Flow emailAlert actionCalls: `%d`\n", report.Summary.FlowEmailAlertCount)
	fmt.Fprintf(&b, "- Referenced templates: `%d`\n", report.Summary.ReferencedTemplateCount)
	fmt.Fprintf(&b, "- Blockers: `%d`\n\n", report.Summary.BlockerCount)

	if len(report.UnsupportedItems) > 0 {
		b.WriteString("## Blockers And Unsupported Items\n\n")
		for _, item := range report.UnsupportedItems {
			fmt.Fprintf(&b, "- `%s` `%s/%s` `%s`: %s", item.Severity, item.SourceType, item.SourceKey, item.Code, item.Message)
			if item.Recommendation != "" {
				fmt.Fprintf(&b, " Recommendation: %s", item.Recommendation)
			}
			b.WriteString("\n")
		}
		b.WriteString("\n")
	}
	if report.DryRun != nil {
		b.WriteString("## Dry-Run Plan\n\n")
		for _, action := range report.DryRun.ProposedSendEmailActions {
			fmt.Fprintf(&b, "- `%s/%s` -> `%s` `%s` template `%s`", action.SourceType, action.SourceKey, action.ActionType, action.ActionName, action.TemplateID)
			if len(action.Prerequisites) > 0 {
				fmt.Fprintf(&b, " prerequisites: `%s`", strings.Join(action.Prerequisites, "`, `"))
			}
			if len(action.BlockedBy) > 0 {
				fmt.Fprintf(&b, " blocked by: `%s`", strings.Join(action.BlockedBy, "`, `"))
			}
			b.WriteString("\n")
		}
		b.WriteString("\n")
	}
	if report.VerifyZero != nil {
		b.WriteString("## Verify-Zero Gate\n\n")
		status := "PASS"
		if !report.VerifyZero.Passed {
			status = "FAIL"
		}
		fmt.Fprintf(&b, "- Status: `%s`\n", status)
		if report.VerifyZero.OfficialPackRoot != "" {
			fmt.Fprintf(&b, "- Official pack root: `%s`\n", report.VerifyZero.OfficialPackRoot)
		}
		fmt.Fprintf(&b, "- Official packs scanned: `%d`\n", report.VerifyZero.ScannedOfficialPackCount)
		fmt.Fprintf(&b, "- Active dependencies: `%d`\n", report.VerifyZero.ActiveDependencyCount)
		if report.VerifyZero.ExistingBlockerCount > 0 {
			fmt.Fprintf(&b, "- Existing blocker count: `%d`\n", report.VerifyZero.ExistingBlockerCount)
		}
		if len(report.VerifyZero.HistoricalWorkflowRows) > 0 {
			fmt.Fprintf(&b, "- Historical WorkflowAlert rows: `%d`\n", len(report.VerifyZero.HistoricalWorkflowRows))
		}
		b.WriteString("\n")
		if len(report.VerifyZero.ActiveDependencies) > 0 {
			b.WriteString("### Active Dependencies\n\n")
			for _, dependency := range report.VerifyZero.ActiveDependencies {
				fmt.Fprintf(&b, "- `%s` `%s/%s`: %s", dependency.Type, dependency.SourceType, dependency.SourceKey, dependency.Message)
				if len(dependency.References) > 0 {
					fmt.Fprintf(&b, " References: `%s`", strings.Join(dependency.References, "`, `"))
				}
				if dependency.Recommendation != "" {
					fmt.Fprintf(&b, " Recommendation: %s", dependency.Recommendation)
				}
				b.WriteString("\n")
			}
			b.WriteString("\n")
		}
		if len(report.VerifyZero.HistoricalWorkflowRows) > 0 {
			b.WriteString("### Historical WorkflowAlert Rows\n\n")
			for _, row := range report.VerifyZero.HistoricalWorkflowRows {
				fmt.Fprintf(&b, "- `%s`: %s\n", row.SourceKey, row.Reason)
			}
			b.WriteString("\n")
		}
	}
	if report.ApplyPack != nil {
		b.WriteString("## Apply-Pack Output\n\n")
		fmt.Fprintf(&b, "- Pack path: `%s`\n", report.ApplyPack.PackPath)
		fmt.Fprintf(&b, "- Generated templates: `%d`\n", len(report.ApplyPack.GeneratedEmailTemplates))
		fmt.Fprintf(&b, "- Generated flows: `%d`\n", len(report.ApplyPack.GeneratedFlows))
		fmt.Fprintf(&b, "- Skipped actions: `%d`\n\n", len(report.ApplyPack.SkippedActions))
	}
	return b.String()
}
