package schedule_storage

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"pinned_message/internal/models"
	"regexp"
	"strings"
	"time"
)

type ScheduleStorage struct {
	filepath string
}

func NewScheduleStorage(
	filepath string,
) *ScheduleStorage {
	return &ScheduleStorage{
		filepath: filepath,
	}
}

func (s *ScheduleStorage) SaveSchedule(schedule *models.Schedule) error {
	data, err := json.Marshal(schedule)
	if err != nil {
		return err
	}
	if err := os.WriteFile(s.filepath, data, 0644); err != nil {
		return err
	}
	log.Printf("save schedule to: %s", s.filepath)
	return nil
}

func (s *ScheduleStorage) GetSchedule() (*models.Schedule, error) {
	data, err := os.ReadFile(s.filepath)
	if err != nil {
		return nil, fmt.Errorf("schedule file %s not found", s.filepath)
	}
	log.Printf("load schedule from: %s", s.filepath)
	schedule := &models.Schedule{}
	if err := json.Unmarshal(data, &schedule); err != nil {
		return nil, err
	}
	filterDays := make([]*models.Day, 0, len(schedule.Days))
	for _, day := range schedule.Days {
		if isBeforeToday(day.Date) {
			continue
		}
		for i := range day.Performances {
			if day.Performances[i].TimeCollection == "" || day.Performances[i].TimeCollection == "-" {
				day.Performances[i].TimeCollection = GetStartTime(day.Performances[i].TimeStart)
			}
			filterNumbers := make([]*models.Number, 0, len(day.Performances[i].Numbers))
			for _, number := range day.Performances[i].Numbers {
				name := strings.TrimSpace(number.Name)
				if name == "" || name == "-" {
					continue
				}
				filterNumbers = append(filterNumbers, number)
			}
			day.Performances[i].Numbers = filterNumbers
		}
		filterDays = append(filterDays, day)
	}
	schedule.Days = filterDays
	return schedule, nil
}

func isBeforeToday(targetDate time.Time) bool {
	now := time.Now()
	todayMidnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	targetMidnight := time.Date(targetDate.Year(), targetDate.Month(), targetDate.Day(), 0, 0, 0, 0, targetDate.Location())
	return targetMidnight.Before(todayMidnight)
}

// Компилируем регулярное выражение один раз (для производительности)
// Ищем от 1 до 2 цифр, затем двоеточие, затем ровно 2 цифры
var timeRegex = regexp.MustCompile(`\d{1,2}:\d{2}`)

// GetStartTime извлекает первое найденное время из строки
func GetStartTime(timeRange string) string {
	// FindString возвращает самое первое совпадение в строке
	return timeRegex.FindString(timeRange)
}
