package schedule

import (
	"time"
	"tm/internal/notice"
	"tm/pkg/logger"
	"tm/pkg/mongo"

	"github.com/robfig/cron/v3"
)

// CronScheduler handles scheduled tasks for TED operations
type CronScheduler struct {
	cron         *cron.Cron
	mongoManager *mongo.ConnectionManager
	noticeRepo   notice.Repository
	logger       logger.Logger
}

// Logger interface for structured logging
type Logger interface {
	Info(msg string, fields map[string]interface{})
	Error(msg string, fields map[string]interface{})
	Debug(msg string, fields map[string]interface{})
}

type Job struct {
	Name string
	Func func()
	Expr string
}

// NewCronScheduler creates a new cron scheduler instance
func NewCronScheduler(logger logger.Logger, mongoManager *mongo.ConnectionManager, noticeRepo notice.Repository) *CronScheduler {
	// Create cron with timezone support and seconds precision
	c := cron.New(cron.WithLocation(time.UTC), cron.WithSeconds())

	return &CronScheduler{
		cron:         c,
		mongoManager: mongoManager,
		noticeRepo:   noticeRepo,
		logger:       logger,
	}
}

// Start starts the cron scheduler
func (cs *CronScheduler) Start() {
	cs.logger.Info("Starting TED cron scheduler", map[string]interface{}{})
	cs.cron.Start()
}

// Stop stops the cron scheduler gracefully
func (cs *CronScheduler) Stop() {
	cs.logger.Info("Stopping TED cron scheduler", map[string]interface{}{})
	ctx := cs.cron.Stop()
	<-ctx.Done()
}

// ScheduleDailyJob schedules a job to run daily at 10:00 AM UTC
func (cs *CronScheduler) AddJob(job Job) error {
	// Cron expression: "0 0 10 * * *" means:
	// Second: 0
	// Minute: 0
	// Hour: 10 (10 AM)
	// Day of month: * (every day)
	// Month: * (every month)
	// Day of week: * (every day of week)
	_, err := cs.cron.AddFunc(job.Expr, func() {
		now := time.Now().Local()
		cs.logger.Info("Starting daily TED job", map[string]interface{}{
			"job_name":        job.Name,
			"cron_expression": job.Expr,
			"time":            time.Now().Format(time.RFC3339),
		})

		job.Func()

		cs.logger.Info("Completed job successfully", map[string]interface{}{
			"time":            now.Format(time.RFC3339),
			"job_name":        job.Name,
			"cron_expression": job.Expr,
		})
	})

	if err != nil {
		cs.logger.Error("Failed to schedule daily job", map[string]interface{}{
			"error":           err.Error(),
			"job_name":        job.Name,
			"cron_expression": job.Expr,
			"time":            time.Now().Format(time.RFC3339),
		})
		return err
	}

	cs.logger.Info("Daily job scheduled successfully", map[string]interface{}{
		"job_name":        job.Name,
		"cron_expression": job.Expr,
		"time":            time.Now().Format(time.RFC3339),
	})

	return nil
}

// ExampleTEDScrapingJob is an example job function that can be scheduled
func ExampleTEDScrapingJob() {
	// now := time.Now().Local()
	// // Example: Get current date for TED scraping
	// currentDate := time.Now().Format("02/01/2006")
	// currentYear := time.Now().Year()

	// // This is just an example - replace with actual TED scraping logic
	// ojs, err := GetOJS(currentYear, currentDate)
	// if err != nil {
	// 	log.Printf("Error getting OJS: %v", err)
	// 	return
	// }

	// log.Printf("Successfully retrieved OJS: %s for date: %s", ojs, currentDate)

	// Add your actual TED scraping/processing logic here

	// ojs, err := GetOJS(now.Year(), now.Format("02/01/2006"))
	// if err != nil {
	// 	cs.logger.Error("Failed to get OJS", map[string]interface{}{
	// 		"error": err.Error(),
	// 	})
	// 	return
	// }

	// scraper := NewTEDScraper(cs.config, cs.logger, cs.mongoManager, cs.tenderRepo)
	// result, err := scraper.DownloadDailyPackage(context.Background(), ojs)
	// if err != nil {
	// 	cs.logger.Error("Failed to download daily package", map[string]interface{}{
	// 		"error": err.Error(),
	// 	})
	// 	return
	// }

	// cs.logger.Info("Downloaded daily package successfully", map[string]interface{}{
	// 	"result": result,
	// 	"time":   now.Format(time.RFC3339),
	// 	"ojs":    ojs,
	// })
}
