using System.Text.Json;

namespace KArtSell.Modules.ModelOperations.TradeExecution;

public enum TradeStatus
{
    Pending,
    Submitted,
    Accepted,
    PartiallyFilled,
    FullyFilled,
    Confirmed,
    Reconciled
}

public class Trade
{
    public Guid Id { get; set; }
    public Guid SellDecisionId { get; set; }
    public string? KisOrderId { get; set; }
    public TradeStatus Status { get; set; }
    public int Quantity { get; set; }
    public int? ExecutedQuantity { get; set; }
    public decimal? UnitPrice { get; set; }
    public decimal? TotalAmount { get; set; }
    public decimal? Commission { get; set; }
    public decimal? NetProceeds { get; set; }
    public string? ErrorMessage { get; set; }
    public string? KisResponse { get; set; }
    public DateTime? ExecutionTimestamp { get; set; }
    public DateTime? SettlementTimestamp { get; set; }
    public DateTime PublishedAt { get; set; }
    public Guid CorrelationId { get; set; }
    public int Revision { get; set; }

    public static Trade Create(
        Guid sellDecisionId,
        int quantity,
        Guid correlationId,
        DateTime now)
    {
        return new Trade
        {
            Id = Guid.NewGuid(),
            SellDecisionId = sellDecisionId,
            Status = TradeStatus.Pending,
            Quantity = quantity,
            PublishedAt = now,
            CorrelationId = correlationId,
            Revision = 1
        };
    }

    public void MarkSubmitted(string kisOrderId, JsonElement response)
    {
        Status = TradeStatus.Submitted;
        KisOrderId = kisOrderId;
        KisResponse = response.ToString();
        Revision++;
    }

    public void MarkAccepted(JsonElement response)
    {
        Status = TradeStatus.Accepted;
        KisResponse = response.ToString();
        Revision++;
    }

    public void MarkFilled(int executedQty, decimal unitPrice, JsonElement response, DateTime now)
    {
        ExecutedQuantity = executedQty;
        UnitPrice = unitPrice;
        TotalAmount = executedQty * unitPrice;
        Status = executedQty >= Quantity ? TradeStatus.FullyFilled : TradeStatus.PartiallyFilled;
        ExecutionTimestamp = now;
        KisResponse = response.ToString();
        Revision++;
    }

    public void MarkConfirmed(DateTime now, decimal? commission = null)
    {
        Status = TradeStatus.Confirmed;
        if (commission.HasValue)
        {
            Commission = commission.Value;
            NetProceeds = (TotalAmount ?? 0) - Commission.Value;
        }
        SettlementTimestamp = now;
        Revision++;
    }

    public void MarkReconciled()
    {
        Status = TradeStatus.Reconciled;
        Revision++;
    }

    public void MarkErrored(KisTradeExecutionException exception)
    {
        ErrorMessage = exception.Message;
        KisResponse = exception.KisResponse?.ToString();
        Revision++;
    }
}

public class CreateTradeRequest
{
    public Guid SellDecisionId { get; set; }
    public int Quantity { get; set; }
    public decimal LimitPrice { get; set; }
}

public class CreateTradeResponse
{
    public Guid Id { get; set; }
    public required string Status { get; set; }
    public Guid SellDecisionId { get; set; }
    public int Quantity { get; set; }
}

public class TradeDetailResponse
{
    public Guid Id { get; set; }
    public required string Status { get; set; }
    public Guid SellDecisionId { get; set; }
    public string? KisOrderId { get; set; }
    public int Quantity { get; set; }
    public int? ExecutedQuantity { get; set; }
    public decimal? UnitPrice { get; set; }
    public decimal? TotalAmount { get; set; }
    public decimal? Commission { get; set; }
    public decimal? NetProceeds { get; set; }
    public DateTime? ExecutionTimestamp { get; set; }
    public DateTime? SettlementTimestamp { get; set; }
}

public class ListTradesResponse
{
    public IEnumerable<TradeDetailResponse> Items { get; set; } = new List<TradeDetailResponse>();
    public int Total { get; set; }
}
