package tools

import (
	"fmt"

	"skraak/utils"
)

// PushCertaintyConfig holds the configuration for push-certainty
type PushCertaintyConfig struct {
	Folder   string
	File     string
	Filter   string
	Species  string
	CallType string
	Night    bool
	Day      bool
	Lat      float64
	Lng      float64
	Timezone string
	Reviewer string
}

// PushCertaintyResult holds the result of push-certainty
type PushCertaintyResult struct {
	SegmentsUpdated   int `json:"segments_updated"`
	FilesUpdated      int `json:"files_updated"`
	TimeFilteredCount int `json:"time_filtered_count"`
}

// PushCertainty promotes all certainty=90 segments matching the filter scope to certainty=100.
// Uses identical filtering logic to LoadDataFiles so the scope matches calls classify exactly.
func PushCertainty(config PushCertaintyConfig) (*PushCertaintyResult, error) {
	state, err := LoadDataFiles(ClassifyConfig{
		Folder:    config.Folder,
		File:      config.File,
		Filter:    config.Filter,
		Species:   config.Species,
		CallType:  config.CallType,
		Certainty: 90,
		Sample:    -1,
		Night:     config.Night,
		Day:       config.Day,
		Lat:       config.Lat,
		Lng:       config.Lng,
		Timezone:  config.Timezone,
	})
	if err != nil {
		return nil, err
	}

	var segsUpdated, filesUpdated int
	for i, df := range state.DataFiles {
		changed := false
		for _, seg := range state.FilteredSegs()[i] {
			for _, label := range seg.Labels {
				if labelMatchesPush(label, config.Filter, config.Species, config.CallType) {
					label.Certainty = 100
					changed = true
					segsUpdated++
				}
			}
		}
		if changed {
			df.Meta.Reviewer = config.Reviewer
			if err := df.Write(df.FilePath); err != nil {
				return nil, fmt.Errorf("write %s: %w", df.FilePath, err)
			}
			filesUpdated++
		}
	}

	return &PushCertaintyResult{
		SegmentsUpdated:   segsUpdated,
		FilesUpdated:      filesUpdated,
		TimeFilteredCount: state.TimeFilteredCount,
	}, nil
}

// labelMatchesPush returns true if the label matches the push scope and has certainty=90.
// Certainty is already guaranteed by LoadDataFiles, but we re-check to target only the
// specific label that matched (a segment may carry labels from multiple filters).
func labelMatchesPush(label *utils.Label, filter, species, callType string) bool {
	if filter != "" && label.Filter != filter {
		return false
	}
	if species != "" && label.Species != species {
		return false
	}
	if callType != "" && label.CallType != callType {
		return false
	}
	return label.Certainty == 90
}