package api

import (
	"context"
	"fmt"
	"github.com/jasonlvhit/gocron"
	"go-admin/app/admin/apis/usermanage"
	"go-admin/app/admin/models"
	"go-admin/app/admin/router"
	"go-admin/logger"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"go-admin/app/jobs"
	"go-admin/common/database"
	"go-admin/common/global"
	mycasbin "go-admin/pkg/casbin"
	"go-admin/tools"
	"go-admin/tools/config"
)

var (
	configYml string
	port      string
	mode      string
	StartCmd  = &cobra.Command{
		Use:          "server",
		Short:        "Start API server",
		Example:      "go-admin server -c config/settings.yml",
		SilenceUsage: true,
		PreRun: func(cmd *cobra.Command, args []string) {
			setup()
		},
		RunE: func(cmd *cobra.Command, args []string) error {
			return run()
		},
	}
)

var AppRouters = make([]func(), 0)

func init() {
	StartCmd.PersistentFlags().StringVarP(&configYml, "config", "c", "config/settings.yml", "Start server with provided configuration file")
	StartCmd.PersistentFlags().StringVarP(&port, "port", "p", "8000", "Tcp port server listening on")
	StartCmd.PersistentFlags().StringVarP(&mode, "mode", "m", "dev", "server mode ; eg:dev,test,prod")

	//注册路由 fixme 其他应用的路由，在本目录新建文件放在init方法
	AppRouters = append(AppRouters, router.InitRouter)
}

func setup() {

	//1. 读取配置
	config.Setup(configYml)
	//2. 设置日志
	logger.Setup()
	//3. 初始化数据库链接
	database.Setup(config.DatabaseConfig.Driver)
	//4. 接口访问控制加载
	mycasbin.Setup()

	//usageStr := `starting api server`
	//global.Logger.Info(usageStr)

}

func run() error {
	if viper.GetString("settings.application.mode") == string(tools.ModeProd) {
		gin.SetMode(gin.ReleaseMode)
	}
	engine := global.Cfg.GetEngine()
	if engine == nil {
		engine = gin.New()
	}

	go func() {
		defer func() {
			if err := recover(); err != nil {
				fmt.Println("err:", err)
			}
		}()
		// TODO
		s := gocron.NewScheduler()

		//err := s.Every(2).Minutes().Do(models.GoodsPutDownAway)
		//if err != nil {
		//	fmt.Println("err:", err)
		//}

		// 待支付关
		//err = s.Every(1).Minutes().Do(models.UnPayOrderStatusUpdate)
		//if err != nil {
		//	fmt.Println("err:", err)
		//}

		// 2024-03-11 跟产品确认共享卡功能已隐藏，暂时注释该部分代码
		//// 生效共享卡
		//err = s.Every(1).Day().At("05:00").Do(models.ShareCardProfitEffectCard)
		//if err != nil {
		//	fmt.Println("err:", err)
		//}
		//// 发放积分
		//err = s.Every(1).Day().At("02:00").Do(models.ShareCardProvideVm)
		//if err != nil {
		//	fmt.Println("err:", err)
		//}
		//// 用户积分记录
		//err = s.Every(1).Day().At("03:00").Do(models.ShareCardUserVmRecord)
		//if err != nil {
		//	fmt.Println("err:", err)
		//}

		err := s.Every(1).Minute().Do(models.DeliveryStorePickStatusUpdate)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 用户收回卡绑定卡
		err = s.Every(1).Day().At("00:00").Do(models.ShareCardRetrieveCardSetStockCardCron)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 更新过期用户的当前会员等级-20240308添加
		err = s.Every(1).Day().At("00:05").Do(models.UpdateExpireMemberLevel)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 用户邀请用户报表
		//err = s.Every(1).Day().At("00:00").Do(models.CreateInviteMemberReport)
		err = s.Every(1).Day().At("00:10").Do(models.CreateInviteMemberReport)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 更新过期尊享会员等级-20240829添加
		err = s.Every(1).Day().At("00:15").Do(models.UpdateExpirePrivilegeMemberLevel)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 更新用户过期积分-20240913添加
		err = s.Every(1).Day().At("00:25").Do(models.UpdateExpireUserVm)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 管理端首页
		err = s.Every(1).Day().At("1:00").Do(models.IndexMemberStatistic)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 卡带回收自动取消
		err = s.Every(10).Minutes().Do(models.RecycleCardOrderStateUpdate)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 刷新access_token
		err = s.Every(1).Hour().Do(models.CheckAccessToken)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 每天凌晨00:30更新用户优惠券
		err = s.Every(1).Day().At("00:30").Do(models.UpdateUserCoupon)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 每天凌晨00:45更新营销管理优惠券发放状态
		err = s.Every(1).Day().At("00:45").Do(models.UpdateErpCouponState)
		if err != nil {
			fmt.Println("err:", err)
		}

		// 每天01:00检查公告是否过期
		err = s.Every(1).Day().At("01:00").Do(models.CheckExpiredSystemMessages)
		if err != nil {
			fmt.Println("err:", err)
		}

		if config.ApplicationConfig.Mode != "dev" {
			// 给会员即将过期且有卡带未归还的用户发短信提醒续费
			err = s.Every(1).Day().At("10:30").Do(models.MemberExpirationReminder)
			if err != nil {
				fmt.Println("err:", err)
			}

			// 给会员过期且有卡带未归还的用户发短信提醒还卡
			err = s.Every(1).Day().At("12:01").Do(models.ExpireMemberSMSSend)
			if err != nil {
				fmt.Println("err:", err)
			}

			// 用户会员到期前一个月发短信提醒用户领取优惠券续费
			err = s.Every(1).Day().At("19:00").Do(models.SendMessageMemberRenewal)
			if err != nil {
				fmt.Println("err:", err)
			}

			// 每天上午10:00退前一天的保证金
			err = s.Every(1).Day().At("10:00").Do(usermanage.AutoDepositRefund)
			if err != nil {
				fmt.Println("err:", err)
			}

			// 检测小程序商城有无待发货订单
			err = s.Every(1).Day().At("09:00").Do(models.CheckOnDeliverMall)
			if err != nil {
				fmt.Println("err:", err)
			}

			// 检测小程序商城有无待发货订单
			err = s.Every(1).Day().At("14:00").Do(models.CheckOnDeliverMall)
			if err != nil {
				fmt.Println("err:", err)
			}
		}

		<-s.Start()
	}()

	for _, f := range AppRouters {
		f()
	}

	srv := &http.Server{
		Addr:    config.ApplicationConfig.Host + ":" + config.ApplicationConfig.Port,
		Handler: global.Cfg.GetEngine(),
	}
	go func() {
		jobs.InitJob()
		jobs.Setup()

	}()

	go func() {
		// 服务连接
		if config.SslConfig.Enable {
			if err := srv.ListenAndServeTLS(config.SslConfig.Pem, config.SslConfig.KeyStr); err != nil && err != http.ErrServerClosed {
				logger.Fatal("listen: ", err)
			}
		} else {
			if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
				logger.Fatal("listen: ", err)
			}
		}
	}()
	content, _ := ioutil.ReadFile("./static/go-admin.txt")
	fmt.Println(tools.Red(string(content)))
	tip()
	fmt.Println(tools.Green("Server run at:"))
	fmt.Printf("-  Local:   http://localhost:%s/ \r\n", config.ApplicationConfig.Port)
	fmt.Printf("-  Network: http://%s:%s/ \r\n", tools.GetLocaHonst(), config.ApplicationConfig.Port)
	fmt.Println(tools.Green("Swagger run at:"))
	fmt.Printf("-  Local:   http://localhost:%s/swagger/index.html \r\n", config.ApplicationConfig.Port)
	fmt.Printf("-  Network: http://%s:%s/swagger/index.html \r\n", tools.GetLocaHonst(), config.ApplicationConfig.Port)
	fmt.Printf("%s Enter Control + C Shutdown Server \r\n", tools.GetCurrentTimeStr())
	// 等待中断信号以优雅地关闭服务器（设置 5 秒的超时时间）
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	fmt.Printf("%s Shutdown Server ... \r\n", tools.GetCurrentTimeStr())

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		logger.Fatal("Server Shutdown:", err)
	}
	logger.Println("Server exiting")

	return nil
}

func tip() {
	usageStr := `欢迎使用 ` + tools.Green(`go-admin `+global.Version) + ` 可以使用 ` + tools.Red(`-h`) + ` 查看命令`
	fmt.Printf("%s \n\n", usageStr)
}
