using System.Collections.Generic;
using System.Text.Json.Serialization;
using FinlyticCore.Dtos.TechnicalAnalysis;
namespace FinlyticCore.Dtos.Trading;
///
/// Filter/pagination request for the admin-only evaluation-history RPC channel
/// (MqttTopics.Channels.EngineGetEvaluationHistory), served by FinlyticEngine and exposed to the Web UI
/// via FinlyticBackend/Controllers/AdminEvaluationHistoryController. All filters are optional and are
/// combined with logical AND; means "do not filter on this field".
///
/// Inclusive lower bound on EngineEvaluationSnapshotEntity.EvaluatedAtUtc.
/// Inclusive upper bound on EngineEvaluationSnapshotEntity.EvaluatedAtUtc.
/// Restricts results to a single .
/// Restricts results to a single .
///
/// Case-sensitive substring search against both Isin and Symbol (matches either). Trimmed
/// server-side; blank/whitespace-only values are treated as "no search".
///
/// 1-based page number. Values below 1 are treated as 1 server-side.
///
/// Requested page size. Server-side clamped to at least 1 and at most 200 (see
/// EvaluationHistoryService.MaxPageSize) so a caller cannot force FinlyticEngine to materialize/transmit
/// an unbounded result set in a single response.
///
public record GetEvaluationHistoryRequest(
[property: JsonPropertyName("fromUtc")] System.DateTime? FromUtc = null,
[property: JsonPropertyName("toUtc")] System.DateTime? ToUtc = null,
[property: JsonPropertyName("outcomeFilter")] OutcomeReason? OutcomeFilter = null,
[property: JsonPropertyName("triggerSourceFilter")] TriggerSource? TriggerSourceFilter = null,
[property: JsonPropertyName("isinOrSymbolSearch")] string? IsinOrSymbolSearch = null,
[property: JsonPropertyName("page")] int Page = 1,
[property: JsonPropertyName("pageSize")] int PageSize = 50
);
///
/// One row of the evaluation history: the full, already-persisted record of a single
/// TradeLifecycleService.EvaluateAssetAsync run, mapped 1:1 from EngineEvaluationSnapshotEntity.
/// Every score field is the real, already-computed value - including the honest "0/default" values recorded
/// for the case, never a fabricated placeholder (Rules.md §4).
///
public record EvaluationHistoryEntryDto(
[property: JsonPropertyName("id")] System.Guid Id,
[property: JsonPropertyName("isin")] string Isin,
[property: JsonPropertyName("symbol")] string Symbol,
[property: JsonPropertyName("technicalScore")] decimal TechnicalScore,
[property: JsonPropertyName("sentimentScore")] decimal SentimentScore,
[property: JsonPropertyName("fundamentalScore")] decimal FundamentalScore,
[property: JsonPropertyName("compositeOpportunityScore")] decimal CompositeOpportunityScore,
[property: JsonPropertyName("reliabilityBonus")] decimal ReliabilityBonus,
[property: JsonPropertyName("passedEarningsLockout")] bool PassedEarningsLockout,
[property: JsonPropertyName("daysToNextEarnings")] int? DaysToNextEarnings,
[property: JsonPropertyName("passedDividendGate")] bool PassedDividendGate,
[property: JsonPropertyName("daysToNextExDividend")] int? DaysToNextExDividend,
[property: JsonPropertyName("universeSource")] UniverseSource? UniverseSource,
[property: JsonPropertyName("universeEnteredAtUtc")] System.DateTime? UniverseEnteredAtUtc,
[property: JsonPropertyName("passedSimulationVeto")] bool PassedSimulationVeto,
[property: JsonPropertyName("passedAiValidation")] bool PassedAiValidation,
[property: JsonPropertyName("aiThesisSummary")] string AiThesisSummary,
[property: JsonPropertyName("outcomeReason")] OutcomeReason OutcomeReason,
[property: JsonPropertyName("triggerSource")] TriggerSource TriggerSource,
[property: JsonPropertyName("triggeredByUserId")] System.Guid? TriggeredByUserId,
[property: JsonPropertyName("proposalId")] System.Guid? ProposalId,
[property: JsonPropertyName("evaluatedAtUtc")] System.DateTime EvaluatedAtUtc
);
///
/// Number of evaluation-history rows matching a given filter set that carry a specific .
/// A typed list of these (rather than a Dictionary<OutcomeReason,int>) is used on
/// purely so this DTO round-trips through
/// System.Text.Json (including the AOT source-generated FinlyticJsonSerializerContext) without needing a
/// custom enum-keyed dictionary converter.
///
public record OutcomeReasonCountDto(
[property: JsonPropertyName("outcomeReason")] OutcomeReason OutcomeReason,
[property: JsonPropertyName("count")] int Count
);
///
/// Pre-aggregated headline numbers for the admin evaluation-history tab (e.g. "1.847 Analysen letzte 24h ·
/// 0 Vorschläge seit 14h · Ø-Score 66,7"), computed server-side so the Web UI never has to aggregate the full,
/// unpaginated result set itself. Every field except is scoped to
/// exactly the same filters as the paginated list it accompanies (see
/// ) - only pagination (Page/PageSize) does not apply,
/// since these are totals over the whole filtered set, not just the current page.
///
/// Total number of snapshot rows matching the request's filters (unpaginated).
/// Breakdown of by .
///
/// Average CompositeOpportunityScore across the filtered set; 0 when is 0.
///
///
/// Number of filtered rows whose is
/// - i.e. the same value as the entry
/// in , exposed directly so the UI does not need to search that list.
///
///
/// Timestamp of the most recently created EngineTradeProposalEntity across the ENTIRE proposals table -
/// deliberately NOT scoped to this request's FromUtc/ToUtc filters, because "how long since the
/// last real proposal" is a single wall-clock fact the admin wants regardless of which historical window they
/// are currently browsing. only if no proposal has ever been created.
///
public record EvaluationHistorySummaryDto(
[property: JsonPropertyName("totalEvaluations")] int TotalEvaluations,
[property: JsonPropertyName("countsByOutcome")] List CountsByOutcome,
[property: JsonPropertyName("averageCompositeScore")] decimal AverageCompositeScore,
[property: JsonPropertyName("proposalsCreated")] int ProposalsCreated,
[property: JsonPropertyName("lastProposalCreatedAtUtc")] System.DateTime? LastProposalCreatedAtUtc
);
///
/// Full response for the evaluation-history RPC channel: a page of matching rows, the total match count (for
/// pagination), and a pre-aggregated so the Web UI never needs a second round trip (and a
/// second, potentially-inconsistent set of filters) just to render a header line above the table.
///
public record GetEvaluationHistoryResponse(
[property: JsonPropertyName("totalCount")] int TotalCount,
[property: JsonPropertyName("entries")] List Entries,
[property: JsonPropertyName("summary")] EvaluationHistorySummaryDto Summary
);