namespace Synor.Sdk.Economics;

public enum ServiceType { Compute, Storage, Database, Hosting, Rpc, Bridge }
public enum BillingPeriod { Hourly, Daily, Weekly, Monthly }
public enum StakeStatus { Active, Unstaking, Withdrawn }
public enum DiscountType { Percentage, Fixed, Credits }
public enum InvoiceStatus { Pending, Paid, Overdue, Cancelled }

public record EconomicsConfig(
    string ApiKey,
    string Endpoint = "https://economics.synor.io/v1",
    TimeSpan? Timeout = null,
    int Retries = 3,
    bool Debug = false
) {
    public TimeSpan Timeout { get; init; } = Timeout ?? TimeSpan.FromSeconds(30);
}

public record ServicePricing(
    ServiceType Service,
    string Unit,
    string PricePerUnit,
    string Currency,
    double Minimum = 0.0,
    double Maximum = 0.0
);

public record UsageMetrics(
    ServiceType Service,
    double ComputeUnits = 0.0,
    double StorageBytes = 0.0,
    double BandwidthBytes = 0.0,
    long DurationSeconds = 0,
    int Requests = 0
);

public record PriceResult(
    ServiceType Service,
    string Amount,
    string Currency,
    UsageMetrics Usage
);

public record UsagePlanItem(
    ServiceType Service,
    UsageMetrics ProjectedUsage,
    BillingPeriod Period
);

public record CostItem(ServiceType Service, string Amount);

public record CostEstimate(
    string Total,
    string Currency,
    List<CostItem> Breakdown,
    string? DiscountApplied,
    BillingPeriod Period
);

public record UsageItem(
    ServiceType Service,
    double ComputeUnits,
    double StorageBytes,
    double BandwidthBytes,
    int Requests,
    string Cost
);

public record Usage(
    BillingPeriod Period,
    long StartDate,
    long EndDate,
    List<UsageItem> Items,
    string TotalCost,
    string Currency
);

public record InvoiceLine(
    string Service,
    string Description,
    int Quantity,
    string UnitPrice,
    string Amount
);

public record Invoice(
    string Id,
    long Date,
    long DueDate,
    InvoiceStatus Status,
    List<InvoiceLine> Lines,
    string Subtotal,
    string Discount,
    string Tax,
    string Total,
    string Currency,
    string? PdfUrl = null
);

public record AccountBalance(
    string Available,
    string Pending,
    string Staked,
    string Total,
    string Currency
);

public record Stake(
    string Id,
    string Amount,
    long StakedAt,
    long UnlockAt,
    StakeStatus Status,
    string RewardsEarned,
    double Apy
);

public record StakeReceipt(
    string Id,
    string Amount,
    string TxHash,
    long StakedAt,
    long UnlockAt,
    double Apy
);

public record UnstakeReceipt(
    string Id,
    string Amount,
    string TxHash,
    long UnstakedAt,
    long AvailableAt
);

public record StakingRewards(
    string Pending,
    string Claimed,
    string Total,
    double CurrentApy,
    long LastClaim,
    long NextDistribution
);

public record Discount(
    string Code,
    DiscountType Type,
    string Value,
    string Description,
    List<ServiceType> ApplicableServices,
    long ValidFrom,
    long ValidUntil,
    int MaxUses,
    int CurrentUses,
    bool Active
);

public record DiscountResult(
    Discount Discount,
    string SavingsEstimate,
    long AppliedAt
);

// Response wrappers
internal record PricingResponse(List<ServicePricing>? Pricing);
internal record InvoicesResponse(List<Invoice>? Invoices);
internal record StakesResponse(List<Stake>? Stakes);
internal record DiscountsResponse(List<Discount>? Discounts);
internal record HealthResponse(string Status);

public class EconomicsException : Exception
{
    public string? Code { get; }
    public int StatusCode { get; }

    public EconomicsException(string message, string? code = null, int statusCode = 0)
        : base(message)
    {
        Code = code;
        StatusCode = statusCode;
    }
}
