import Testing
@testable import ContactsSyncCore

// MARK: - composeFamilyName

@Suite("composeFamilyName")
struct ComposeFamilyNameTests {

    @Test func emojiOnly_whenExistingIsEmpty() {
        #expect(ContactsWriterCore.composeFamilyName(emojis: "🔥👸", existingFamilyName: "") == "🔥👸")
    }

    @Test func emojiPlusSurname_whenExistingIsHumanName() {
        #expect(ContactsWriterCore.composeFamilyName(emojis: "🔥👸", existingFamilyName: "Smith") == "🔥👸 Smith")
    }

    @Test func dropsEmojiOnlyPrior_replaceWithNewEmoji() {
        // Prior write was emoji-only; new write replaces it entirely.
        #expect(ContactsWriterCore.composeFamilyName(emojis: "🔥", existingFamilyName: "🔥👸") == "🔥")
    }

    @Test func preservesHumanSurname_whenPriorHadEmojiPrefix() {
        // Prior write was "🔥 Smith"; we re-write with "🔥" — surname survives.
        #expect(ContactsWriterCore.composeFamilyName(emojis: "🔥", existingFamilyName: "🔥 Smith") == "🔥 Smith")
    }

    @Test func returnsHumanSurname_whenEmojisEmpty() {
        #expect(ContactsWriterCore.composeFamilyName(emojis: "", existingFamilyName: "Smith") == "Smith")
    }

    @Test func returnsEmpty_whenBothEmpty() {
        #expect(ContactsWriterCore.composeFamilyName(emojis: "", existingFamilyName: "") == "")
    }

    @Test func threeEmojis_withSurname() {
        #expect(ContactsWriterCore.composeFamilyName(emojis: "🔥👸🌹", existingFamilyName: "Fox") == "🔥👸🌹 Fox")
    }

    @Test func transFlagCompose_withSurname() {
        #expect(ContactsWriterCore.composeFamilyName(emojis: "🏳️‍⚧️", existingFamilyName: "Lane") == "🏳️‍⚧️ Lane")
    }

    @Test func whitespaceOnlyExisting_treatedAsEmpty() {
        #expect(ContactsWriterCore.composeFamilyName(emojis: "🔥", existingFamilyName: "   ") == "🔥")
    }
}

// MARK: - extractExtra

@Suite("extractExtra")
struct ExtractExtraTests {

    @Test func extractsHumanSurname_afterEmojiRun() {
        #expect(ContactsWriterCore.extractExtra(from: "🔥👸🌹 Smith") == "Smith")
    }

    @Test func returnsEmpty_forEmojiOnly() {
        #expect(ContactsWriterCore.extractExtra(from: "🔥👸🌹") == "")
    }

    @Test func returnsWholeName_whenNoLeadingEmoji() {
        #expect(ContactsWriterCore.extractExtra(from: "Smith") == "Smith")
    }

    @Test func returnsEmpty_forEmptyInput() {
        #expect(ContactsWriterCore.extractExtra(from: "") == "")
    }

    @Test func extractsMultiWordSurname() {
        #expect(ContactsWriterCore.extractExtra(from: "🔥 Anne Smith") == "Anne Smith")
    }

    @Test func transFlagFollowedBySurname() {
        #expect(ContactsWriterCore.extractExtra(from: "🏳️‍⚧️ Lane") == "Lane")
    }

    @Test func handlesWhitespace_onlyLeadingEmoji() {
        // Single emoji + spaces — tail is empty after trimming
        #expect(ContactsWriterCore.extractExtra(from: "🔥   ") == "")
    }
}

// MARK: - mergeNote

@Suite("mergeNote")
struct MergeNoteTests {

    let block = "<lilith-sync v=1>Handle: +14155551234\nMarket: SF</lilith-sync>"

    @Test func appendsBlock_whenNoteIsEmpty() {
        let result = ContactsWriterCore.mergeNote(existing: "", managedBlock: block)
        #expect(result == block)
    }

    @Test func appendsBlock_afterExistingText_whenNoSentinelPresent() {
        let existing = "Personal note."
        let result = ContactsWriterCore.mergeNote(existing: existing, managedBlock: block)
        #expect(result == "Personal note.\n\n\(block)")
    }

    @Test func replacesManagedBlock_whenSentinelsPresent() {
        let old = "<lilith-sync v=1>Handle: +1OLD\nMarket: LA</lilith-sync>"
        let existing = "Personal note.\n\n\(old)"
        let newBlock = "<lilith-sync v=1>Handle: +14155551234\nMarket: SF</lilith-sync>"
        let result = ContactsWriterCore.mergeNote(existing: existing, managedBlock: newBlock)
        #expect(result == "Personal note.\n\n\(newBlock)")
    }

    @Test func preservesTextBeforeSentinel() {
        let existing = "My notes before.\n\n\(block)"
        let newBlock = "<lilith-sync v=1>Handle: +14155559999</lilith-sync>"
        let result = ContactsWriterCore.mergeNote(existing: existing, managedBlock: newBlock)
        #expect(result.hasPrefix("My notes before.\n\n"))
    }

    @Test func preservesTextAfterSentinel() {
        let existing = "\(block)\n\nText after."
        let newBlock = "<lilith-sync v=1>updated</lilith-sync>"
        let result = ContactsWriterCore.mergeNote(existing: existing, managedBlock: newBlock)
        #expect(result.hasSuffix("\n\nText after."))
    }

    @Test func roundTrip_replacesCorrectly() {
        // Two sequential merges — second merge replaces first block entirely.
        let first = ContactsWriterCore.mergeNote(existing: "", managedBlock: block)
        let secondBlock = "<lilith-sync v=1>Handle: +15105550001\nMarket: LA</lilith-sync>"
        let second = ContactsWriterCore.mergeNote(existing: first, managedBlock: secondBlock)
        #expect(second == secondBlock)
    }
}

