package services

import (
	"context"
	"log/slog"
	"time"

	"gitea.henriburau.de/haw-lan/cod4watcher/models"
)

type Scanner struct {
	p        models.Persistence
	done     chan bool
	interval time.Duration
}

func NewScanner(p models.Persistence, interval time.Duration, done chan bool) (*Scanner, error) {
	return &Scanner{
		p, done, interval,
	}, nil
}

func (s *Scanner) Scan() {
	ticker := time.NewTicker(s.interval)
	for {
		select {
		case <-s.done:
			return
		case <-ticker.C:
			ctx := context.Background()
			slog.Info("starting update")

			captures, err := s.p.GetCaptures(ctx)
			if err != nil {
				slog.Error("cannot get captures", "err", err)
				continue
			}

			for _, capture := range captures {
				if capture.Active {
					err := s.fetchInformation(ctx, capture)
					if err != nil {
						slog.Error("failed to update captures", "err", err)
						continue
					}
				}
			}

		}
	}

}

func (s *Scanner) fetchInformation(ctx context.Context, capture models.Capture) error {
	server, err := models.NewCOD4ServerStatus(capture.Host, capture.Port, time.Second)
	if err != nil {
		return err
	}

	status, err := server.GetServerStatus()
	if err != nil {
		return err
	}

	slog.Info("fetched data", "host", capture.Host, "map", status.MapName)

	recentMap, err := s.p.GetRecentMapScore(ctx, capture.ID)
	if err != nil {
		return err
	}

	if recentMap == nil || recentMap.StartTime.Before(status.MapStartTime) {
		newMap := models.MapScore{
			CaptureID: capture.ID,
			StartTime: status.MapStartTime,
			Map:       status.MapName,
		}

		err := s.p.CreateMapScore(ctx, &newMap)
		if err != nil {
			return err
		}

		recentMap, err = s.p.GetRecentMapScore(ctx, capture.ID)
		if err != nil {
			return err
		}
	}

	var scores []models.Score
	for _, score := range status.Score {
		score.MapScoreID = recentMap.ID
		scores = append(scores, score)
	}

	return s.p.CreateOrUpdateScores(ctx, scores)
}
