/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package com.runicgateway.app.ui.navigation

import com.runicgateway.app.data.repository.ContentRepository

/**
 * Navigation destinations for the M1 public surface (PLAN.md §5). Routes are
 * plain strings for Navigation-Compose; argument-bearing routes expose a
 * `build(...)` helper so call sites never hand-format paths.
 */
object Routes {
    const val HOME = "home"
    const val NEWS = "news"
    const val WIKI = "wiki"
    const val CONTACT = "contact"

    /**
     * The News hub's NavHost pattern: [NEWS] plus an optional category, so a link
     * to one of the website's three category pages can land on the matching tab
     * (THEMING_AND_NAV.md §6.2). Navigating to plain [NEWS] matches this pattern
     * with no argument and opens the default tab, so every existing call site —
     * the drawer, [forStream] — is unaffected.
     *
     * Declared beside [NEWS] rather than replacing it because the two are used for
     * different things: this is what `composable()` and `destination.route` speak,
     * [NEWS] is what callers navigate to.
     */
    const val NEWS_ROUTE = "news?category={category}"

    /** Native login (§4.1) and the signed-in account surface (§5). */
    const val LOGIN = "login"
    const val ACCOUNT = "account"

    /** MFA management, reached from Account (TRUSTED_DEVICES_MFA.md). Signed-in only. */
    const val ACCOUNT_TRUSTED_DEVICES = "account/trusted-devices"
    const val ACCOUNT_RECOVERY_CODES = "account/recovery-codes"

    /** Opt-in push notification settings (§11, signed-in). */
    const val NOTIFICATIONS = "notifications"

    /** Public shard hub (§6.2). */
    const val SHARD = "shard"

    /** Shard boards, reachable from the hub. */
    const val SHARD_CHAMPS = "shard/champs"
    const val SHARD_GUILDS = "shard/guilds"
    const val SHARD_GOVERNORS = "shard/governors"
    const val SHARD_HOUSES = "shard/houses"

    /**
     * Protocol 3.0 shard content (M11), each gated by its own visibility feature. The
     * atlas is not under `shard/` on the wire (`/public/atlas`) because it is static
     * content rather than live state, but it is a peer of these in the app's nav.
     */
    const val SHARD_RULES = "shard/rules"
    const val SHARD_LEADERBOARDS = "shard/leaderboards"
    const val SHARD_MARKET = "shard/market"
    const val SHARD_MARKET_VENDOR = "shard/market/{serial}"
    const val ATLAS = "atlas"
    const val ATLAS_CREATURE = "atlas/{slug}"

    /** Player game-data groups (§6.3, player-only). Distinct from the public shard boards. */
    const val PLAYER_CHARACTERS = "player/characters"
    const val PLAYER_VENDORS = "player/vendors"
    const val PLAYER_HOUSES = "player/houses"

    /** A single character sheet by in-game (hex) serial. */
    const val PLAYER_CHAR = "player/char/{serial}"

    /** Staff operations (§1, §6.4, M10). Gated to staff roles by the menu access level;
     *  the backend re-checks role on every `/admin/…` call. */
    const val ADMIN_DASHBOARD = "admin/dashboard"
    const val ADMIN_MODERATION = "admin/moderation"
    const val ADMIN_SUPPORT = "admin/support"
    const val ADMIN_CONTENT = "admin/content"

    /** CMS page by slug (e.g. the conventional "about" page, mirrored from the site nav). */
    const val PAGE = "page/{slug}"

    /** News post detail by category + id-or-slug. */
    const val POST = "news/{category}/{idOrSlug}"

    /** Wiki page detail by slug. */
    const val WIKI_PAGE = "wiki/{slug}"

    object Args {
        const val SLUG = "slug"
        const val CATEGORY = "category"
        const val ID_OR_SLUG = "idOrSlug"
        const val SERIAL = "serial"
    }

    fun page(slug: String) = "page/$slug"
    fun post(categoryUrlSlug: String, idOrSlug: String) = "news/$categoryUrlSlug/$idOrSlug"

    /**
     * The News hub with [category] preselected. Takes the enum rather than a slug
     * so an unmapped category cannot reach the NavHost — the screen's tabs are the
     * enum's entries, and a slug it doesn't know would select nothing.
     */
    fun news(category: ContentRepository.PostCategory) = "news?category=${category.urlSlug}"
    fun wikiPage(slug: String) = "wiki/$slug"

    /** The character-sheet route for an in-game serial (e.g. "0x24C"). */
    fun playerChar(serial: String) = "player/char/$serial"

    /** One player vendor's shop, by in-game (hex) serial. */
    fun marketVendor(serial: String) = "shard/market/$serial"

    /** One creature's atlas page, by slug. */
    fun atlasCreature(slug: String) = "atlas/$slug"

    /**
     * The in-app destination a tapped push notification deep-links to (§11, M7
     * Part 2 work item 7). Maps a stream id to the screen that shows its content;
     * unknown streams land on Home. Personal streams route to the player groups
     * (a signed-out/demoted tap is caught by [com.runicgateway.app.ui.PlayerGate]).
     */
    fun forStream(streamId: String): String = when (streamId) {
        com.runicgateway.app.core.push.PushStreams.NEWS_POST -> NEWS
        com.runicgateway.app.core.push.PushStreams.SERVER_STATUS,
        com.runicgateway.app.core.push.PushStreams.CHAMP_START,
        com.runicgateway.app.core.push.PushStreams.IDOC_WARNING,
        com.runicgateway.app.core.push.PushStreams.GOVERNOR_ELECTION,
        -> SHARD
        com.runicgateway.app.core.push.PushStreams.VENDOR_SALE -> PLAYER_VENDORS
        com.runicgateway.app.core.push.PushStreams.HOUSE_IDOC -> PLAYER_HOUSES
        com.runicgateway.app.core.push.PushStreams.ACCOUNT_LOGIN -> ACCOUNT
        else -> HOME
    }
}
