import Foundation

// MARK: - Configuration

/// Configuration for the Synor Hosting client.
public struct HostingConfig {
    public let apiKey: String
    public let endpoint: String
    public let timeout: TimeInterval
    public let retries: Int
    public let debug: Bool

    public init(
        apiKey: String,
        endpoint: String = "https://hosting.synor.io/v1",
        timeout: TimeInterval = 60,
        retries: Int = 3,
        debug: Bool = false
    ) {
        self.apiKey = apiKey
        self.endpoint = endpoint
        self.timeout = timeout
        self.retries = retries
        self.debug = debug
    }
}

// MARK: - Domain Types

/// Status of a domain.
public enum DomainStatus: String, Codable, Sendable {
    case pending
    case active
    case expired
    case suspended
}

/// A domain registration.
public struct Domain: Codable, Sendable {
    public let name: String
    public let status: DomainStatus
    public let owner: String
    public let registeredAt: Int64
    public let expiresAt: Int64
    public let autoRenew: Bool
    public let records: DomainRecord?
}

/// DNS record for a domain.
public struct DomainRecord: Codable, Sendable {
    public let cid: String?
    public let ipv4: [String]?
    public let ipv6: [String]?
    public let cname: String?
    public let txt: [String]?
    public let metadata: [String: String]?

    public init(
        cid: String? = nil,
        ipv4: [String]? = nil,
        ipv6: [String]? = nil,
        cname: String? = nil,
        txt: [String]? = nil,
        metadata: [String: String]? = nil
    ) {
        self.cid = cid
        self.ipv4 = ipv4
        self.ipv6 = ipv6
        self.cname = cname
        self.txt = txt
        self.metadata = metadata
    }
}

/// Domain availability check result.
public struct DomainAvailability: Codable, Sendable {
    public let name: String
    public let available: Bool
    public let price: Double?
    public let premium: Bool
}

/// Options for domain registration.
public struct RegisterDomainOptions: Codable, Sendable {
    public let years: Int?
    public let autoRenew: Bool?

    public init(years: Int? = nil, autoRenew: Bool? = nil) {
        self.years = years
        self.autoRenew = autoRenew
    }
}

/// Response for domain list operations.
public struct DomainsResponse: Codable {
    public let domains: [Domain]?
}

// MARK: - DNS Types

/// Type of DNS record.
public enum DnsRecordType: String, Codable, Sendable {
    case A, AAAA, CNAME, TXT, MX, NS, SRV, CAA
}

/// A DNS record.
public struct DnsRecord: Codable, Sendable {
    public let type: DnsRecordType
    public let name: String
    public let value: String
    public let ttl: Int
    public let priority: Int?

    public init(type: DnsRecordType, name: String, value: String, ttl: Int = 3600, priority: Int? = nil) {
        self.type = type
        self.name = name
        self.value = value
        self.ttl = ttl
        self.priority = priority
    }
}

/// A DNS zone containing records.
public struct DnsZone: Codable, Sendable {
    public let domain: String
    public let records: [DnsRecord]
    public let updatedAt: Int64
}

// MARK: - Deployment Types

/// Status of a deployment.
public enum DeploymentStatus: String, Codable, Sendable {
    case pending
    case building
    case deploying
    case active
    case failed
    case inactive
}

/// A deployment.
public struct Deployment: Codable, Sendable {
    public let id: String
    public let domain: String
    public let cid: String
    public let status: DeploymentStatus
    public let url: String
    public let createdAt: Int64
    public let updatedAt: Int64
    public let buildLogs: String?
    public let errorMessage: String?
}

/// Options for deploying content.
public struct DeployOptions: Codable, Sendable {
    public let domain: String?
    public let subdomain: String?
    public let spa: Bool?
    public let cleanUrls: Bool?
    public let trailingSlash: Bool?

    public init(
        domain: String? = nil,
        subdomain: String? = nil,
        spa: Bool? = nil,
        cleanUrls: Bool? = nil,
        trailingSlash: Bool? = nil
    ) {
        self.domain = domain
        self.subdomain = subdomain
        self.spa = spa
        self.cleanUrls = cleanUrls
        self.trailingSlash = trailingSlash
    }
}

/// Response for deployment list operations.
public struct DeploymentsResponse: Codable {
    public let deployments: [Deployment]?
}

// MARK: - SSL Types

/// Status of an SSL certificate.
public enum CertificateStatus: String, Codable, Sendable {
    case pending
    case issued
    case expired
    case revoked
}

/// An SSL certificate.
public struct Certificate: Codable, Sendable {
    public let domain: String
    public let status: CertificateStatus
    public let autoRenew: Bool
    public let issuer: String
    public let issuedAt: Int64?
    public let expiresAt: Int64?
    public let fingerprint: String?
}

/// Options for SSL provisioning.
public struct ProvisionSslOptions: Codable, Sendable {
    public let includeWww: Bool?
    public let autoRenew: Bool?

    public init(includeWww: Bool? = nil, autoRenew: Bool? = nil) {
        self.includeWww = includeWww
        self.autoRenew = autoRenew
    }
}

// MARK: - Site Configuration Types

/// Site configuration.
public struct SiteConfig: Codable, Sendable {
    public let domain: String
    public let cid: String?
    public let headers: [String: String]?
    public let redirects: [RedirectRule]?
    public let errorPages: [String: String]?
    public let spa: Bool
    public let cleanUrls: Bool
    public let trailingSlash: Bool
}

/// A redirect rule.
public struct RedirectRule: Codable, Sendable {
    public let source: String
    public let destination: String
    public let statusCode: Int
    public let permanent: Bool

    public init(source: String, destination: String, statusCode: Int = 301, permanent: Bool = true) {
        self.source = source
        self.destination = destination
        self.statusCode = statusCode
        self.permanent = permanent
    }
}

// MARK: - Analytics Types

/// Analytics data for a site.
public struct AnalyticsData: Codable, Sendable {
    public let domain: String
    public let period: String
    public let pageViews: Int64
    public let uniqueVisitors: Int64
    public let bandwidth: Int64
    public let topPages: [PageView]
    public let topReferrers: [Referrer]
    public let topCountries: [Country]
}

/// Page view statistics.
public struct PageView: Codable, Sendable {
    public let path: String
    public let views: Int64
}

/// Referrer statistics.
public struct Referrer: Codable, Sendable {
    public let referrer: String
    public let count: Int64
}

/// Country statistics.
public struct Country: Codable, Sendable {
    public let country: String
    public let count: Int64
}

/// Options for analytics queries.
public struct AnalyticsOptions: Codable, Sendable {
    public let period: String?
    public let start: String?
    public let end: String?

    public init(period: String? = nil, start: String? = nil, end: String? = nil) {
        self.period = period
        self.start = start
        self.end = end
    }
}

/// Response for cache purge operations.
public struct PurgeResponse: Codable {
    public let purged: Int64
}

// MARK: - Error Types

/// Errors that can occur during hosting operations.
public enum HostingError: Error, LocalizedError {
    case clientClosed
    case httpError(statusCode: Int, message: String, code: String?)
    case networkError(Error)
    case encodingError(Error)
    case decodingError(Error)
    case invalidResponse

    public var errorDescription: String? {
        switch self {
        case .clientClosed:
            return "Client has been closed"
        case .httpError(let statusCode, let message, _):
            return "HTTP \(statusCode): \(message)"
        case .networkError(let error):
            return "Network error: \(error.localizedDescription)"
        case .encodingError(let error):
            return "Encoding error: \(error.localizedDescription)"
        case .decodingError(let error):
            return "Decoding error: \(error.localizedDescription)"
        case .invalidResponse:
            return "Invalid response"
        }
    }
}

// MARK: - Health Check

/// Health check response.
public struct HostingHealthResponse: Codable {
    public let status: String
}
