//
//  GalleryManifestParityTest.swift
//  HoneyDueTests
//
//  Parity gate — asserts `SnapshotGalleryTests.swift`'s covered-screen
//  set matches exactly the subset of screens in the canonical
//  `GalleryScreens` manifest (in
//  `composeApp/src/commonMain/.../testing/GalleryManifest.kt`) with
//  `Platform.IOS` in their `platforms`.
//
//  If this fails, either:
//    - A new `test_<name>()` was added to `SnapshotGalleryTests.swift`
//      but the name isn't in the canonical manifest — add it to
//      `GalleryScreens.all`.
//    - A new screen was added to the manifest but there's no matching
//      `test_<name>()` function in the Swift test file — write one.
//    - A rename landed on only one side — reconcile.
//
//  Together with the Android `GalleryManifestParityTest`, this keeps
//  the two platforms from silently drifting apart in coverage.
//

import XCTest
import ComposeApp

@MainActor
final class GalleryManifestParityTest: XCTestCase {

    /// Canonical names of every surface covered by
    /// `SnapshotGalleryTests.swift`. This must be updated whenever a
    /// new `test_<name>()` is added to the suite. The parity assertion
    /// below catches a missed update.
    ///
    /// Using a hand-maintained list (rather than runtime introspection
    /// of `XCTestCase` selectors) keeps the contract explicit and makes
    /// drifts obvious in a diff.
    private static let iosCoveredScreens: Set<String> = [
        // Auth
        "login", "register", "forgot_password", "verify_reset_code",
        "reset_password", "verify_email",
        // Onboarding
        "onboarding_welcome", "onboarding_value_props",
        "onboarding_create_account", "onboarding_verify_email",
        "onboarding_location", "onboarding_name_residence",
        "onboarding_home_profile", "onboarding_join_residence",
        "onboarding_first_task", "onboarding_subscription",
        // Residences
        "residences", "residence_detail", "add_residence",
        "edit_residence", "join_residence", "manage_users",
        // Tasks
        "all_tasks", "add_task", "add_task_with_residence",
        "edit_task", "complete_task", "task_suggestions",
        "task_templates_browser",
        // Contractors
        "contractors", "contractor_detail",
        // Documents
        "documents_warranties", "document_detail", "add_document",
        "edit_document",
        // Profile / settings
        "profile", "profile_edit", "notification_preferences",
        "theme_selection",
        // Subscription
        "feature_comparison",
    ]

    func test_ios_surfaces_match_canonical_manifest() {
        // `GalleryScreens.shared.forIos` is the Swift-bridged map of
        // `GalleryScreen` keyed by canonical name. SKIE exposes the
        // Kotlin `object GalleryScreens` as a Swift type with a
        // `shared` instance accessor.
        let manifestKeys = Set(GalleryScreens.shared.forIos.keys.compactMap { $0 as? String })

        let missing = manifestKeys.subtracting(Self.iosCoveredScreens)
        let extra = Self.iosCoveredScreens.subtracting(manifestKeys)

        if !missing.isEmpty || !extra.isEmpty {
            var message = "iOS SnapshotGalleryTests drifted from canonical manifest.\n"
            if !missing.isEmpty {
                message += "\nScreens in manifest but missing test_<name>() in Swift:\n"
                for name in missing.sorted() {
                    message += "  - \(name)\n"
                }
            }
            if !extra.isEmpty {
                message += "\nScreens covered by Swift tests but missing from manifest:\n"
                for name in extra.sorted() {
                    message += "  - \(name)\n"
                }
            }
            message += "\nReconcile by editing com.tt.honeyDue.testing.GalleryScreens and/or\n"
            message += "SnapshotGalleryTests.swift (plus iosCoveredScreens above) so all three agree.\n"
            XCTFail(message)
        }
    }
}
