package com.fieldlabel.collector.ui.navigation

import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.History
import androidx.compose.material.icons.filled.Map
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.fieldlabel.collector.ui.screens.*
import java.net.URLDecoder
import java.net.URLEncoder
import java.nio.charset.StandardCharsets

sealed class Screen(val route: String, val label: String) {
    object Collection : Screen("collection", "採集入力")
    object History    : Screen("history",    "地点情報")
    object Settings   : Screen("settings",   "設定")
    object Preview    : Screen("preview/{recordId}", "印刷プレビュー") {
        fun createRoute(id: String) = "preview/$id"
    }
    object AllLocationsMap: Screen("all_locations_map", "マップ")
    object PrinterScan   : Screen("printer_scan", "プリンター選択")
    object PrintSettings  : Screen("print_settings",  "印刷設定")
    object PrivacyPolicy  : Screen("privacy_policy",  "プライバシーポリシー")
    object VoiceManual    : Screen("voice_manual",     "音声コマンド一覧")
    object LocationDetail : Screen("location_detail/{locationId}", "地点詳細") {
        fun createRoute(id: String) = "location_detail/$id"
    }
    object RouteLogList : Screen("route_log_list", "ルートログ")
    object RouteMap     : Screen("route_map/{routeLogId}", "ルートマップ") {
        fun createRoute(id: String) = "route_map/$id"
    }
    object MediaPreview : Screen(
        "media_preview?filePath={filePath}&mediaType={mediaType}&locationId={locationId}&specimenId={specimenId}",
        "メディアプレビュー"
    ) {
        fun createRoute(
            filePath: String,
            mediaType: String,
            locationId: String = "",
            specimenId: String = ""
        ): String {
            val encodedPath = URLEncoder.encode(filePath, StandardCharsets.UTF_8.toString())
            return "media_preview?filePath=$encodedPath&mediaType=$mediaType" +
                   "&locationId=$locationId&specimenId=$specimenId"
        }
    }
}

@Composable
fun AppNavigation() {
    val navController = rememberNavController()

    val bottomItems = listOf(Screen.Collection, Screen.History, Screen.AllLocationsMap, Screen.Settings)

    Scaffold(
        bottomBar = {
            val navBackStack by navController.currentBackStackEntryAsState()
            val current = navBackStack?.destination
            NavigationBar {
                bottomItems.forEach { screen ->
                    NavigationBarItem(
                        selected = current?.hierarchy?.any { it.route == screen.route } == true,
                        onClick  = {
                            navController.navigate(screen.route) {
                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                launchSingleTop = true
                                restoreState    = true
                            }
                        },
                        icon  = {
                            when (screen) {
                                Screen.Collection      -> Icon(Icons.Default.Add,     "採集")
                                Screen.History         -> Icon(Icons.Default.History,  "履歴")
                                Screen.AllLocationsMap -> Icon(Icons.Default.Map,      "マップ")
                                Screen.Settings        -> Icon(Icons.Default.Settings, "設定")
                                else -> {}
                            }
                        },
                        label = { Text(screen.label) }
                    )
                }
            }
        }
    ) { innerPadding ->
        NavHost(
            navController    = navController,
            startDestination = Screen.Collection.route,
            // 各画面のコンテンツがボトムナビゲーションバーの裏に潜らないよう
            // NavHost 全体の描画領域を下部メニューより上に制限する
            modifier         = Modifier.padding(
                bottom = innerPadding.calculateBottomPadding()
            )
        ) {
            composable(Screen.Collection.route) {
                CollectionFormScreen(
                    onNavigateToPreview = { id ->
                        navController.navigate(Screen.Preview.createRoute(id))
                    },
                    onNavigateToMediaPreview = { filePath, mediaType, locationId, specimenId ->
                        navController.navigate(Screen.MediaPreview.createRoute(filePath, mediaType, locationId, specimenId ?: ""))
                    }
                )
            }
            composable(Screen.History.route) {
                HistoryScreen(
                    onNavigateToPreview = { id ->
                        navController.navigate(Screen.Preview.createRoute(id))
                    },
                    onNavigateToDetail = { locationId ->
                        navController.navigate(Screen.LocationDetail.createRoute(locationId))
                    }
                )
            }
            composable(Screen.Settings.route) {
                SettingsScreen(
                    onNavigateToPrinterScan = {
                        navController.navigate(Screen.PrinterScan.route)
                    },
                    onNavigateToPrintSettings = {
                        navController.navigate(Screen.PrintSettings.route)
                    },
                    onNavigateToPrivacyPolicy = {
                        navController.navigate(Screen.PrivacyPolicy.route)
                    },
                    onNavigateToVoiceManual = {
                        navController.navigate(Screen.VoiceManual.route)
                    }
                )
            }
            composable(Screen.Preview.route) { backStack ->
                val recordId = backStack.arguments?.getString("recordId") ?: ""
                LabelPreviewScreen(
                    recordId  = recordId,
                    onBack    = { navController.popBackStack() }
                )
            }
            composable(Screen.AllLocationsMap.route) {
                AllLocationsMapScreen(
                    onNavigateToDetail = { locationId ->
                        // Switch to the 地点情報 tab (saving map state so Map tab restores it)
                        navController.navigate(Screen.History.route) {
                            popUpTo(navController.graph.findStartDestination().id) {
                                saveState = true
                            }
                            launchSingleTop = true
                            restoreState    = true
                        }
                        // Then push LocationDetail on top of the History stack
                        navController.navigate(Screen.LocationDetail.createRoute(locationId))
                    },
                    onNavigateToRouteLogList = {
                        navController.navigate(Screen.RouteLogList.route)
                    }
                )
            }
            composable(Screen.RouteLogList.route) {
                RouteLogListScreen(
                    onNavigateBack  = { navController.popBackStack() },
                    onNavigateToMap = { routeLogId ->
                        navController.navigate(Screen.RouteMap.createRoute(routeLogId))
                    }
                )
            }
            composable(
                route     = Screen.RouteMap.route,
                arguments = listOf(
                    navArgument("routeLogId") { type = NavType.StringType; defaultValue = "" }
                )
            ) { backStack ->
                val routeLogId = backStack.arguments?.getString("routeLogId") ?: ""
                RouteMapScreen(
                    routeLogId     = routeLogId,
                    onNavigateBack = { navController.popBackStack() }
                )
            }
            composable(Screen.PrinterScan.route) {
                PrinterScanScreen(
                    onBack = { navController.popBackStack() }
                )
            }
            composable(Screen.PrintSettings.route) {
                PrintSettingsScreen(
                    onNavigateBack = { navController.popBackStack() },
                    onNavigateToPrinterScan = {
                        navController.navigate(Screen.PrinterScan.route)
                    }
                )
            }
            composable(Screen.PrivacyPolicy.route) {
                PrivacyPolicyScreen(
                    onNavigateBack = { navController.popBackStack() }
                )
            }
            composable(Screen.VoiceManual.route) {
                VoiceManualScreen(
                    onNavigateBack = { navController.popBackStack() }
                )
            }
            composable(Screen.LocationDetail.route) {
                LocationDetailScreen(
                    onNavigateBack = { navController.popBackStack() },
                    onNavigateToPreview = { id ->
                        navController.navigate(Screen.Preview.createRoute(id))
                    },
                    onNavigateToMediaPreview = { filePath, mediaType, locationId, specimenId ->
                        navController.navigate(Screen.MediaPreview.createRoute(filePath, mediaType, locationId, specimenId ?: ""))
                    }
                )
            }
            composable(
                route = Screen.MediaPreview.route,
                arguments = listOf(
                    navArgument("filePath")   { type = NavType.StringType; defaultValue = "" },
                    navArgument("mediaType")  { type = NavType.StringType; defaultValue = "photo" },
                    navArgument("locationId") { type = NavType.StringType; defaultValue = "" },
                    navArgument("specimenId") { type = NavType.StringType; defaultValue = "" }
                )
            ) { backStack ->
                val filePath  = URLDecoder.decode(
                    backStack.arguments?.getString("filePath") ?: "",
                    StandardCharsets.UTF_8.toString()
                )
                val mediaType = backStack.arguments?.getString("mediaType") ?: "photo"
                MediaPreviewScreen(
                    filePath  = filePath,
                    mediaType = mediaType,
                    onBack    = { navController.popBackStack() }
                )
            }
        }
    }
}
