// 将 data/*.json（站点与分组）导入 MySQL。建议空库首次使用，或加 -wipe 清空业务表后再导。
//
//	go run ./cmd/importjson -data ./data -wipe
package main

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

	"gorm.io/datatypes"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"

	"mengyaping-backend/config"
	"mengyaping-backend/models"
	"mengyaping-backend/storage"
)

func main() {
	dataDir := flag.String("data", "./data", "JSON 目录（websites.json、groups.json）")
	wipe := flag.Bool("wipe", false, "导入前 TRUNCATE 所有 monitor_* 表（慎用）")
	flag.Parse()

	cfg := config.GetConfig()
	// 大批量 INSERT 时单条超过 200ms 会触发 GORM 默认「SLOW SQL」提示，易被误认为报错；导入工具改为静默 SQL 日志
	db, err := gorm.Open(mysql.Open(cfg.DatabaseDSN()), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Silent),
	})
	if err != nil {
		log.Fatal(err)
	}

	if err := db.AutoMigrate(
		&storage.MonitorGroup{},
		&storage.MonitorWebsite{},
		&storage.MonitorWebsiteURL{},
		&storage.MonitorWebsiteGroup{},
		&storage.MonitorProbeLatest{},
		&storage.MonitorProbeHour{},
		&storage.MonitorProbeDay{},
		&storage.MonitorKV{},
	); err != nil {
		log.Fatal(err)
	}

	if *wipe {
		_ = db.Exec("SET FOREIGN_KEY_CHECKS = 0").Error
		for _, tbl := range []string{
			"monitor_probe_latest",
			"monitor_probe_hour",
			"monitor_probe_day",
			"monitor_kv",
			"monitor_checks",
			"monitor_website_urls",
			"monitor_website_groups",
			"monitor_websites",
			"monitor_groups",
		} {
			_ = db.Exec("TRUNCATE TABLE " + tbl).Error
		}
		_ = db.Exec("SET FOREIGN_KEY_CHECKS = 1").Error
		log.Println("已清空 monitor_* 表")
	}

	websitesPath := filepath.Join(*dataDir, "websites.json")
	raw, err := os.ReadFile(websitesPath)
	if err != nil {
		log.Fatalf("读取 websites.json: %v", err)
	}
	var websites []models.Website
	if err := json.Unmarshal(raw, &websites); err != nil {
		log.Fatal(err)
	}

	groupsPath := filepath.Join(*dataDir, "groups.json")
	var fileGroups []models.Group
	if g, err := os.ReadFile(groupsPath); err == nil {
		_ = json.Unmarshal(g, &fileGroups)
	}
	if len(fileGroups) == 0 {
		fileGroups = models.DefaultGroups
	}
	for i, g := range fileGroups {
		if err := db.Create(&storage.MonitorGroup{
			ID: g.ID, Name: g.Name, SortOrder: i + 1,
		}).Error; err != nil {
			log.Printf("导入分组 %s: %v", g.ID, err)
		}
	}

	for _, w := range websites {
		if len(w.Groups) == 0 && w.Group != "" {
			w.Groups = []string{w.Group}
		}
		row := &storage.MonitorWebsite{
			ID:          w.ID,
			Name:        w.Name,
			LegacyGroup: "",
			Favicon:     w.Favicon,
			Title:       w.Title,
			IPAddresses: datatypes.JSON(mustJSON(w.IPAddresses)),
			CreatedAt:   w.CreatedAt,
			UpdatedAt:   w.UpdatedAt,
		}
		if err := db.Create(row).Error; err != nil {
			log.Printf("网站 %s: %v", w.ID, err)
			continue
		}
		for i, u := range w.URLs {
			_ = db.Create(&storage.MonitorWebsiteURL{
				WebsiteID: w.ID, URLID: u.ID, URL: u.URL, Remark: u.Remark, SortOrder: i,
			})
		}
		for _, gid := range w.Groups {
			_ = db.Create(&storage.MonitorWebsiteGroup{WebsiteID: w.ID, GroupID: gid})
		}
	}
	fmt.Printf("已导入 %d 个网站\n", len(websites))
	log.Println("探测历史由运行时写入 monitor_probe_* 汇总表，不再从 records.json 导入")
}

func mustJSON(v []string) []byte {
	if v == nil {
		return []byte("[]")
	}
	b, err := json.Marshal(v)
	if err != nil {
		return []byte("[]")
	}
	return b
}
