package com.tt.honeyDue.testing

/**
 * Canonical list of every user-reachable screen in the HoneyDue app, used
 * as the single source of truth for the iOS↔Android parity-gallery
 * snapshot tests.
 *
 * Both platforms' snapshot harnesses are CI-gated against this manifest:
 *   - Android: `GalleryManifestParityTest` fails if the entries in
 *     `GallerySurfaces.kt` don't match the subset of screens with
 *     [Platform.ANDROID] in [platforms].
 *   - iOS: `GalleryManifestParityTest.swift` performs the equivalent check
 *     against `SnapshotGalleryTests.swift`.
 *
 * This prevents the two platforms from silently drifting apart in
 * coverage — adding a screen to one side without updating this manifest
 * (and therefore the other side) fails CI.
 *
 * When a screen is reachable on only one platform (e.g. [GalleryScreens.home]
 * on Android, [GalleryScreens.documentsWarranties] on iOS), mark it with
 * the relevant [Platform] set. The gallery HTML renders a visible
 * `[missing — <platform>]` placeholder for the absent side so the gap is
 * obvious rather than silently omitted.
 */

/** Category of a gallery screen — drives the capture-variant matrix. */
enum class GalleryCategory {
    /**
     * Screen renders data from [com.tt.honeyDue.data.IDataManager] (lists,
     * detail views, dashboards). Captures 4 variants: empty+populated x
     * light+dark — so the test proves the fixture actually reaches the UI.
     */
    DataCarrying,

    /**
     * Screen is a pure form, auth view, static onboarding step, or chrome
     * with no backing entity data. Captures 2 variants: light+dark only.
     * Skipping the populated variant prevents ~50 byte-identical-to-empty
     * goldens that add no signal.
     */
    DataFree,
}

/** Platforms that include a given screen in their parity-gallery harness. */
enum class Platform { ANDROID, IOS }

/**
 * One canonical screen in the parity manifest.
 *
 * @property name Snake-case identifier; doubles as the golden-PNG filename
 *   prefix on both platforms.
 * @property category Drives the capture-variant matrix (see [GalleryCategory]).
 * @property platforms Platforms that capture this screen. Screens captured
 *   on both have a paired row in the gallery; screens on only one show a
 *   `[missing]` placeholder for the absent platform.
 */
data class GalleryScreen(
    val name: String,
    val category: GalleryCategory,
    val platforms: Set<Platform>,
)

/**
 * Canonical manifest — 43 screens, ordered by product flow.
 *
 * Breakdown:
 *   - 12 [GalleryCategory.DataCarrying] screens — 4 captures each.
 *   - 31 [GalleryCategory.DataFree] screens — 2 captures each.
 *   - 37 screens captured on both platforms.
 *   - 3 Android-only: `home`, `documents`, `biometric_lock`.
 *   - 3 iOS-only: `documents_warranties`, `add_task`, `profile_edit`.
 */
object GalleryScreens {

    private val both = setOf(Platform.ANDROID, Platform.IOS)
    private val androidOnly = setOf(Platform.ANDROID)
    private val iosOnly = setOf(Platform.IOS)

    val all: List<GalleryScreen> = listOf(
        // ---------- Auth ----------
        GalleryScreen("login", GalleryCategory.DataFree, both),
        GalleryScreen("register", GalleryCategory.DataFree, both),
        GalleryScreen("forgot_password", GalleryCategory.DataFree, both),
        GalleryScreen("verify_reset_code", GalleryCategory.DataFree, both),
        GalleryScreen("reset_password", GalleryCategory.DataFree, both),
        GalleryScreen("verify_email", GalleryCategory.DataFree, both),

        // ---------- Onboarding ----------
        GalleryScreen("onboarding_welcome", GalleryCategory.DataFree, both),
        GalleryScreen("onboarding_value_props", GalleryCategory.DataFree, both),
        GalleryScreen("onboarding_create_account", GalleryCategory.DataFree, both),
        GalleryScreen("onboarding_verify_email", GalleryCategory.DataFree, both),
        GalleryScreen("onboarding_location", GalleryCategory.DataFree, both),
        GalleryScreen("onboarding_name_residence", GalleryCategory.DataFree, both),
        GalleryScreen("onboarding_home_profile", GalleryCategory.DataFree, both),
        GalleryScreen("onboarding_join_residence", GalleryCategory.DataFree, both),
        GalleryScreen("onboarding_first_task", GalleryCategory.DataCarrying, both),
        GalleryScreen("onboarding_subscription", GalleryCategory.DataFree, both),

        // ---------- Home / dashboard (Android-only) ----------
        GalleryScreen("home", GalleryCategory.DataCarrying, androidOnly),

        // ---------- Residences ----------
        GalleryScreen("residences", GalleryCategory.DataCarrying, both),
        GalleryScreen("residence_detail", GalleryCategory.DataCarrying, both),
        GalleryScreen("add_residence", GalleryCategory.DataFree, both),
        GalleryScreen("edit_residence", GalleryCategory.DataFree, both),
        GalleryScreen("join_residence", GalleryCategory.DataFree, both),
        // `manage_users` is DataFree: both platforms render a loading /
        // error state on first paint because residence-users data is
        // fetched via APILayer directly (no fixture seam). Populating
        // it would require a new `usersByResidence` field on
        // `IDataManager` plus fixture+screen wiring — deferred as a
        // production improvement rather than a snapshot-test-only
        // shim.
        GalleryScreen("manage_users", GalleryCategory.DataFree, both),

        // ---------- Tasks ----------
        GalleryScreen("all_tasks", GalleryCategory.DataCarrying, both),
        // `add_task` is iOS-only: iOS presents an "Add task" sheet from a
        // residence-scoped context. Android adds tasks via an inline dialog
        // inside `residence_detail`, with no standalone destination.
        GalleryScreen("add_task", GalleryCategory.DataFree, iosOnly),
        GalleryScreen("add_task_with_residence", GalleryCategory.DataFree, both),
        GalleryScreen("edit_task", GalleryCategory.DataFree, both),
        // `complete_task` is DataFree: the task and residence-name are
        // passed as static props, completion form fields default-render
        // the same regardless of fixture state, and the contractor
        // picker is collapsed on first paint. Nothing visible diffs
        // between empty and populated.
        GalleryScreen("complete_task", GalleryCategory.DataFree, both),
        // `task_suggestions` is DataFree in snapshot terms: the visible
        // first-paint state is driven by an `APILayer.getTaskSuggestions`
        // call (which fails hermetically), not by anything on
        // `IDataManager`. The populated templates stored on DM are only
        // surfaced after the API resolves, so both variants render the
        // same loading/error frame. Treating as DataFree is honest.
        GalleryScreen("task_suggestions", GalleryCategory.DataFree, both),
        GalleryScreen("task_templates_browser", GalleryCategory.DataCarrying, both),

        // ---------- Contractors ----------
        GalleryScreen("contractors", GalleryCategory.DataCarrying, both),
        GalleryScreen("contractor_detail", GalleryCategory.DataCarrying, both),

        // ---------- Documents ----------
        // Android has a single `documents` screen; iOS has a tabbed
        // `documents_warranties` view that unifies docs + warranties under
        // a segmented control. They're structurally distinct enough to
        // list as separate rows so the gallery makes the divergence
        // visible rather than pretending they're the same screen.
        GalleryScreen("documents", GalleryCategory.DataCarrying, androidOnly),
        GalleryScreen("documents_warranties", GalleryCategory.DataCarrying, iosOnly),
        GalleryScreen("document_detail", GalleryCategory.DataCarrying, both),
        GalleryScreen("add_document", GalleryCategory.DataFree, both),
        GalleryScreen("edit_document", GalleryCategory.DataFree, both),

        // ---------- Profile / settings ----------
        GalleryScreen("profile", GalleryCategory.DataCarrying, both),
        // `profile_edit` is iOS-only: iOS has a standalone edit-profile view.
        // On Android, profile editing is folded into `profile` (inline form).
        GalleryScreen("profile_edit", GalleryCategory.DataFree, iosOnly),
        GalleryScreen("notification_preferences", GalleryCategory.DataFree, both),
        GalleryScreen("theme_selection", GalleryCategory.DataFree, both),
        GalleryScreen("biometric_lock", GalleryCategory.DataFree, androidOnly),

        // ---------- Subscription ----------
        GalleryScreen("feature_comparison", GalleryCategory.DataFree, both),
    )

    /** Screens captured on Android, keyed by canonical name. */
    val forAndroid: Map<String, GalleryScreen> =
        all.filter { Platform.ANDROID in it.platforms }.associateBy { it.name }

    /** Screens captured on iOS, keyed by canonical name. */
    val forIos: Map<String, GalleryScreen> =
        all.filter { Platform.IOS in it.platforms }.associateBy { it.name }
}
