package app.closer.core.navigation

import android.net.Uri

object AppRoute {
    const val ONBOARDING = "onboarding"
    const val LOGIN = "login"
    const val SIGN_UP = "sign_up"
    const val FORGOT_PASSWORD = "forgot_password"
    const val CREATE_PROFILE = "create_profile"
    const val PAIR_PROMPT = "pair_prompt"
    const val HOME = "home"
    const val PARTNER_HOME = "partner_home"
    const val PLAY = "play"
    const val DAILY_QUESTION = "daily_question"
    const val QUESTION_PACKS = "question_packs"
    const val MESSAGES = "messages"
    const val CONVERSATION = "conversation/{coupleId}/{conversationId}"
    const val QUESTION_CATEGORY = "question_category/{categoryId}"
    const val QUESTION_COMPOSER = "question_composer"
    const val ANSWER_REVEAL = "answer_reveal/{questionId}"
    const val ANSWER_HISTORY = "answer_history"
    const val CREATE_INVITE = "create_invite"
    const val ACCEPT_INVITE = "accept_invite"
    const val INVITE_CONFIRM = "invite_confirm/{inviteCode}"
    const val CATEGORY_PICKER = "category_picker"
    const val SPIN_WHEEL = "spin_wheel/{categoryId}"
    const val SPIN_WHEEL_RANDOM = "spin_wheel_random"
    const val WHEEL_SESSION = "wheel_session/{sessionId}"
    const val WHEEL_COMPLETE = "wheel_complete/{sessionId}"
    const val PAYWALL = "paywall"
    const val SETTINGS = "settings"
    const val ACCOUNT = "account"
    const val NOTIFICATIONS = "notifications"
    const val APPEARANCE = "appearance"
    const val PRIVACY = "privacy"
    const val SUBSCRIPTION = "subscription"
    const val RELATIONSHIP_SETTINGS = "relationship_settings"
    const val DELETE_ACCOUNT = "delete_account"
    const val SECURITY = "security_settings"
    const val WHEEL_HISTORY = "wheel_history"
    const val GAME_HISTORY = "game_history"
    const val THIS_OR_THAT_REPLAY = "this_or_that_replay/{sessionId}"
    const val DESIRE_SYNC_REPLAY = "desire_sync_replay/{sessionId}"
    const val HOW_WELL_REPLAY = "how_well_replay/{sessionId}"
    const val DATE_MATCH = "date_match"
    const val DATE_MATCHES = "date_matches"
    const val DATE_BUILDER = "date_builder"
    const val BUCKET_LIST = "bucket_list"
    const val THIS_OR_THAT = "this_or_that"
    const val HOW_WELL = "how_well"
    const val DESIRE_SYNC = "desire_sync"
    const val CONNECTION_CHALLENGES = "connection_challenges"
    const val MEMORY_LANE = "memory_lane"
    const val MEMORY_LANE_CAPSULE = "memory_lane_capsule/{capsuleId}"
    const val WAITING_FOR_PARTNER = "waiting_for_partner"
    const val RECOVERY = "recovery"
    const val YOUR_PROGRESS = "your_progress"
    const val ACTIVITY = "activity"
    const val ART_PREVIEW = "art_preview"
    const val PAIRED_HOME_PREVIEW = "paired_home_preview"
    const val PAIRING_SUCCESS = "pairing_success/{coupleId}"

    fun pairingSuccess(coupleId: String) = "pairing_success/$coupleId"

    fun memorylaneDetail(capsuleId: String): String = "memory_lane_capsule/${capsuleId.asRouteArg()}"

    // Question thread: coupleId and questionId are required; prevId and nextId are optional.
    const val QUESTION_THREAD =
        "question_thread/{coupleId}/{questionId}?prevId={prevId}&nextId={nextId}"

    data class Definition(
        val route: String,
        val title: String,
        val group: String
    )

    val definitions = listOf(
        Definition(ONBOARDING, "Onboarding", "onboarding"),
        Definition(CREATE_PROFILE, "Create Profile", "onboarding"),
        Definition(PAIR_PROMPT, "Invite Partner", "onboarding"),
        Definition(LOGIN, "Login", "auth"),
        Definition(SIGN_UP, "Sign Up", "auth"),
        Definition(FORGOT_PASSWORD, "Forgot Password", "auth"),
        Definition(HOME, "Home", "home"),
        Definition(PARTNER_HOME, "Partner", "home"),
        Definition(PLAY, "Play", "play"),
        Definition(DAILY_QUESTION, "Daily Question", "questions"),
        Definition(QUESTION_PACKS, "Question Packs", "questions"),
        Definition(MESSAGES, "Messages", "messages"),
        Definition(CONVERSATION, "Conversation", "messages"),
        Definition(QUESTION_CATEGORY, "Question Pack", "questions"),
        Definition(QUESTION_COMPOSER, "New Question", "questions"),
        Definition(QUESTION_THREAD, "Answer", "questions"),
        Definition(ANSWER_REVEAL, "Reveal", "answers"),
        Definition(ANSWER_HISTORY, "Answer History", "answers"),
        Definition(CREATE_INVITE, "Create Invite", "pairing"),
        Definition(ACCEPT_INVITE, "Accept Invite", "pairing"),
        Definition(INVITE_CONFIRM, "Invite Confirm", "pairing"),
        Definition(CATEGORY_PICKER, "Choose A Category", "wheel"),
        Definition(SPIN_WHEEL, "Spin", "wheel"),
        Definition(SPIN_WHEEL_RANDOM, "Spin the Wheel", "wheel"),
        Definition(WHEEL_SESSION, "Wheel Session", "wheel"),
        Definition(WHEEL_COMPLETE, "Complete", "wheel"),
        Definition(PAYWALL, "Unlock Everything", "paywall"),
        Definition(SETTINGS, "Settings", "settings"),
        Definition(ACCOUNT, "Account", "settings"),
        Definition(NOTIFICATIONS, "Notifications", "settings"),
        Definition(PRIVACY, "Privacy", "settings"),
        Definition(SUBSCRIPTION, "Subscription", "settings"),
        Definition(RELATIONSHIP_SETTINGS, "Relationship Settings", "settings"),
        Definition(DELETE_ACCOUNT, "Delete Account", "settings"),
        Definition(SECURITY, "Security", "settings"),
        Definition(WHEEL_HISTORY, "Wheel History", "wheel"),
        Definition(GAME_HISTORY, "Past Games", "play"),
        Definition(THIS_OR_THAT_REPLAY, "This or That Results", "play"),
        Definition(DESIRE_SYNC_REPLAY, "Desire Sync Results", "play"),
        Definition(HOW_WELL_REPLAY, "How Well Results", "play"),
        Definition(DATE_MATCH, "Date Match", "dates"),
        Definition(DATE_MATCHES, "Matches", "dates"),
        Definition(DATE_BUILDER, "Plan a Date", "dates"),
        Definition(BUCKET_LIST, "Our Bucket List", "dates"),
        Definition(THIS_OR_THAT, "This or That", "play"),
        Definition(HOW_WELL, "How Well Do You Know Me", "play"),
        Definition(DESIRE_SYNC, "Desire Sync", "play"),
        Definition(CONNECTION_CHALLENGES, "Connection Challenges", "play"),
        Definition(MEMORY_LANE, "Memory Lane", "play"),
        Definition(MEMORY_LANE_CAPSULE, "Memory Lane", "play"),
        Definition(WAITING_FOR_PARTNER, "Waiting for Partner", "play"),
        Definition(RECOVERY, "Unlock Answers", "security"),
        Definition(YOUR_PROGRESS, "Your Progress", "settings"),
        Definition(ACTIVITY, "Together", "home")
    )

    val topLevelRoutes = setOf(
        HOME,
        DAILY_QUESTION,
        PLAY,
        MESSAGES,
        SETTINGS
    )

    val onboardingAuthRoutes = setOf(
        ONBOARDING,
        CREATE_PROFILE,
        LOGIN,
        SIGN_UP,
        FORGOT_PASSWORD
    )

    val modalLikeRoutes = setOf(
        CREATE_INVITE,
        ACCEPT_INVITE,
        INVITE_CONFIRM,
        PAYWALL,
        YOUR_PROGRESS
    )

    val drillInRoutes = setOf(
        PARTNER_HOME,
        QUESTION_CATEGORY,
        QUESTION_COMPOSER,
        QUESTION_THREAD,
        ANSWER_REVEAL,
        CATEGORY_PICKER,
        SPIN_WHEEL,
        SPIN_WHEEL_RANDOM,
        WHEEL_SESSION,
        WHEEL_COMPLETE,
        WHEEL_HISTORY,
        GAME_HISTORY,
        THIS_OR_THAT_REPLAY,
        DESIRE_SYNC_REPLAY,
        HOW_WELL_REPLAY,
        DATE_MATCH,
        DATE_MATCHES,
        DATE_BUILDER,
        BUCKET_LIST,
        ACCOUNT,
        NOTIFICATIONS,
        PRIVACY,
        SUBSCRIPTION,
        RELATIONSHIP_SETTINGS,
        DELETE_ACCOUNT,
        SECURITY,
        CONNECTION_CHALLENGES,
        MEMORY_LANE,
        MEMORY_LANE_CAPSULE,
        WAITING_FOR_PARTNER,
        YOUR_PROGRESS
    )

    fun titleFor(route: String?): String? =
        definitions.firstOrNull { it.route == route }?.title

    fun answerReveal(questionId: String): String = "answer_reveal/${questionId.asRouteArg()}"

    fun conversation(coupleId: String, conversationId: String): String =
        "conversation/${coupleId.asRouteArg()}/${conversationId.asRouteArg()}"

    fun inviteConfirm(inviteCode: String): String = "invite_confirm/${inviteCode.asRouteArg()}"

    fun questionCategory(categoryId: String): String = "question_category/${categoryId.asRouteArg()}"

    fun spinWheel(categoryId: String): String = "spin_wheel/${categoryId.asRouteArg()}"

    fun wheelSession(sessionId: String): String = "wheel_session/${sessionId.asRouteArg()}"

    fun wheelComplete(sessionId: String): String = "wheel_complete/${sessionId.asRouteArg()}"

    fun thisOrThatReplay(sessionId: String): String = "this_or_that_replay/${sessionId.asRouteArg()}"

    fun desireSyncReplay(sessionId: String): String = "desire_sync_replay/${sessionId.asRouteArg()}"

    fun howWellReplay(sessionId: String): String = "how_well_replay/${sessionId.asRouteArg()}"

    fun questionThread(
        coupleId: String,
        questionId: String,
        prevId: String? = null,
        nextId: String? = null
    ): String {
        var route = "question_thread/${coupleId.asRouteArg()}/${questionId.asRouteArg()}"
        val params = buildList {
            prevId?.let { add("prevId=${it.asRouteArg()}") }
            nextId?.let { add("nextId=${it.asRouteArg()}") }
        }
        if (params.isNotEmpty()) route += "?" + params.joinToString("&")
        return route
    }

    private fun String.asRouteArg(): String = try {
        Uri.encode(this)
    } catch (e: NullPointerException) {
        // Uri.encode uses JNI on the JVM unit-test classpath where android.net.Uri is stubbed;
        // fallback to a safe path encoding for tests only.
        this.replace("/", "%2F").replace(" ", "%20")
    }
}
