package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"time"

	"github.com/niels/banking-app/backend/internal/platform/migrations"
)

type output struct {
	GeneratedAt       time.Time              `json:"generated_at"`
	MigrationsDir     string                 `json:"migrations_dir"`
	MigrationCount    int                    `json:"migration_count"`
	RollbackReady     bool                   `json:"rollback_ready"`
	MissingRollbacks  []string               `json:"missing_rollbacks,omitempty"`
	MigrationSequence []migrations.PlanEntry `json:"migration_sequence"`
}

func main() {
	dir := flag.String("dir", "migrations", "directory containing .up.sql and .down.sql migration files")
	format := flag.String("format", "text", "output format: text or json")
	requireRollback := flag.Bool("require-rollback", false, "exit non-zero when any migration is missing a matching .down.sql rollback file")
	flag.Parse()

	plan, err := migrations.Plan(*dir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "migration plan error: %v\n", err)
		os.Exit(1)
	}

	out := output{
		GeneratedAt:       time.Now().UTC(),
		MigrationsDir:     *dir,
		MigrationCount:    len(plan),
		RollbackReady:     true,
		MigrationSequence: plan,
	}
	for _, entry := range plan {
		if !entry.RollbackAvailable {
			out.RollbackReady = false
			out.MissingRollbacks = append(out.MissingRollbacks, entry.Version)
		}
	}

	switch *format {
	case "json":
		encoder := json.NewEncoder(os.Stdout)
		encoder.SetIndent("", "  ")
		if err := encoder.Encode(out); err != nil {
			fmt.Fprintf(os.Stderr, "encode migration plan: %v\n", err)
			os.Exit(1)
		}
	case "text":
		fmt.Printf("Migration directory: %s\n", out.MigrationsDir)
		fmt.Printf("Migration count: %d\n", out.MigrationCount)
		fmt.Printf("Rollback ready: %t\n", out.RollbackReady)
		for _, entry := range out.MigrationSequence {
			rollback := "missing"
			if entry.RollbackAvailable {
				rollback = entry.DownFile
			}
			fmt.Printf("- %s checksum=%s up=%s rollback=%s\n", entry.Version, entry.Checksum, entry.UpFile, rollback)
		}
	default:
		fmt.Fprintf(os.Stderr, "unsupported format %q\n", *format)
		os.Exit(1)
	}

	if *requireRollback && !out.RollbackReady {
		fmt.Fprintf(os.Stderr, "missing rollback files for: %v\n", out.MissingRollbacks)
		os.Exit(2)
	}
}
