import Testing
import SwiftUI
@testable import bookstax

// MARK: - Color Hex Parsing

@Suite("Color – Hex Parsing")
struct ColorHexParsingTests {

    // MARK: Valid 6-digit hex

    @Test("6-digit hex without # prefix parses successfully")
    func sixDigitNoPound() {
        #expect(Color(hex: "FF0000") != nil)
    }

    @Test("6-digit hex with # prefix parses successfully")
    func sixDigitWithPound() {
        #expect(Color(hex: "#FF0000") != nil)
    }

    @Test("Black hex #000000 parses successfully")
    func blackHex() {
        #expect(Color(hex: "#000000") != nil)
    }

    @Test("White hex #FFFFFF parses successfully")
    func whiteHex() {
        #expect(Color(hex: "#FFFFFF") != nil)
    }

    @Test("Lowercase hex parses successfully")
    func lowercaseHex() {
        #expect(Color(hex: "#ff6600") != nil)
    }

    // MARK: Valid 3-digit hex

    @Test("3-digit hex #FFF is valid shorthand")
    func threeDigitFFF() {
        #expect(Color(hex: "#FFF") != nil)
    }

    @Test("3-digit hex #000 is valid shorthand")
    func threeDigitZero() {
        #expect(Color(hex: "#000") != nil)
    }

    @Test("3-digit hex #F60 is expanded to #FF6600")
    func threeDigitExpansion() {
        let threeDigit = Color(hex: "#F60")
        let sixDigit   = Color(hex: "#FF6600")
        // Both should parse successfully
        #expect(threeDigit != nil)
        #expect(sixDigit != nil)
    }

    // MARK: Invalid inputs

    @Test("5-digit hex returns nil")
    func fiveDigitInvalid() {
        #expect(Color(hex: "#FFFFF") == nil)
    }

    @Test("7-digit hex returns nil")
    func sevenDigitInvalid() {
        #expect(Color(hex: "#FFFFFFF") == nil)
    }

    @Test("Empty string returns nil")
    func emptyStringInvalid() {
        #expect(Color(hex: "") == nil)
    }

    @Test("Non-hex characters return nil")
    func nonHexCharacters() {
        #expect(Color(hex: "#GGGGGG") == nil)
    }

    @Test("Just # returns nil")
    func onlyHash() {
        #expect(Color(hex: "#") == nil)
    }
}

// MARK: - Color Hex Round-trip

@Suite("Color – Hex Round-trip")
struct ColorHexRoundTripTests {

    @Test("Red #FF0000 round-trips correctly")
    func redRoundTrip() {
        let color = Color(hex: "#FF0000")!
        let hex = color.toHexString()
        #expect(hex == "#FF0000")
    }

    @Test("Green #00FF00 round-trips correctly")
    func greenRoundTrip() {
        let color = Color(hex: "#00FF00")!
        let hex = color.toHexString()
        #expect(hex == "#00FF00")
    }

    @Test("Blue #0000FF round-trips correctly")
    func blueRoundTrip() {
        let color = Color(hex: "#0000FF")!
        let hex = color.toHexString()
        #expect(hex == "#0000FF")
    }

    @Test("Custom color #3A7B55 round-trips correctly")
    func customColorRoundTrip() {
        let color = Color(hex: "#3A7B55")!
        let hex = color.toHexString()
        #expect(hex == "#3A7B55")
    }
}

// MARK: - AccentTheme

@Suite("AccentTheme – Properties")
struct AccentThemeTests {

    @Test("All cases are represented in CaseIterable")
    func allCasesPresent() {
        #expect(AccentTheme.allCases.count == 8)
    }

    @Test("id equals rawValue")
    func idEqualsRawValue() {
        for theme in AccentTheme.allCases {
            #expect(theme.id == theme.rawValue)
        }
    }

    @Test("Every theme has a non-empty displayName")
    func displayNamesNonEmpty() {
        for theme in AccentTheme.allCases {
            #expect(!theme.displayName.isEmpty)
        }
    }

    @Test("accentColor equals shelfColor")
    func accentColorEqualsShelfColor() {
        for theme in AccentTheme.allCases {
            #expect(theme.accentColor == theme.shelfColor)
        }
    }

    @Test("Ocean theme has expected displayName")
    func oceanDisplayName() {
        #expect(AccentTheme.ocean.displayName == "Ocean")
    }

    @Test("Graphite theme has expected displayName")
    func graphiteDisplayName() {
        #expect(AccentTheme.graphite.displayName == "Graphite")
    }

    @Test("All themes can be init'd from rawValue")
    func initFromRawValue() {
        for theme in AccentTheme.allCases {
            let reinit = AccentTheme(rawValue: theme.rawValue)
            #expect(reinit == theme)
        }
    }
}
