/**
 * @file economics.hpp
 * @brief Synor Economics SDK for C++
 *
 * Modern C++17 SDK for pricing, billing, staking, and discount management.
 */

#pragma once

#include <string>
#include <vector>
#include <optional>
#include <future>
#include <memory>
#include <cstdint>
#include "wallet.hpp"  // For SynorException

namespace synor {
namespace economics {

/// Service type
enum class ServiceType {
    Compute,
    Storage,
    Database,
    Hosting,
    Rpc,
    Bridge
};

/// Billing period
enum class BillingPeriod {
    Hourly,
    Daily,
    Weekly,
    Monthly
};

/// Stake status
enum class StakeStatus {
    Active,
    Unstaking,
    Withdrawn
};

/// Discount type
enum class DiscountType {
    Percentage,
    Fixed,
    Credits
};

/// Invoice status
enum class InvoiceStatus {
    Pending,
    Paid,
    Overdue,
    Cancelled
};

/// Economics configuration
struct Config {
    std::string api_key;
    std::string endpoint = "https://economics.synor.io/v1";
    uint32_t timeout_ms = 30000;
    uint32_t retries = 3;
    bool debug = false;
};

/// Service pricing
struct ServicePricing {
    ServiceType service;
    std::string unit;
    std::string price_per_unit;
    std::string currency;
    double minimum = 0.0;
    double maximum = 0.0;
};

/// Usage metrics for pricing calculation
struct UsageMetrics {
    ServiceType service;
    double compute_units = 0.0;
    double storage_bytes = 0.0;
    double bandwidth_bytes = 0.0;
    int64_t duration_seconds = 0;
    int32_t requests = 0;
};

/// Price calculation result
struct PriceResult {
    ServiceType service;
    std::string amount;
    std::string currency;
    UsageMetrics usage;
};

/// Usage plan item for cost estimation
struct UsagePlanItem {
    ServiceType service;
    UsageMetrics projected_usage;
    BillingPeriod period;
};

/// Cost breakdown item
struct CostItem {
    ServiceType service;
    std::string amount;
};

/// Cost estimate result
struct CostEstimate {
    std::string total;
    std::string currency;
    std::vector<CostItem> breakdown;
    std::optional<std::string> discount_applied;
    BillingPeriod period;
};

/// Usage item
struct UsageItem {
    ServiceType service;
    double compute_units;
    double storage_bytes;
    double bandwidth_bytes;
    int32_t requests;
    std::string cost;
};

/// Usage report
struct Usage {
    BillingPeriod period;
    int64_t start_date;
    int64_t end_date;
    std::vector<UsageItem> items;
    std::string total_cost;
    std::string currency;
};

/// Invoice line item
struct InvoiceLine {
    std::string service;
    std::string description;
    int32_t quantity;
    std::string unit_price;
    std::string amount;
};

/// Invoice
struct Invoice {
    std::string id;
    int64_t date;
    int64_t due_date;
    InvoiceStatus status;
    std::vector<InvoiceLine> lines;
    std::string subtotal;
    std::string discount;
    std::string tax;
    std::string total;
    std::string currency;
    std::optional<std::string> pdf_url;
};

/// Account balance
struct AccountBalance {
    std::string available;
    std::string pending;
    std::string staked;
    std::string total;
    std::string currency;
};

/// Stake information
struct Stake {
    std::string id;
    std::string amount;
    int64_t staked_at;
    int64_t unlock_at;
    StakeStatus status;
    std::string rewards_earned;
    double apy;
};

/// Stake receipt
struct StakeReceipt {
    std::string id;
    std::string amount;
    std::string tx_hash;
    int64_t staked_at;
    int64_t unlock_at;
    double apy;
};

/// Unstake receipt
struct UnstakeReceipt {
    std::string id;
    std::string amount;
    std::string tx_hash;
    int64_t unstaked_at;
    int64_t available_at;
};

/// Staking rewards
struct StakingRewards {
    std::string pending;
    std::string claimed;
    std::string total;
    double current_apy;
    int64_t last_claim;
    int64_t next_distribution;
};

/// Discount information
struct Discount {
    std::string code;
    DiscountType type;
    std::string value;
    std::string description;
    std::vector<ServiceType> applicable_services;
    int64_t valid_from;
    int64_t valid_until;
    int32_t max_uses;
    int32_t current_uses;
    bool active;
};

/// Discount application result
struct DiscountResult {
    Discount discount;
    std::string savings_estimate;
    int64_t applied_at;
};

// Forward declaration
class SynorEconomicsImpl;

/// Synor Economics client
class SynorEconomics {
public:
    explicit SynorEconomics(const Config& config);
    ~SynorEconomics();

    SynorEconomics(const SynorEconomics&) = delete;
    SynorEconomics& operator=(const SynorEconomics&) = delete;
    SynorEconomics(SynorEconomics&&) noexcept;
    SynorEconomics& operator=(SynorEconomics&&) noexcept;

    // Pricing operations
    std::future<std::vector<ServicePricing>> get_pricing(std::optional<ServiceType> service = std::nullopt);
    std::future<PriceResult> get_price(ServiceType service, const UsageMetrics& usage);
    std::future<CostEstimate> estimate_cost(const std::vector<UsagePlanItem>& plan);

    // Billing operations
    std::future<Usage> get_usage(std::optional<BillingPeriod> period = std::nullopt);
    std::future<std::vector<Invoice>> get_invoices();
    std::future<Invoice> get_invoice(const std::string& invoice_id);
    std::future<AccountBalance> get_balance();

    // Staking operations
    std::future<StakeReceipt> stake(const std::string& amount, int32_t duration_days = 0);
    std::future<UnstakeReceipt> unstake(const std::string& stake_id);
    std::future<std::vector<Stake>> get_stakes();
    std::future<Stake> get_stake(const std::string& stake_id);
    std::future<StakingRewards> get_staking_rewards();
    std::future<StakeReceipt> claim_rewards();

    // Discount operations
    std::future<DiscountResult> apply_discount(const std::string& code);
    std::future<void> remove_discount(const std::string& code);
    std::future<std::vector<Discount>> get_discounts();

    // Lifecycle
    void close();
    bool is_closed() const;
    std::future<bool> health_check();

private:
    std::unique_ptr<SynorEconomicsImpl> impl_;
};

}  // namespace economics
}  // namespace synor
