using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using PolyTrader.Core.Persistence;
using PolyTrader.Modules.ResolutionFarming.Logic;
using PolyTrader.Modules.ResolutionFarming.Models;
using PolyTrader.Modules.ResolutionFarming.Persistence;
using PolyTraderSharp;
using PolyTraderSharp.Models;
using PolyTraderSharp.Services;

namespace PolyTrader.Modules.ResolutionFarming.Services
{
    /// <summary>
    /// Prüft offene Farming-Positionen gegen Marktauflösung und schließt aufgelöste (Phase RF-2/3):
    /// realisierten PnL buchen (rein via <see cref="FarmingResolution"/>), rf_position löschen,
    /// Gesamt-PnL fortschreiben und generischen Core-Trade-Log schreiben (Dashboard). Der
    /// Auflösungsstatus kommt aus einer <see cref="IMarketResolutionSource"/> (Live: Data-API).
    /// On-Chain-Redeem der Gewinner-Shares ist eine spätere, clob.md-kritische Phase (Zielland).
    /// </summary>
    public class FarmingResolutionMonitorService : BackgroundService
    {
        private static readonly TimeSpan Interval = TimeSpan.FromMinutes(10);

        private readonly TradingState _state;
        private readonly IRfPositionRepository _positionRepo;
        private readonly IRfClosedTradeRepository _closedRepo;
        private readonly IMarketResolutionSource _resolution;
        private readonly ITradeLogRepository _coreLog;
        private readonly TerminalLogger _logger;
        private readonly IDecisionJournal _journal;

        public FarmingResolutionMonitorService(
            TradingState state, IRfPositionRepository positionRepo, IRfClosedTradeRepository closedRepo,
            IMarketResolutionSource resolution, ITradeLogRepository coreLog, TerminalLogger logger,
            IDecisionJournal journal)
        {
            _state = state;
            _positionRepo = positionRepo;
            _closedRepo = closedRepo;
            _resolution = resolution;
            _coreLog = coreLog;
            _logger = logger;
            _journal = journal;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await Task.Delay(TimeSpan.FromSeconds(60), stoppingToken);
            _logger.Info("ResolutionFarming-Monitor gestartet.");

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    var closed = await CheckAndCloseAsync(stoppingToken);
                    if (closed.Count > 0)
                        _logger.Trade($"🏁 [RF-Monitor] {closed.Count} Position(en) bei Auflösung geschlossen.");
                }
                catch (OperationCanceledException) { break; }
                catch (Exception ex) { _logger.Error($"RF-Monitor Fehler: {ex.Message}"); }

                await Task.Delay(Interval, stoppingToken);
            }
        }

        /// <summary>Testbarer Kern: prüft alle offenen Positionen und schließt aufgelöste. Liefert die geschlossenen Trades.</summary>
        internal async Task<List<RfClosedTrade>> CheckAndCloseAsync(CancellationToken ct)
        {
            var result = new List<RfClosedTrade>();
            foreach (var pos in _positionRepo.GetAllOpen())
            {
                if (ct.IsCancellationRequested) break;

                var (isClosed, isWinner) = await _resolution.CheckAsync(pos.MarketSlug, pos.TokenId, ct);
                if (!isClosed) continue;

                var trade = FarmingResolution.BuildClosedTrade(pos, isWinner, DateTime.UtcNow);
                _closedRepo.Insert(trade);
                _positionRepo.Delete(pos.AccountId, pos.TokenId);
                _state.GlobalPnl += trade.RealizedPnl;

                // Dual-Write: generischer, modulübergreifender Core-Trade-Log (Dashboard).
                _coreLog.Insert(new TradeRecord
                {
                    ModuleName = "ResolutionFarming",
                    AccountId = trade.AccountId,
                    IsDemo = trade.IsDemo,
                    TokenId = trade.TokenId,
                    MarketQuestion = trade.MarketQuestion,
                    Outcome = trade.Outcome,
                    Side = "BUY",
                    EntryPrice = trade.EntryPrice,
                    ExitPrice = trade.ExitPrice,
                    Size = trade.Size,
                    RealizedPnl = trade.RealizedPnl,
                    PnlPercent = trade.PnlPercent,
                    OpenedAt = trade.OpenedAt,
                    ClosedAt = trade.ClosedAt,
                    ExitReason = trade.ExitReason
                });

                _logger.Trade($"🏆 [RF] {pos.MarketQuestion} aufgelöst ({(isWinner ? "Gewinner" : "Verlierer")}) – PnL {trade.RealizedPnl:F2} USDC.");
                _journal.Write(new DecisionRecord
                {
                    SignalId = Guid.NewGuid().ToString("N"),
                    ModuleName = "ResolutionFarming",
                    AccountId = pos.AccountId,
                    IsDemo = pos.IsDemo,
                    TokenId = pos.TokenId,
                    MarketSlug = pos.MarketSlug,
                    MarketQuestion = pos.MarketQuestion,
                    Side = "SELL",
                    SignalPrice = trade.ExitPrice,
                    Decision = TradeDecision.Executed,
                    Reason = DecisionReason.SystemResolutionClose,
                    Message = $"RF-Resolution ({(isWinner ? "Gewinner" : "Verlierer")}), PnL {trade.RealizedPnl:F2}",
                    ContextJson = System.Text.Json.JsonSerializer.Serialize(new { isWinner, realizedPnl = trade.RealizedPnl, size = pos.Size })
                });
                result.Add(trade);
            }
            return result;
        }
    }
}
