// migrate 将历史上导出的 JSON 数据文件导入 MySQL。
// 在切到数据库存储方式后执行一次即可：
//
//	go run ./cmd/migrate/main.go
package main

import (
	"encoding/json"
	"log"
	"os"
	"strconv"
	"time"

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

	"mengyastore-backend/internal/config"
	"mengyastore-backend/internal/database"
)

func main() {
	// 从环境变量 / .env.development 加载（在仓库根目录执行 go run ./cmd/migrate，或设置 ENV_FILE）。
	cfg, err := config.Load()
	if err != nil {
		log.Fatalf("load config: %v", err)
	}

	db, err := gorm.Open(mysql.Open(cfg.DatabaseDSN), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		log.Fatalf("open db: %v", err)
	}

	// 确保表结构存在
	if err := db.AutoMigrate(
		&database.ProductRow{},
		&database.ProductCodeRow{},
		&database.OrderRow{},
		&database.SiteSettingRow{},
		&database.WishlistRow{},
		&database.ChatMessageRow{},
	); err != nil {
		log.Fatalf("auto migrate: %v", err)
	}

	log.Println("数据库连接成功，开始导入...")
	migrateProducts(db)
	migrateOrders(db)
	migrateWishlists(db)
	migrateChats(db)
	migrateSite(db)
	log.Println("✅ 数据导入完成！")
}

// ─── 商品 ─────────────────────────────────────────────────────────────────────

type jsonProduct struct {
	ID             string    `json:"id"`
	Name           string    `json:"name"`
	Price          float64   `json:"price"`
	DiscountPrice  float64   `json:"discountPrice"`
	Tags           []string  `json:"tags"`
	CoverURL       string    `json:"coverUrl"`
	ScreenshotURLs []string  `json:"screenshotUrls"`
	Description    string    `json:"description"`
	Active         bool      `json:"active"`
	RequireLogin   bool      `json:"requireLogin"`
	MaxPerAccount  int       `json:"maxPerAccount"`
	TotalSold      int       `json:"totalSold"`
	ViewCount      int       `json:"viewCount"`
	DeliveryMode   string    `json:"deliveryMode"`
	ShowNote       bool      `json:"showNote"`
	ShowContact    bool      `json:"showContact"`
	Codes          []string  `json:"codes"`
	CreatedAt      time.Time `json:"createdAt"`
}

func migrateProducts(db *gorm.DB) {
	data, err := os.ReadFile("data/json/products.json")
	if err != nil {
		log.Printf("[products] 文件不存在，跳过: %v", err)
		return
	}
	var products []jsonProduct
	if err := json.Unmarshal(data, &products); err != nil {
		log.Printf("[products] JSON 解析失败: %v", err)
		return
	}
	for _, p := range products {
		if p.ID == "" {
			continue
		}
		if p.DeliveryMode == "" {
			p.DeliveryMode = "auto"
		}
		row := database.ProductRow{
			ID:             p.ID,
			Name:           p.Name,
			Price:          p.Price,
			DiscountPrice:  p.DiscountPrice,
			Tags:           database.StringSlice(p.Tags),
			CoverURL:       p.CoverURL,
			ScreenshotURLs: database.StringSlice(p.ScreenshotURLs),
			Description:    p.Description,
			Active:         p.Active,
			RequireLogin:   p.RequireLogin,
			MaxPerAccount:  p.MaxPerAccount,
			TotalSold:      p.TotalSold,
			ViewCount:      p.ViewCount,
			DeliveryMode:   p.DeliveryMode,
			ShowNote:       p.ShowNote,
			ShowContact:    p.ShowContact,
			CreatedAt:      p.CreatedAt,
		}
		if row.CreatedAt.IsZero() {
			row.CreatedAt = time.Now()
		}
		result := db.Clauses(clause.OnConflict{DoNothing: true}).Create(&row)
		if result.Error != nil {
			log.Printf("[products] 导入 %s 失败: %v", p.ID, result.Error)
			continue
		}
		// 卡密写入 product_codes 表
		for _, code := range p.Codes {
			if code == "" {
				continue
			}
			db.Clauses(clause.OnConflict{DoNothing: true}).Create(&database.ProductCodeRow{
				ProductID: p.ID,
				Code:      code,
			})
		}
	}
	log.Printf("[products] 导入 %d 条商品", len(products))
}

// ─── 订单 ─────────────────────────────────────────────────────────────────────

type jsonOrder struct {
	ID             string    `json:"id"`
	ProductID      string    `json:"productId"`
	ProductName    string    `json:"productName"`
	UserAccount    string    `json:"userAccount"`
	UserName       string    `json:"userName"`
	Quantity       int       `json:"quantity"`
	DeliveredCodes []string  `json:"deliveredCodes"`
	Status         string    `json:"status"`
	DeliveryMode   string    `json:"deliveryMode"`
	Note           string    `json:"note"`
	ContactPhone   string    `json:"contactPhone"`
	ContactEmail   string    `json:"contactEmail"`
	CreatedAt      time.Time `json:"createdAt"`
}

func migrateOrders(db *gorm.DB) {
	data, err := os.ReadFile("data/json/orders.json")
	if err != nil {
		log.Printf("[orders] 文件不存在，跳过: %v", err)
		return
	}
	var orders []jsonOrder
	if err := json.Unmarshal(data, &orders); err != nil {
		log.Printf("[orders] JSON 解析失败: %v", err)
		return
	}
	for _, o := range orders {
		if o.ID == "" {
			continue
		}
		if o.DeliveryMode == "" {
			o.DeliveryMode = "auto"
		}
		if o.DeliveredCodes == nil {
			o.DeliveredCodes = []string{}
		}
		row := database.OrderRow{
			ID:             o.ID,
			ProductID:      o.ProductID,
			ProductName:    o.ProductName,
			UserAccount:    o.UserAccount,
			UserName:       o.UserName,
			Quantity:       o.Quantity,
			DeliveredCodes: database.StringSlice(o.DeliveredCodes),
			Status:         o.Status,
			DeliveryMode:   o.DeliveryMode,
			Note:           o.Note,
			ContactPhone:   o.ContactPhone,
			ContactEmail:   o.ContactEmail,
			CreatedAt:      o.CreatedAt,
		}
		if row.CreatedAt.IsZero() {
			row.CreatedAt = time.Now()
		}
		if result := db.Clauses(clause.OnConflict{DoNothing: true}).Create(&row); result.Error != nil {
			log.Printf("[orders] 导入 %s 失败: %v", o.ID, result.Error)
		}
	}
	log.Printf("[orders] 导入 %d 条订单", len(orders))
}

// ─── 收藏夹 ───────────────────────────────────────────────────────────────────

func migrateWishlists(db *gorm.DB) {
	data, err := os.ReadFile("data/json/wishlists.json")
	if err != nil {
		log.Printf("[wishlists] 文件不存在，跳过: %v", err)
		return
	}
	var wl map[string][]string
	if err := json.Unmarshal(data, &wl); err != nil {
		log.Printf("[wishlists] JSON 解析失败: %v", err)
		return
	}
	count := 0
	for account, productIDs := range wl {
		for _, pid := range productIDs {
			db.Clauses(clause.OnConflict{DoNothing: true}).Create(&database.WishlistRow{
				AccountID: account,
				ProductID: pid,
			})
			count++
		}
	}
	log.Printf("[wishlists] 导入 %d 条收藏记录", count)
}

// ─── 聊天 ─────────────────────────────────────────────────────────────────────

type jsonChatMsg struct {
	ID          string    `json:"id"`
	AccountID   string    `json:"accountId"`
	AccountName string    `json:"accountName"`
	Content     string    `json:"content"`
	SentAt      time.Time `json:"sentAt"`
	FromAdmin   bool      `json:"fromAdmin"`
}

func migrateChats(db *gorm.DB) {
	data, err := os.ReadFile("data/json/chats.json")
	if err != nil {
		log.Printf("[chats] 文件不存在，跳过: %v", err)
		return
	}
	var convs map[string][]jsonChatMsg
	if err := json.Unmarshal(data, &convs); err != nil {
		log.Printf("[chats] JSON 解析失败: %v", err)
		return
	}
	count := 0
	for _, msgs := range convs {
		for _, m := range msgs {
			if m.ID == "" {
				continue
			}
			db.Clauses(clause.OnConflict{DoNothing: true}).Create(&database.ChatMessageRow{
				ID:          m.ID,
				AccountID:   m.AccountID,
				AccountName: m.AccountName,
				Content:     m.Content,
				SentAt:      m.SentAt,
				FromAdmin:   m.FromAdmin,
			})
			count++
		}
	}
	log.Printf("[chats] 导入 %d 条聊天消息", count)
}

// ─── 站点设置 ─────────────────────────────────────────────────────────────────

type jsonSite struct {
	TotalVisits       int    `json:"totalVisits"`
	Maintenance       bool   `json:"maintenance"`
	MaintenanceReason string `json:"maintenanceReason"`
}

func migrateSite(db *gorm.DB) {
	data, err := os.ReadFile("data/json/site.json")
	if err != nil {
		log.Printf("[site] 文件不存在，跳过: %v", err)
		return
	}
	var site jsonSite
	if err := json.Unmarshal(data, &site); err != nil {
		log.Printf("[site] JSON 解析失败: %v", err)
		return
	}
	upsert := func(key, value string) {
		db.Clauses(clause.OnConflict{
			Columns:   []clause.Column{{Name: "key"}},
			DoUpdates: clause.AssignmentColumns([]string{"value"}),
		}).Create(&database.SiteSettingRow{Key: key, Value: value})
	}
	upsert("totalVisits", strconv.Itoa(site.TotalVisits))
	maintenance := "false"
	if site.Maintenance {
		maintenance = "true"
	}
	upsert("maintenance", maintenance)
	upsert("maintenanceReason", site.MaintenanceReason)
	log.Printf("[site] 站点设置导入完成（访问量: %d）", site.TotalVisits)
}
