using System;
using System.Collections.Generic;
using System.Linq;
using PolyTrader.Core.Streaming;
using PolyTraderSharp.Models;

namespace PolyTrader.Modules.CopyTrading.Logic
{
    /// <summary>
    /// Reine Logik zum Aufbau des Alchemy-Blockchain-Abos für die getrackten Master-Wallets.
    /// Aus <c>AlchemyWebsocketService</c> herausgezogen, damit das Filter-Batching und das
    /// Adress-Padding vollständig testbar sind (falsche Filter = verpasste Master-Trades).
    /// Verhalten 1:1 aus dem Listener übernommen.
    /// </summary>
    public static class BlockchainSubscription
    {
        /// <summary>Polymarket CTF (ConditionalTokens) Contract – Quelle der Transfer-Events.</summary>
        public const string CtfContractAddress = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";
        public const string TransferSingleTopic = "0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62";
        public const string TransferBatchTopic = "0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7ce";

        /// <summary>Alchemy begrenzt Topic-Arrays auf ~3–4 Einträge → Batchgröße 3.</summary>
        public const int BatchSize = 3;

        /// <summary>
        /// Wandelt eine Wallet-Adresse in die 32-Byte-Topic-Form (lowercase, ohne 0x, links mit
        /// Nullen auf 64 Hex-Zeichen aufgefüllt, mit 0x-Präfix). Nötig, weil Log-Topics die
        /// Adresse in voller Wortbreite enthalten.
        /// </summary>
        public static string PadAddress(string address)
        {
            string stripped = address.Replace("0x", "", StringComparison.OrdinalIgnoreCase).ToLowerInvariant();
            return "0x" + stripped.PadLeft(64, '0');
        }

        /// <summary>
        /// Baut das Abo: pro 3er-Chunk der gepaddeten Master-Adressen je EIN Filter für Käufe
        /// (Master ist Empfänger → Topic3) und EIN Filter für Verkäufe (Master ist Sender → Topic2),
        /// beide auf dem CTF-Contract mit den Transfer-Topics.
        /// </summary>
        public static BlockchainWssSubscription Build(IEnumerable<TrackedTrader> activeTraders)
        {
            var subscription = new BlockchainWssSubscription();
            var paddedAddresses = activeTraders.Select(t => PadAddress(t.WalletAddress)).ToList();
            var topic0 = new List<string> { TransferSingleTopic, TransferBatchTopic };

            for (int i = 0; i < paddedAddresses.Count; i += BatchSize)
            {
                var chunk = paddedAddresses.Skip(i).Take(BatchSize).ToList();
                // Buys: Master-Trader ist Empfänger (Topic 3)
                subscription.Filters.Add(new LogSubscriptionFilter { Address = CtfContractAddress, Topic0 = topic0, Topic3 = chunk });
                // Sells: Master-Trader ist Sender (Topic 2)
                subscription.Filters.Add(new LogSubscriptionFilter { Address = CtfContractAddress, Topic0 = topic0, Topic2 = chunk });
            }
            return subscription;
        }
    }
}
