// Command backbeat-validate provides CLI validation of BACKBEAT messages for CI integration
package main

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

	"github.com/chorus-services/backbeat/contracts/tests/integration"
)

func main() {
	var (
		schemaDir   = flag.String("schemas", "", "Path to BACKBEAT schema directory (required)")
		validateDir = flag.String("dir", "", "Directory to validate (optional)")
		validateFile = flag.String("file", "", "Single file to validate (optional)")
		messageJSON = flag.String("message", "", "JSON message to validate (optional)")
		examples    = flag.Bool("examples", false, "Validate built-in examples")
		quiet       = flag.Bool("quiet", false, "Only output errors")
		json_output = flag.Bool("json", false, "Output results as JSON")
		exitCode    = flag.Bool("exit-code", true, "Exit with non-zero code on validation failures")
	)
	flag.Parse()

	if *schemaDir == "" {
		fmt.Fprintf(os.Stderr, "Error: --schemas parameter is required\n")
		flag.Usage()
		os.Exit(1)
	}

	// Create CI helper
	helper, err := integration.NewCIHelper(*schemaDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating validator: %v\n", err)
		os.Exit(1)
	}

	// Determine what to validate
	switch {
	case *examples:
		validateExamples(helper, *quiet, *json_output, *exitCode)
	case *validateDir != "":
		validateDirectory(helper, *validateDir, *quiet, *json_output, *exitCode)
	case *validateFile != "":
		validateFile_func(helper, *validateFile, *quiet, *json_output, *exitCode)
	case *messageJSON != "":
		validateMessage(helper, *messageJSON, *quiet, *json_output, *exitCode)
	default:
		fmt.Fprintf(os.Stderr, "Error: must specify one of --dir, --file, --message, or --examples\n")
		flag.Usage()
		os.Exit(1)
	}
}

func validateExamples(helper *integration.CIHelper, quiet, jsonOutput, exitOnError bool) {
	results, err := helper.ValidateExamples()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error validating examples: %v\n", err)
		os.Exit(1)
	}

	invalidCount := 0
	for _, result := range results {
		if !result.Valid {
			invalidCount++
		}
		
		if !quiet || !result.Valid {
			if jsonOutput {
				jsonBytes, _ := json.MarshalIndent(result, "", "  ")
				fmt.Println(string(jsonBytes))
			} else {
				fmt.Print(integration.PrettyPrintValidationResult(result))
				fmt.Println(strings.Repeat("-", 50))
			}
		}
	}

	if !quiet {
		fmt.Printf("\nSummary: %d total, %d valid, %d invalid\n", len(results), len(results)-invalidCount, invalidCount)
	}

	if exitOnError && invalidCount > 0 {
		os.Exit(1)
	}
}

func validateDirectory(helper *integration.CIHelper, dir string, quiet, jsonOutput, exitOnError bool) {
	result, err := helper.ValidateDirectory(dir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error validating directory: %v\n", err)
		os.Exit(1)
	}

	if jsonOutput {
		jsonBytes, _ := json.MarshalIndent(result, "", "  ")
		fmt.Println(string(jsonBytes))
	} else if !quiet {
		fmt.Print(helper.GenerateCIReport(result))
	}

	if exitOnError && (result.InvalidFiles > 0 || len(result.Errors) > 0) {
		if quiet {
			fmt.Fprintf(os.Stderr, "Validation failed: %d invalid files, %d errors\n", result.InvalidFiles, len(result.Errors))
		}
		os.Exit(1)
	}
}

func validateFile_func(helper *integration.CIHelper, filePath string, quiet, jsonOutput, exitOnError bool) {
	// Create a temporary directory for validation
	tmpDir := filepath.Dir(filePath)
	result, err := helper.ValidateDirectory(tmpDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error validating file: %v\n", err)
		os.Exit(1)
	}

	// Filter results to just this file
	fileName := filepath.Base(filePath)
	fileResult, exists := result.Files[fileName]
	if !exists {
		fmt.Fprintf(os.Stderr, "File was not validated (may not contain BACKBEAT messages)\n")
		os.Exit(1)
	}

	if jsonOutput {
		jsonBytes, _ := json.MarshalIndent(fileResult, "", "  ")
		fmt.Println(string(jsonBytes))
	} else if !quiet {
		fmt.Printf("File: %s\n", fileName)
		fmt.Printf("Valid: %t\n", fileResult.AllValid)
		
		if len(fileResult.Errors) > 0 {
			fmt.Println("Errors:")
			for _, err := range fileResult.Errors {
				fmt.Printf("  - %s\n", err)
			}
		}
		
		for i, msg := range fileResult.Messages {
			fmt.Printf("\nMessage %d:\n", i+1)
			fmt.Print(integration.PrettyPrintValidationResult(msg))
		}
	}

	if exitOnError && !fileResult.AllValid {
		if quiet {
			fmt.Fprintf(os.Stderr, "Validation failed\n")
		}
		os.Exit(1)
	}
}

func validateMessage(helper *integration.CIHelper, messageJSON string, quiet, jsonOutput, exitOnError bool) {
	validator, err := integration.NewMessageValidator(flag.Lookup("schemas").Value.String())
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating validator: %v\n", err)
		os.Exit(1)
	}

	result, err := validator.ValidateMessageString(messageJSON)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error validating message: %v\n", err)
		os.Exit(1)
	}

	if jsonOutput {
		jsonBytes, _ := json.MarshalIndent(result, "", "  ")
		fmt.Println(string(jsonBytes))
	} else if !quiet {
		fmt.Print(integration.PrettyPrintValidationResult(result))
	}

	if exitOnError && !result.Valid {
		if quiet {
			fmt.Fprintf(os.Stderr, "Validation failed\n")
		}
		os.Exit(1)
	}
}