import Testing
@testable import bookstax

@Suite("BookStackError – errorDescription")
struct BookStackErrorTests {

    @Test("invalidURL has non-nil description mentioning https")
    func invalidURL() {
        let desc = BookStackError.invalidURL.errorDescription
        #expect(desc != nil)
        #expect(desc!.contains("https"))
    }

    @Test("notAuthenticated has non-nil description")
    func notAuthenticated() {
        let desc = BookStackError.notAuthenticated.errorDescription
        #expect(desc != nil)
        #expect(!desc!.isEmpty)
    }

    @Test("unauthorized mentions token")
    func unauthorized() {
        let desc = BookStackError.unauthorized.errorDescription
        #expect(desc != nil)
        #expect(desc!.lowercased().contains("token"))
    }

    @Test("forbidden mentions 403 or permission")
    func forbidden() {
        let desc = BookStackError.forbidden.errorDescription
        #expect(desc != nil)
        let lower = desc!.lowercased()
        #expect(lower.contains("403") || lower.contains("permission") || lower.contains("access"))
    }

    @Test("notFound includes resource name in description")
    func notFound() {
        let desc = BookStackError.notFound(resource: "MyPage").errorDescription
        #expect(desc != nil)
        #expect(desc!.contains("MyPage"))
    }

    @Test("httpError with message returns that message")
    func httpErrorWithMessage() {
        let desc = BookStackError.httpError(statusCode: 500, message: "Internal Server Error").errorDescription
        #expect(desc == "Internal Server Error")
    }

    @Test("httpError without message includes status code")
    func httpErrorWithoutMessage() {
        let desc = BookStackError.httpError(statusCode: 503, message: nil).errorDescription
        #expect(desc != nil)
        #expect(desc!.contains("503"))
    }

    @Test("decodingError includes detail string")
    func decodingError() {
        let desc = BookStackError.decodingError("keyNotFound").errorDescription
        #expect(desc != nil)
        #expect(desc!.contains("keyNotFound"))
    }

    @Test("networkUnavailable mentions cache or offline")
    func networkUnavailable() {
        let desc = BookStackError.networkUnavailable.errorDescription
        #expect(desc != nil)
        let lower = desc!.lowercased()
        #expect(lower.contains("cache") || lower.contains("offline") || lower.contains("internet"))
    }

    @Test("keychainError includes numeric status code")
    func keychainError() {
        let desc = BookStackError.keychainError(-25300).errorDescription
        #expect(desc != nil)
        #expect(desc!.contains("-25300"))
    }

    @Test("sslError mentions SSL or TLS")
    func sslError() {
        let desc = BookStackError.sslError.errorDescription
        #expect(desc != nil)
        let upper = desc!.uppercased()
        #expect(upper.contains("SSL") || upper.contains("TLS"))
    }

    @Test("timeout mentions timed out or server")
    func timeout() {
        let desc = BookStackError.timeout.errorDescription
        #expect(desc != nil)
        #expect(!desc!.isEmpty)
    }

    @Test("notReachable includes the host name")
    func notReachable() {
        let desc = BookStackError.notReachable(host: "wiki.company.com").errorDescription
        #expect(desc != nil)
        #expect(desc!.contains("wiki.company.com"))
    }

    @Test("notBookStack includes the host name")
    func notBookStack() {
        let desc = BookStackError.notBookStack(host: "example.com").errorDescription
        #expect(desc != nil)
        #expect(desc!.contains("example.com"))
    }

    @Test("unknown returns the provided message verbatim")
    func unknown() {
        let msg = "Something went very wrong"
        let desc = BookStackError.unknown(msg).errorDescription
        #expect(desc == msg)
    }

    @Test("All cases produce non-nil, non-empty descriptions")
    func allCasesHaveDescriptions() {
        let errors: [BookStackError] = [
            .invalidURL, .notAuthenticated, .unauthorized, .forbidden,
            .notFound(resource: "X"), .httpError(statusCode: 400, message: nil),
            .decodingError("err"), .networkUnavailable, .keychainError(0),
            .sslError, .timeout, .notReachable(host: "host"),
            .notBookStack(host: "host"), .unknown("oops")
        ]
        for error in errors {
            let desc = error.errorDescription
            #expect(desc != nil, "nil description for \(error)")
            #expect(!desc!.isEmpty, "empty description for \(error)")
        }
    }
}
