/**
 * @file hosting.hpp
 * @brief Synor Hosting SDK for C++
 *
 * Modern C++17 SDK for decentralized web hosting with domain management, DNS, deployments, and SSL.
 */

#pragma once

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

namespace synor {
namespace hosting {

/// Domain status
enum class DomainStatus {
    Pending,
    Active,
    Expired,
    Suspended
};

/// Deployment status
enum class DeploymentStatus {
    Pending,
    Building,
    Deploying,
    Active,
    Failed,
    Inactive
};

/// Certificate status
enum class CertificateStatus {
    Pending,
    Issued,
    Expired,
    Revoked
};

/// DNS record type
enum class DnsRecordType {
    A,
    AAAA,
    CNAME,
    TXT,
    MX,
    NS,
    SRV,
    CAA
};

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

/// Domain record
struct DomainRecord {
    std::optional<std::string> cid;
    std::optional<std::vector<std::string>> ipv4;
    std::optional<std::vector<std::string>> ipv6;
    std::optional<std::string> cname;
    std::optional<std::vector<std::string>> txt;
    std::optional<std::map<std::string, std::string>> metadata;
};

/// A domain
struct Domain {
    std::string name;
    DomainStatus status;
    std::string owner;
    int64_t registered_at;
    int64_t expires_at;
    bool auto_renew;
    std::optional<DomainRecord> records;
};

/// Domain availability
struct DomainAvailability {
    std::string name;
    bool available;
    std::optional<double> price;
    bool premium = false;
};

/// Domain registration options
struct RegisterDomainOptions {
    std::optional<int32_t> years;
    std::optional<bool> auto_renew;
};

/// DNS record
struct DnsRecord {
    DnsRecordType type;
    std::string name;
    std::string value;
    int32_t ttl = 3600;
    std::optional<int32_t> priority;
};

/// DNS zone
struct DnsZone {
    std::string domain;
    std::vector<DnsRecord> records;
    int64_t updated_at;
};

/// A deployment
struct Deployment {
    std::string id;
    std::string domain;
    std::string cid;
    DeploymentStatus status;
    std::string url;
    int64_t created_at;
    int64_t updated_at;
    std::optional<std::string> build_logs;
    std::optional<std::string> error_message;
};

/// Deploy options
struct DeployOptions {
    std::optional<std::string> domain;
    std::optional<std::string> subdomain;
    std::optional<bool> spa;
    std::optional<bool> clean_urls;
    std::optional<bool> trailing_slash;
};

/// SSL certificate
struct Certificate {
    std::string domain;
    CertificateStatus status;
    bool auto_renew;
    std::string issuer;
    std::optional<int64_t> issued_at;
    std::optional<int64_t> expires_at;
    std::optional<std::string> fingerprint;
};

/// SSL provisioning options
struct ProvisionSslOptions {
    std::optional<bool> include_www;
    std::optional<bool> auto_renew;
};

/// Redirect rule
struct RedirectRule {
    std::string source;
    std::string destination;
    int32_t status_code = 301;
    bool permanent = true;
};

/// Site configuration
struct SiteConfig {
    std::string domain;
    std::optional<std::string> cid;
    std::optional<std::map<std::string, std::string>> headers;
    std::optional<std::vector<RedirectRule>> redirects;
    std::optional<std::map<std::string, std::string>> error_pages;
    bool spa = false;
    bool clean_urls = true;
    bool trailing_slash = false;
};

/// Page view stats
struct PageView {
    std::string path;
    int64_t views;
};

/// Analytics data
struct AnalyticsData {
    std::string domain;
    std::string period;
    int64_t page_views;
    int64_t unique_visitors;
    int64_t bandwidth;
    std::vector<PageView> top_pages;
};

/// Analytics options
struct AnalyticsOptions {
    std::optional<std::string> period;
    std::optional<std::string> start;
    std::optional<std::string> end;
};

// Forward declaration
class SynorHostingImpl;

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

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

    // Domain operations
    std::future<DomainAvailability> check_availability(const std::string& name);
    std::future<Domain> register_domain(const std::string& name,
                                        const RegisterDomainOptions& options = {});
    std::future<Domain> get_domain(const std::string& name);
    std::future<std::vector<Domain>> list_domains();
    std::future<Domain> update_domain_record(const std::string& name, const DomainRecord& record);
    std::future<DomainRecord> resolve_domain(const std::string& name);
    std::future<Domain> renew_domain(const std::string& name, int32_t years);

    // DNS operations
    std::future<DnsZone> get_dns_zone(const std::string& domain);
    std::future<DnsZone> set_dns_records(const std::string& domain,
                                         const std::vector<DnsRecord>& records);
    std::future<DnsZone> add_dns_record(const std::string& domain, const DnsRecord& record);
    std::future<DnsZone> delete_dns_record(const std::string& domain,
                                           const std::string& record_type,
                                           const std::string& name);

    // Deployment operations
    std::future<Deployment> deploy(const std::string& cid, const DeployOptions& options = {});
    std::future<Deployment> get_deployment(const std::string& id);
    std::future<std::vector<Deployment>> list_deployments(
        std::optional<std::string> domain = std::nullopt);
    std::future<Deployment> rollback(const std::string& domain, const std::string& deployment_id);
    std::future<void> delete_deployment(const std::string& id);

    // SSL operations
    std::future<Certificate> provision_ssl(const std::string& domain,
                                           const ProvisionSslOptions& options = {});
    std::future<Certificate> get_certificate(const std::string& domain);
    std::future<Certificate> renew_certificate(const std::string& domain);
    std::future<void> delete_certificate(const std::string& domain);

    // Site configuration
    std::future<SiteConfig> get_site_config(const std::string& domain);
    std::future<SiteConfig> update_site_config(const std::string& domain,
                                                const std::map<std::string, std::string>& config);
    std::future<int64_t> purge_cache(const std::string& domain,
                                     std::optional<std::vector<std::string>> paths = std::nullopt);

    // Analytics
    std::future<AnalyticsData> get_analytics(const std::string& domain,
                                             const AnalyticsOptions& options = {});

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

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

}  // namespace hosting
}  // namespace synor
