using System.Text.Json;
using System.Text.Json.Serialization;

namespace Predictalytics.Infrastructure.Providers.Polymarket;

/// <summary>
/// Converter that handles JSON values that may be either a number or a string.
/// Polymarket API is inconsistent — some fields are numbers in one endpoint and strings in another.
/// </summary>
public class FlexibleDoubleConverter : JsonConverter<double>
{
    public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return reader.TokenType switch
        {
            JsonTokenType.Number => reader.GetDouble(),
            JsonTokenType.String => double.TryParse(reader.GetString(), System.Globalization.NumberStyles.Any,
                System.Globalization.CultureInfo.InvariantCulture, out var v) ? v : 0,
            JsonTokenType.Null => 0,
            _ => 0
        };
    }

    public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options)
        => writer.WriteNumberValue(value);
}

public class FlexibleLongConverter : JsonConverter<long>
{
    public override long Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return reader.TokenType switch
        {
            JsonTokenType.Number => reader.GetInt64(),
            JsonTokenType.String => long.TryParse(reader.GetString(), out var v) ? v : 0,
            _ => 0
        };
    }

    public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options)
        => writer.WriteNumberValue(value);
}

// ═══════════════════════════════════════════════════════
//  Polymarket Data API response models
// ═══════════════════════════════════════════════════════

public class PolymarketTradeResponse
{
    [JsonPropertyName("conditionId")] public string ConditionId { get; set; } = "";
    [JsonPropertyName("asset")] public string Asset { get; set; } = "";
    [JsonPropertyName("side")] public string Side { get; set; } = "";
    [JsonPropertyName("action")] public string Action { get; set; } = "";
    [JsonPropertyName("type")] public string Type { get; set; } = "";
    [JsonPropertyName("user")] public string? User { get; set; }
    [JsonPropertyName("proxyWallet")] public string? ProxyWallet { get; set; }

    [JsonPropertyName("size")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Size { get; set; }

    [JsonPropertyName("usdcSize")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double UsdcSize { get; set; }

    [JsonPropertyName("price")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Price { get; set; }

    [JsonPropertyName("outcomeIndex")]
    public int? OutcomeIndex { get; set; }

    [JsonPropertyName("name")] public string? Name { get; set; }
    [JsonPropertyName("pseudonym")] public string? Pseudonym { get; set; }

    [JsonPropertyName("outcome")] public string Outcome { get; set; } = "";

    [JsonPropertyName("timestamp")]
    [JsonConverter(typeof(FlexibleLongConverter))]
    public long Timestamp { get; set; }

    [JsonPropertyName("transactionHash")] public string? TransactionHash { get; set; }
}

public class PolymarketPositionResponse
{
    [JsonPropertyName("asset_id")] public string AssetId { get; set; } = "";
    [JsonPropertyName("market")] public string Market { get; set; } = "";
    [JsonPropertyName("outcome")] public string Outcome { get; set; } = "";

    [JsonPropertyName("size")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Size { get; set; }

    [JsonPropertyName("avgPrice")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double AvgPrice { get; set; }

    [JsonPropertyName("currentValue")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double CurrentValue { get; set; }

    [JsonPropertyName("cashPnl")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double CashPnl { get; set; }

    [JsonPropertyName("percentPnl")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double PercentPnl { get; set; }

    [JsonPropertyName("question")] public string Question { get; set; } = "";
}

// ═══════════════════════════════════════════════════════
//  Gamma API — Market metadata (full market response)
// ═══════════════════════════════════════════════════════

public class GammaMarketResponse
{
    [JsonPropertyName("id")] public string Id { get; set; } = "";
    [JsonPropertyName("conditionId")] public string ConditionId { get; set; } = "";
    [JsonPropertyName("questionID")] public string QuestionId { get; set; } = "";
    [JsonPropertyName("question")] public string Question { get; set; } = "";
    [JsonPropertyName("slug")] public string Slug { get; set; } = "";
    [JsonPropertyName("description")] public string? Description { get; set; }
    [JsonPropertyName("image")] public string? Image { get; set; }
    [JsonPropertyName("category")] public string Category { get; set; } = "";
    [JsonPropertyName("groupItemTitle")] public string? GroupItemTitle { get; set; }
    [JsonPropertyName("events")] public List<GammaEventResponse>? Events { get; set; }

    [JsonPropertyName("volumeNum")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Volume { get; set; }

    [JsonPropertyName("volume24hr")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Volume24hr { get; set; }

    [JsonPropertyName("liquidityNum")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Liquidity { get; set; }

    [JsonPropertyName("endDateIso")] public string? EndDateIso { get; set; }
    [JsonPropertyName("endDate")] public string? EndDate { get; set; }
    [JsonPropertyName("startDate")] public string? StartDate { get; set; }
    [JsonPropertyName("createdAt")] public string? CreatedAt { get; set; }
    [JsonPropertyName("closed")] public bool Closed { get; set; }
    [JsonPropertyName("active")] public bool Active { get; set; }
    [JsonPropertyName("resolved")] public bool Resolved { get; set; }
    [JsonPropertyName("umaResolutionStatus")] public string? UmaResolutionStatus { get; set; }
    [JsonPropertyName("negRisk")] public bool NegRisk { get; set; }
    [JsonPropertyName("closedTime")] public string? ClosedTime { get; set; }
    [JsonPropertyName("takerFee")] [JsonConverter(typeof(FlexibleDoubleConverter))] public double TakerFee { get; set; }

    /// <summary>JSON string of outcomes, e.g. "[\"Yes\", \"No\"]"</summary>
    [JsonPropertyName("outcomes")] public string? Outcomes { get; set; }

    /// <summary>JSON string of outcomePrices, e.g. "[\"0.55\", \"0.45\"]"</summary>
    [JsonPropertyName("outcomePrices")] public string? OutcomePrices { get; set; }

    /// <summary>JSON string of CLOB token IDs, e.g. "[\"12345...\", \"67890...\"]"</summary>
    [JsonPropertyName("clobTokenIds")] public string? ClobTokenIds { get; set; }
}

public class GammaEventResponse
{
    [JsonPropertyName("id")] public string Id { get; set; } = "";
    [JsonPropertyName("slug")] public string Slug { get; set; } = "";
    [JsonPropertyName("title")] public string Title { get; set; } = "";
    [JsonPropertyName("description")] public string? Description { get; set; }
    [JsonPropertyName("image")] public string? Image { get; set; }
    [JsonPropertyName("startDate")] public string? StartDate { get; set; }
    [JsonPropertyName("endDate")] public string? EndDate { get; set; }
    [JsonPropertyName("createdAt")] public string? CreatedAt { get; set; }
    [JsonPropertyName("active")] public bool Active { get; set; }
    [JsonPropertyName("closed")] public bool Closed { get; set; }
    [JsonPropertyName("tags")] public List<GammaTagResponse> Tags { get; set; } = [];
    [JsonPropertyName("markets")] public List<GammaMarketResponse> Markets { get; set; } = [];
}

public class OrderBookResponse
{
    [JsonPropertyName("bids")] public List<OrderBookLevel> Bids { get; set; } = [];
    [JsonPropertyName("asks")] public List<OrderBookLevel> Asks { get; set; } = [];
}

public class OrderBookLevel
{
    [JsonPropertyName("price")] public string Price { get; set; } = "0";
    [JsonPropertyName("size")] public string Size { get; set; } = "0";
}

public class GammaTagResponse
{
    [JsonPropertyName("id")] public string Id { get; set; } = "";
    [JsonPropertyName("label")] public string Label { get; set; } = "";
    [JsonPropertyName("slug")] public string Slug { get; set; } = "";
}

// ═══════════════════════════════════════════════════════
//  Data API — Holders response
// ═══════════════════════════════════════════════════════

public class HoldersResponse
{
    [JsonPropertyName("token")] public string Token { get; set; } = "";
    [JsonPropertyName("holders")] public List<HolderEntry> Holders { get; set; } = [];
}

public class HolderEntry
{
    [JsonPropertyName("proxyWallet")] public string ProxyWallet { get; set; } = "";
    [JsonPropertyName("name")] public string Name { get; set; } = "";
    [JsonPropertyName("pseudonym")] public string Pseudonym { get; set; } = "";

    [JsonPropertyName("amount")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Amount { get; set; }

    [JsonPropertyName("outcomeIndex")] public int OutcomeIndex { get; set; }
    [JsonPropertyName("profileImage")] public string? ProfileImage { get; set; }
    [JsonPropertyName("verified")] public bool Verified { get; set; }
}

// ═══════════════════════════════════════════════════════
//  Polymarket Data API v1 Leaderboard response
// ═══════════════════════════════════════════════════════

public class LeaderboardEntry
{
    [JsonPropertyName("rank")] public string Rank { get; set; } = "";
    [JsonPropertyName("proxyWallet")] public string ProxyWallet { get; set; } = "";
    [JsonPropertyName("userName")] public string UserName { get; set; } = "";

    [JsonPropertyName("vol")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Vol { get; set; }

    [JsonPropertyName("pnl")]
    [JsonConverter(typeof(FlexibleDoubleConverter))]
    public double Pnl { get; set; }

    [JsonPropertyName("profileImage")] public string? ProfileImage { get; set; }
    [JsonPropertyName("xUsername")] public string? XUsername { get; set; }
    [JsonPropertyName("verifiedBadge")] public bool VerifiedBadge { get; set; }
}
