package at.procon.dip.search.config;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Positive;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;

/**
 * New-runtime generic search configuration.
 *
 * <p>This property tree is intentionally separated from the legacy
 * {@code ted.search.*} settings. NEW-mode search/semantic/lexical code should
 * depend on {@code dip.search.*} only.</p>
 */
@Configuration
@ConfigurationProperties(prefix = "dip.search")
@Data
@Validated
public class DipSearchProperties {

    /** Default page size for search results. */
    @Positive
    private int defaultPageSize = 20;

    /** Maximum allowed page size. */
    @Positive
    private int maxPageSize = 100;

    /** Semantic similarity threshold (normalized score). */
    private double similarityThreshold = 0.7d;

    /** Minimum trigram similarity for fuzzy lexical matches. */
    private double trigramSimilarityThreshold = 0.12d;

    /** Candidate limits per search engine before fusion/collapse. */
    @Positive
    private int fulltextCandidateLimit = 120;

    @Positive
    private int trigramCandidateLimit = 120;

    @Positive
    private int semanticCandidateLimit = 120;

    /** Hybrid fusion weights. */
    private double fulltextWeight = 0.35d;
    private double trigramWeight = 0.20d;
    private double semanticWeight = 0.45d;

    /** Enable chunk representations for long documents. */
    private boolean chunkingEnabled = true;

    /** Target chunk size in characters for CHUNK representations. */
    @Positive
    private int chunkTargetChars = 1800;

    /** Overlap between consecutive chunks in characters. */
    @Min(0)
    private int chunkOverlapChars = 200;

    /** Maximum CHUNK representations generated per document. */
    @Positive
    private int maxChunksPerDocument = 12;

    /** Additional score weight for recency. */
    private double recencyBoostWeight = 0.05d;

    /** Half-life in days used for recency decay. */
    @Positive
    private int recencyHalfLifeDays = 30;

    /** Startup backfill limit for missing DOC lexical vectors. */
    @Positive
    private int startupLexicalBackfillLimit = 500;

    /** Number of hits per engine returned by the debug endpoint. */
    @Positive
    private int debugTopHitsPerEngine = 10;

    private boolean scheduledLexicalBackfillEnabled;

    @Positive
    private int scheduledLexicalBackfillDelayMs = 30000;

    @Positive
    private int scheduledLexicalBackfillBatchSize = 200;
}