package main

import (
	"context"
	"flag"
	"log"
	"time"

	"github.com/tidbcloud/metering/pkg/common/config"
	"github.com/tidbcloud/metering/pkg/httpapi"
	"github.com/tidbcloud/metering/pkg/nextgentasks"
	"github.com/tidbcloud/metering/pkg/schedule"
	"go.uber.org/zap"
)

var serviceconfigpath string

func main() {
	// Load config
	flag.StringVar(&serviceconfigpath, "serviceconfig", "./configs/serviceconfig.yaml", "service info.")
	flag.Parse()

	serviceConfig, err := config.LoadServiceConfig(serviceconfigpath)
	if err != nil {
		log.Panicf("load service config failed. %s", err.Error())
	}

	var logger *zap.Logger
	if serviceConfig.LogLevel == "debug" {
		logger, _ = zap.NewDevelopment()
	} else {
		logger, _ = zap.NewProduction()
	}
	logger.Info("serviceconfig", zap.Any("serviceconfig", serviceConfig))

	// Validate NextGen config
	if serviceConfig.NextGenMeteringConfig == nil {
		log.Panicf("NextGenMeteringConfig is required but not found in config")
	}

	// Initialize global Delta Lake lock to prevent concurrent access between tasks
	nextgentasks.InitGlobalDeltaLakeLock(logger)

	scheduler := schedule.NewScheduler()

	// Setup NextGen metering task
	nextGenTask, err := nextgentasks.NewNextGenTask(&serviceConfig, logger)
	if err != nil {
		logger.Fatal("new NextGen metering task failed", zap.Error(err))
	}

	// Get task interval from config, default to 1 minute
	taskInterval := serviceConfig.NextGenMeteringConfig.TaskInterval
	if taskInterval == 0 {
		taskInterval = 1 // Default 1 minute
	}

	scheduler.AddJob(logger, time.Duration(taskInterval)*time.Minute, nextGenTask)
	go scheduler.Run()

	// Setup NextGen reporter task if enabled
	if serviceConfig.NextGenMeteringConfig.EnableReporter {
		nextGenReporterTask, err := nextgentasks.NewNextGenRepoterTask(&serviceConfig, logger)
		if err != nil {
			logger.Fatal("new NextGen reporter task failed", zap.Error(err))
		}

		// Get reporter interval from config, default to 60 minutes
		reporterInterval := serviceConfig.NextGenMeteringConfig.ReporterInterval
		if reporterInterval == 0 {
			reporterInterval = 60 // Default 60 minutes
		}

		// Create a separate scheduler for reporter task to avoid conflict with metering task
		reporterScheduler := schedule.NewScheduler()
		reporterScheduler.AddJob(logger, time.Duration(reporterInterval)*time.Minute, nextGenReporterTask)
		go reporterScheduler.Run()

		logger.Info("NextGen reporter task enabled",
			zap.Int("reporter_interval_minutes", reporterInterval))
	} else {
		logger.Info("NextGen reporter task is disabled")
	}

	// Setup NextGen maintenance task if enabled
	if maintCfg := serviceConfig.NextGenMeteringConfig.MaintenanceConfig; maintCfg != nil && maintCfg.Enable {
		nextGenMaintenanceTask, err := nextgentasks.NewNextGenMaintenanceTask(&serviceConfig, logger)
		if err != nil {
			logger.Fatal("new NextGen maintenance task failed", zap.Error(err))
		}

		maintenanceInterval := maintCfg.IntervalMinutes
		if maintenanceInterval <= 0 {
			maintenanceInterval = 24 * 60 // Default once per day
		}

		maintenanceScheduler := schedule.NewScheduler()
		maintenanceScheduler.AddJob(logger, time.Duration(maintenanceInterval)*time.Minute, nextGenMaintenanceTask)
		go maintenanceScheduler.Run()

		logger.Info("NextGen maintenance task enabled",
			zap.Int("maintenance_interval_minutes", maintenanceInterval),
			zap.Bool("delete_enabled", maintCfg.EnableDelete),
			zap.Bool("vacuum_enabled", maintCfg.EnableVacuum))
	} else {
		logger.Info("NextGen maintenance task is disabled")
	}

	// Setup HTTP server
	logger.Info("starting NextGen metering service",
		zap.String("vendor", serviceConfig.Vendor),
		zap.Int("task_interval_minutes", taskInterval),
		zap.Int("delay_minutes", serviceConfig.NextGenMeteringConfig.DelayMinutes),
		zap.String("delta_table_path", serviceConfig.NextGenMeteringConfig.DeltaTablePath),
		zap.Bool("enable_pprof", serviceConfig.EnablePprof))

	httpapi.StartService(context.Background(), serviceConfig)
}
