package db

import (
	"go.uber.org/zap"

	"cold-delivery/app/admin/model"
	jobModel "cold-delivery/app/jobs/model"
	"fmt"
	"log"
	"os"
	"strings"

	"gorm.io/gorm"
)

// 执行数据迁移
func AutoMigrateDB() {
	//自动迁移模式
	err := DB.Set("gorm:table_options", "charset=utf8mb4").
		AutoMigrate(
			&jobModel.SysJob{},
			&model.SysUser{},
			&model.SysRole{},
			&model.SysRoleMenu{},
			&model.SysMenu{},
			&model.SysDept{},
			&model.SysLoginLog{},
			&model.SysOperaLog{},
			&model.Address{},
			&model.AddressDefault{},
			&model.CoolerBox{},
			&model.Waybill{},
			&model.WaybillLogistics{},
			&model.WaybillTask{},
			&model.IceRaft{},
			&model.IceLocker{},
			&model.IceRaftRecord{},
			&model.CoolerBoxRecord{},
			&model.Drug{},
			&model.SysPost{},
			&model.SysPostMenu{},
		)
	if err != nil {
		zap.L().Panic("migrate db fail", zap.Error(err))
	}
}

// AutoSeedMenus 检查并初始化菜单数据
func AutoSeedMenus() {
	var count int64
	DB.Table("sys_menu").Count(&count)
	if count > 0 {
		return
	}
	log.Println("sys_menu 表为空，开始初始化菜单数据...")
	err := ExecSqlFile(DB, "conf/menu_seed.sql")
	if err != nil {
		log.Printf("菜单数据初始化失败: %s", err.Error())
	} else {
		log.Println("菜单数据初始化完成")
	}
}

// ExecSqlFile 执行SQL文件
func ExecSqlFile(db *gorm.DB, filePath string) error {
	sql, err := ioUtil(filePath)
	if err != nil {
		return fmt.Errorf("读取SQL文件失败: %s", err.Error())
	}

	tx := db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	sqlList := strings.Split(sql, ";")
	for i := 0; i < len(sqlList)-1; i++ {
		s := strings.TrimSpace(sqlList[i])
		if s == "" || strings.HasPrefix(s, "--") {
			continue
		}
		s = sqlList[i] + ";"
		s = strings.Replace(s, "\n", "", -1)
		s = strings.TrimSpace(s)
		if s == ";" {
			continue
		}
		if err = tx.Exec(s).Error; err != nil {
			if !strings.Contains(err.Error(), "Query was empty") {
				log.Printf("error sql: %s", s)
				return err
			}
		}
	}
	return nil
}

func ioUtil(filePath string) (string, error) {
	contents, err := os.ReadFile(filePath)
	if err != nil {
		return "", err
	}
	return strings.Replace(string(contents), "\n", "", 1), nil
}
