using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using PolyTrader.Core.Persistence;
using PolyTraderSharp;
using PolyTraderSharp.Models;

namespace PolyTraderSharp.Services
{
    /// <summary>
    /// K2 (Fable-Fixes) – Neustart-Reconciliation. Ruhende GTC-Orders der SELL-Eskalationsleiter
    /// (und ruhende MakerEntry-BUYs) überleben einen Neustart auf dem CLOB, der zugehörige
    /// Verwaltungszustand (ExitLadders, Position.ExitPending, PendingOrderTimestamps) ist aber
    /// bewusst transient. Ohne Bereinigung liefe die Engine gegen Waisen-Orders (Doppel-Leiter auf
    /// dieselben Shares, Fehlerkaskaden).
    ///
    /// Deterministische Lösung: Beim Start je LIVE-Account alle offenen CLOB-Orders pauschal canceln.
    /// Danach entscheidet die Engine sauber neu (Master-SELL/Profit-Target starten frische Leitern).
    /// Bewusst blockierend als IHostedService, registriert VOR TraderMonitor/Engine, damit die
    /// Bereinigung abgeschlossen ist, bevor das erste Signal verarbeitet wird. Pro Account
    /// fehlertolerant – ein Account-Fehler darf den Start nicht verhindern.
    /// </summary>
    public class StartupOrderReconciliationService : IHostedService
    {
        private readonly TradingState _state;
        private readonly IClobClient _clob;
        private readonly TerminalLogger _logger;
        private readonly IOrderEventLog _orderEvents;

        public StartupOrderReconciliationService(TradingState state, IClobClient clob, TerminalLogger logger, IOrderEventLog orderEvents)
        {
            _state = state;
            _clob = clob;
            _logger = logger;
            _orderEvents = orderEvents;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            int accountsProcessed = 0, ordersCancelled = 0;

            foreach (var acc in _state.Accounts.Values)
            {
                if (cancellationToken.IsCancellationRequested) break;

                // Nur echte Live-Accounts mit CLOB-Credentials haben ruhende Orders.
                if (acc.IsDemo) continue;
                if (string.IsNullOrEmpty(acc.ApiKey) || string.IsNullOrEmpty(acc.ApiSecret)
                    || string.IsNullOrEmpty(acc.ApiPassphrase) || string.IsNullOrEmpty(acc.PrivateKey)) continue;

                try
                {
                    var openOrders = await _clob.GetOpenOrdersAsync(acc);   // ohne assetId = ALLE offenen Orders
                    if (openOrders.Count == 0)
                    {
                        _logger.Info($"🧹 [Startup-Reconciliation] {acc.Name}: keine offenen Orders.");
                        accountsProcessed++;
                        continue;
                    }

                    _logger.Warning($"🧹 [Startup-Reconciliation] {acc.Name}: {openOrders.Count} verwaiste Order(s) vom vorherigen Lauf – storniere alle.");
                    foreach (var order in openOrders)
                    {
                        if (cancellationToken.IsCancellationRequested) break;
                        try
                        {
                            bool ok = await _clob.CancelOrderAsync(acc, order.Id);
                            if (ok) ordersCancelled++;
                            else _logger.Warning($"⚠️ [Startup-Reconciliation] {acc.Name}: Order {order.Id} konnte nicht storniert werden.");
                            _orderEvents.Write(new OrderEventRecord
                            {
                                ModuleName = "CopyTrading",
                                AccountId = acc.AccountId,
                                EventType = OrderEventType.StartupReconcileCancel,
                                Side = order.Side,
                                Price = order.Price,
                                Response = ok ? "OK" : "Cancel fehlgeschlagen",
                                DetailsJson = $"{{\"orderId\":\"{order.Id}\"}}"
                            });
                        }
                        catch (Exception ex)
                        {
                            _logger.Error($"[Startup-Reconciliation] {acc.Name}: Cancel {order.Id} fehlgeschlagen: {ex.Message}");
                        }
                    }
                    accountsProcessed++;
                }
                catch (Exception ex)
                {
                    _logger.Error($"[Startup-Reconciliation] {acc.Name}: Abruf offener Orders fehlgeschlagen: {ex.Message}");
                }
            }

            _logger.Info($"🧹 [Startup-Reconciliation] Abgeschlossen: {accountsProcessed} Live-Account(s) geprüft, {ordersCancelled} Order(s) storniert. Engine entscheidet jetzt sauber neu.");
        }

        public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
}
