package logger

import (
	"fmt"
	"path/filepath"
	"sync"
	"time"
)

type RotatingLogger struct {
	dataLogger      *DataLogger
	currentHour     int
	baseDir         string
	mu              sync.Mutex
	eventLogger     *EventLogger
	checkInterval   time.Duration
}

func NewRotatingLogger(eventLogger *EventLogger, checkInterval time.Duration) (*RotatingLogger, error) {
	// Получаем директорию для бинарных данных
	dataDir, err := GetDataLogsDir()
	if err != nil {
		return nil, err
	}

	// Интервал проверки по умолчанию
	if checkInterval == 0 {
		checkInterval = 1 * time.Minute
	}

	r := &RotatingLogger{
		baseDir:       dataDir,
		eventLogger:   eventLogger,
		checkInterval: checkInterval,
	}

	if err := r.rotate(); err != nil {
		return nil, err
	}

	go r.rotationLoop()
	return r, nil
}

func (r *RotatingLogger) getFilename() string {
	now := time.Now()
	return filepath.Join(r.baseDir, fmt.Sprintf("gpio-%04d-%02d-%02d-%02d.bin",
		now.Year(), now.Month(), now.Day(), now.Hour()))
}

func (r *RotatingLogger) rotate() error {
	r.mu.Lock()
	defer r.mu.Unlock()

	now := time.Now()
	newHour := now.Hour()

	// Если уже правильный час и логгер существует - ок
	if r.dataLogger != nil && r.currentHour == newHour {
		return nil
	}

	// Закрываем старый
	if r.dataLogger != nil {
		r.dataLogger.Close()
	}

	// Открываем новый
	filename := r.getFilename()
	dataLogger, err := NewDataLogger(filename)
	if err != nil {
		if r.eventLogger != nil {
			r.eventLogger.Event("ПЛАНОВАЯ_РОТАЦИЯ_НЕУДАЧНА")
		}
		return err
	}

	r.dataLogger = dataLogger
	r.currentHour = newHour
	if r.eventLogger != nil {
		r.eventLogger.Event("ПЛАНОВАЯ_РОТАЦИЯ")
	}
	return nil
}

func (r *RotatingLogger) Write(s Sample) {
	r.mu.Lock()
	logger := r.dataLogger
	r.mu.Unlock()

	if logger != nil {
		logger.Write(s)
	}
}

func (r *RotatingLogger) rotationLoop() {
	ticker := time.NewTicker(r.checkInterval)
	defer ticker.Stop()

	for range ticker.C {
		r.rotate()
	}
}

func (r *RotatingLogger) Close() error {
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.dataLogger != nil {
		return r.dataLogger.Close()
	}
	return nil
}