/*
 * Copyright 2021 PingCAP, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/push"
	"gorm.io/gorm/logger"

	"gorm.io/gorm"

	"gorm.io/driver/mysql"
)

var (
	jobStatus = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: "cronjob",
			Subsystem: "status",
			Name:      "table_checker",
			Help:      "Whether the table is updated as expected.",
		},
		[]string{"tablename"})

	registry = prometheus.NewRegistry()
)

const (
	JobFailed = iota
	JobSuccess
)

func init() {
	registry.MustRegister(jobStatus)
}

func main() {
	var dsn string
	var gateWayUrl string
	var tableName string
	var renewalInMin int

	flag.StringVar(&dsn, "dsn", "root:@(127.0.0.1:4000)/mimir?charset=utf8mb4&parseTime=True&loc=UTC&timeout=30s&readTimeout=30s&writeTimeout=30s", "mysql dsn configuration")
	flag.StringVar(&tableName, "table", "", "table name")
	flag.IntVar(&renewalInMin, "renewal-period", 10, "expect renewal period, the unit is minute")
	flag.StringVar(&gateWayUrl, "push-gateway-url", "", "push gateway address")
	flag.Parse()

	pusher := push.New(gateWayUrl, "cronjob").Gatherer(registry)
	jobStatus.WithLabelValues(tableName).Set(JobFailed)
	defer func() {
		if err := pusher.Add(); err != nil {
			panic(err)
		}
	}()

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{
			SlowThreshold: 200 * time.Millisecond,
			LogLevel:      logger.Info,
			Colorful:      true,
		}),
	})
	if err != nil {
		panic(err)
	}

	var meta StatsMeta
	err = db.Raw(`show STATS_META where Table_name = ?`, tableName).First(&meta).Error
	if err != nil {
		panic(err)
	}

	lastUpdateTime, err := time.Parse(time.RFC3339, string(meta.UpdateTime))
	if err != nil {
		fmt.Printf("the update time is %s\n", string(meta.UpdateTime))
		panic(err)
	}

	if lastUpdateTime.Add(time.Minute * time.Duration(renewalInMin)).After(time.Now()) {
		jobStatus.WithLabelValues(tableName).Set(JobSuccess)
	}
}

type StatsMeta struct {
	UpdateTime []uint8 `gorm:"column:Update_time"`
}
