using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using PolyTraderSharp.Models;

namespace PolyTraderSharp
{
    /// <summary>
    /// In-Memory Hot-Path State des Copytrading-Moduls.
    /// Enthält den copytrading-spezifischen Zustand: kopierte Master-Trader, deren
    /// Positions-Tracking, Analytics-Cache, Copy-Trade-Zähler und Order-Timestamps.
    /// Der modulübergreifende Zustand (Accounts, MarketCache, globale Schalter) liegt
    /// im Core-<see cref="TradingState"/>.
    /// </summary>
    public class CopyTradingState
    {
        // Copytrading-Risk-Regel: mindestens 6 Shares pro Order erzwingen.
        public bool SixSharesMinimum { get; set; } = true;

        // Auto-Pause-Kill-Switch (Phase 3.3), global. Pro-Master-Schalter: TrackedTrader.AutoPauseEnabled.
        public int AutoPauseMinTrades { get; set; } = 10;      // Mindest-Stichprobe vor Pause
        public decimal AutoPauseDrawdownUsd { get; set; } = 10m; // Copy-PnL (30T) darunter -> Pause

        // Kopierte Master-Trader (TraderId -> TrackedTrader)
        public ConcurrentDictionary<int, TrackedTrader> Traders { get; } = new();

        // Copytrading-Detail-Einstellungen je Account (AccountId -> Settings).
        public ConcurrentDictionary<int, CopyTradingAccountSettings> AccountSettings { get; } = new();

        /// <summary>
        /// Liefert die Copytrading-Einstellungen für einen Account. Legt bei Bedarf einen
        /// Default-Eintrag an, damit der Hot-Path nie null erhält.
        /// </summary>
        public CopyTradingAccountSettings GetAccountSettings(int accountId)
        {
            return AccountSettings.GetOrAdd(accountId, id => new CopyTradingAccountSettings { AccountId = id });
        }

        private int _totalCopyTrades = 0;
        public int TotalCopyTrades
        {
            get => _totalCopyTrades;
            set => _totalCopyTrades = value;
        }

        public int GetNextTradeId()
        {
            return Interlocked.Increment(ref _totalCopyTrades);
        }

        // Analytics Cache (AccountId -> List<TraderAnalyticsResult>)
        public ConcurrentDictionary<int, List<TraderAnalyticsResult>> TraderAnalyticsCache { get; } = new();

        // Tracks when live orders were placed for stale order cleanup.
        // Key: "AccountId_TokenId", Value: (PlacedAt, SourceTraderId, Side "BUY"/"SELL").
        // Side ermöglicht, dass die 20s-Blockade im SELL-Pfad nur greift, wenn zuletzt ein
        // SELL platziert wurde (ein vorheriger BUY blockiert einen legitimen SELL nicht mehr).
        public ConcurrentDictionary<string, (DateTime PlacedAt, int SourceTraderId, string Side)> PendingOrderTimestamps { get; } = new();

        // Master Trader Position Tracker (Key: "{TraderId}_{TokenId}", Value: (Shares, LastUpdated))
        // Entscheidet, ob ein SELL-Signal ein Teilverkauf (ignorieren) oder ein Voll-Exit (kopieren) ist.
        public ConcurrentDictionary<string, (decimal Shares, DateTime LastUpdated)> MasterTraderPositions { get; } = new();

        // Aktive SELL-Eskalationsleitern (Phase 0.1). Key: "{AccountId}_{TokenId}".
        // Transient (nach App-Neustart leer) – siehe Position.ExitPending.
        public ConcurrentDictionary<string, ExitLadderState> ExitLadders { get; } = new();
    }

    /// <summary>
    /// Laufzeit-Zustand einer SELL-Eskalationsleiter (Phase 0.1): schrittweises Absenken des
    /// Limit-Preises vom Master-Exit bis zum Floor, verwaltet vom SellLadderService.
    /// </summary>
    public sealed class ExitLadderState
    {
        public int AccountId { get; set; }
        public string TokenId { get; set; } = string.Empty;
        public int SourceTraderId { get; set; }

        /// <summary>Korrelation zum auslösenden Signal (leer bei Profit-Target-Exits).</summary>
        public string SignalId { get; set; } = string.Empty;
        public string MarketQuestion { get; set; } = string.Empty;

        public decimal ReferencePrice { get; set; }   // Master-Exit-Preis
        public decimal CurrentLimit { get; set; }      // aktuell platziertes Limit
        public decimal Floor { get; set; }             // absolute Untergrenze
        public bool IsHf { get; set; }

        public int Attempt { get; set; } = 1;
        public DateTime LastActionAt { get; set; } = DateTime.UtcNow;
        public bool FloorNotified { get; set; }
    }
}
