using Predictalytics.Domain.Enums;
using System.ComponentModel.DataAnnotations.Schema;

namespace Predictalytics.Domain.Entities;

/// <summary>
/// Represents a single trade executed by a trader on a prediction market.
/// </summary>
public class Trade
{
    public long Id { get; set; }

    /// <summary>Foreign key to the trader who made this trade.</summary>
    public int TraderId { get; set; }

    /// <summary>Platform where the trade occurred.</summary>
    public PlatformType Platform { get; set; }

    /// <summary>
    /// Platform-specific trade ID for deduplication.
    /// Format: "{txHash}_{assetId}_{side}" (max ~143 chars for new trades).
    /// Legacy trades may include wallet address as 2nd segment.
    /// </summary>
    public string PlatformTradeId { get; set; } = string.Empty;

    /// <summary>
    /// Platform-specific market identifier string (conditionId on Polymarket, address on Limitless).
    /// Kept as VARCHAR(66) for cross-referencing during import and reconciliation.
    /// After full linking, prefer DbMarketId.
    /// </summary>
    public string MarketId { get; set; } = string.Empty;

    /// <summary>
    /// Foreign key to the internal Markets table. Populated during import when the market is known.
    /// Null for trades whose market has not yet been synced.
    /// </summary>
    public int? DbMarketId { get; set; }

    /// <summary>
    /// Platform-specific token/asset ID (clobTokenId on Polymarket). Links to MarketOutcome.TokenId.
    /// Kept as VARCHAR(66) until MarketOutcomeId is resolved.
    /// </summary>
    public string AssetId { get; set; } = string.Empty;

    /// <summary>Foreign key to the resolved MarketOutcome (nullable until resolved via market sync).</summary>
    public int? MarketOutcomeId { get; set; }

    /// <summary>The outcome the trader bet on (e.g. "Yes", "No").</summary>
    public string Outcome { get; set; } = string.Empty;

    /// <summary>Buy or Sell.</summary>
    public TradeSide Side { get; set; }

    /// <summary>Price per share at execution (0.00 to 1.00 on Polymarket).</summary>
    public decimal Price { get; set; }

    /// <summary>Number of shares/tokens traded.</summary>
    public decimal Size { get; set; }

    /// <summary>Total notional value in USD.</summary>
    public decimal Amount { get; set; }

    /// <summary>When the trade was executed on the platform.</summary>
    public DateTime ExecutedAt { get; set; }

    /// <summary>Transaction hash (for blockchain-based platforms).</summary>
    public string? TransactionHash { get; set; }

    /// <summary>USDC size of the trade (raw currency size traded).</summary>
    [Column(TypeName = "decimal(18,6)")]
    public decimal? UsdcSize { get; set; }

    /// <summary>Outcome index traded.</summary>
    public int? OutcomeIndex { get; set; }

    // ── Context Enrichment (AI Strategy Detection) ───────────
    
    /// <summary>Market price 1 minute before trade execution.</summary>
    [Column(TypeName = "decimal(18,4)")]
    public decimal? PreTradePrice1m { get; set; }
    
    /// <summary>Market price 1 minute after trade execution.</summary>
    [Column(TypeName = "decimal(18,4)")]
    public decimal? PostTradePrice1m { get; set; }
    
    /// <summary>Indicates if high-res price context was fetched.</summary>
    public bool IsContextEnriched { get; set; }

    /// <summary>
    /// For aggregated trades (compacted history or HF trader hourly bucket), this stores 
    /// the number of original trades that were grouped into this single row. Null means 1.
    /// </summary>
    public int? AggregatedCount { get; set; }

    // ── Transient (not persisted) ──────────────────────────────────────────

    /// <summary>
    /// Wallet address of the trader, set by the provider during data ingestion.
    /// NOT stored in the database — used transiently for trader discovery in MarketHistoryWorker.
    /// </summary>
    [NotMapped]
    public string? TransientWallet { get; set; }
    
    /// <summary>
    /// Transient reference to the trader's display name from the platform, used to opportunistically 
    /// update the local name if it's currently a placeholder or empty.
    /// </summary>
    [NotMapped] 
    public string? TransientDisplayName { get; set; }

    // ── Navigation ────────────────────────────────────────────────────────
    public Trader Trader { get; set; } = null!;
    public MarketOutcome? MarketOutcome { get; set; }

    /// <summary>Analytics context containing high-resolution price data and slippage (if collected).</summary>
    public TradeContext? Context { get; set; }

    public Market? DbMarket { get; set; }
}
