//go:build ignore

package main

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

	"github.com/glebarez/sqlite"
	"gorm.io/gorm"
)

type snapshot struct {
	GeneratedAt string           `json:"generated_at"`
	Path        string           `json:"path"`
	FileSize    int64            `json:"file_size"`
	Existing    []string         `json:"existing_tables"`
	Missing     []string         `json:"missing_tables"`
	Tables      map[string]int64 `json:"tables"`
	SampleUsers []string         `json:"sample_users"`
}

func main() {
	dbPath := flag.String("db", "./data/user_management.db", "sqlite database path")
	jsonOutput := flag.Bool("json", false, "emit snapshot as JSON")
	flag.Parse()

	info, err := os.Stat(*dbPath)
	if err != nil {
		log.Fatalf("stat db failed: %v", err)
	}

	db, err := gorm.Open(sqlite.Open(*dbPath), &gorm.Config{})
	if err != nil {
		log.Fatalf("open db failed: %v", err)
	}

	tableNames := []string{
		"users",
		"roles",
		"permissions",
		"user_roles",
		"role_permissions",
		"devices",
		"login_logs",
		"operation_logs",
		"social_accounts",
		"webhooks",
		"webhook_deliveries",
		"password_histories",
	}

	var existingTables []string
	if err := db.Raw("SELECT name FROM sqlite_master WHERE type = 'table'").Scan(&existingTables).Error; err != nil {
		log.Fatalf("load sqlite table names failed: %v", err)
	}
	sort.Strings(existingTables)
	existingTableSet := make(map[string]struct{}, len(existingTables))
	for _, tableName := range existingTables {
		existingTableSet[tableName] = struct{}{}
	}

	tableCounts := make(map[string]int64, len(tableNames))
	missingTables := make([]string, 0)
	for _, tableName := range tableNames {
		if _, ok := existingTableSet[tableName]; !ok {
			missingTables = append(missingTables, tableName)
			continue
		}
		var count int64
		if err := db.Raw("SELECT COUNT(*) FROM " + tableName).Scan(&count).Error; err != nil {
			log.Fatalf("count table %s failed: %v", tableName, err)
		}
		tableCounts[tableName] = count
	}

	var sampleUsers []string
	if err := db.Raw("SELECT username FROM users ORDER BY id ASC LIMIT 10").Scan(&sampleUsers).Error; err != nil {
		log.Fatalf("load sample users failed: %v", err)
	}
	sort.Strings(sampleUsers)

	result := snapshot{
		GeneratedAt: time.Now().Format(time.RFC3339),
		Path:        *dbPath,
		FileSize:    info.Size(),
		Existing:    existingTables,
		Missing:     missingTables,
		Tables:      tableCounts,
		SampleUsers: sampleUsers,
	}

	if *jsonOutput {
		encoder := json.NewEncoder(os.Stdout)
		encoder.SetIndent("", "  ")
		if err := encoder.Encode(result); err != nil {
			log.Fatalf("encode snapshot failed: %v", err)
		}
		return
	}

	fmt.Printf("snapshot generated_at=%s\n", result.GeneratedAt)
	fmt.Printf("path=%s size=%d\n", result.Path, result.FileSize)
	for _, tableName := range tableNames {
		if count, ok := result.Tables[tableName]; ok {
			fmt.Printf("%s=%d\n", tableName, count)
			continue
		}
		fmt.Printf("%s=missing\n", tableName)
	}
	fmt.Printf("sample_users=%v\n", result.SampleUsers)
}
