package com.fieldlabel.collector.ui.screens

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.fieldlabel.collector.domain.model.CustomFieldDef
import com.fieldlabel.collector.ui.viewmodel.SettingsViewModel

// ─────────────────────────────────────────────────────────────────────────────
// SettingsScreen — ツリー構造の設定トップページ
// ─────────────────────────────────────────────────────────────────────────────

@Composable
fun SettingsScreen(
    onNavigateToPrinterScan:   () -> Unit,
    onNavigateToPrintSettings: () -> Unit = {},
    onNavigateToPrivacyPolicy: () -> Unit = {},
    onNavigateToVoiceManual:   () -> Unit = {},
    viewModel: SettingsViewModel = hiltViewModel()
) {
    val collectorName    by viewModel.collectorName   .collectAsState()
    val mapTileSource    by viewModel.mapTileSource   .collectAsState()
    val mapPinStyle      by viewModel.mapPinStyle     .collectAsState()
    val showThumbnails   by viewModel.showThumbnails  .collectAsState()
    val customFieldDefs  by viewModel.allCustomFieldDefs.collectAsState()
    val locIdPrefix             by viewModel.locIdPrefix            .collectAsState()
    val locIdSeparator          by viewModel.locIdSeparator         .collectAsState()
    val locIdIncludeYear        by viewModel.locIdIncludeYear       .collectAsState()
    val locIdYearDigits         by viewModel.locIdYearDigits        .collectAsState()
    val locIdCounterDigits      by viewModel.locIdCounterDigits     .collectAsState()
    val locIdCounterResetYearly by viewModel.locIdCounterResetYearly.collectAsState()
    // ハンズフリー設定
    val hfEnabled         by viewModel.hfEnabled        .collectAsState()
    val hfScreenLock      by viewModel.hfScreenLock     .collectAsState()
    val hfVoiceResponse   by viewModel.hfVoiceResponse  .collectAsState()
    val hfWakeWord        by viewModel.hfWakeWord       .collectAsState()
    val hfLanguage        by viewModel.hfLanguage       .collectAsState()
    val hfRequireWakeWord by viewModel.hfRequireWakeWord.collectAsState()

    var nameField       by remember(collectorName) { mutableStateOf(collectorName) }
    var locPrefixDraft  by remember(locIdPrefix)   { mutableStateOf(locIdPrefix) }
    var wakeWordDraft   by remember(hfWakeWord)    { mutableStateOf(hfWakeWord) }

    // セクションの開閉状態
    var locIdExpanded      by remember { mutableStateOf(false) }
    var mapExpanded        by remember { mutableStateOf(false) }
    var hfExpanded         by remember { mutableStateOf(false) }
    var customFieldExpanded by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .navigationBarsPadding()
            .imePadding()
            .padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 96.dp),
        verticalArrangement = Arrangement.spacedBy(0.dp)
    ) {
        Text("設定", style = MaterialTheme.typography.headlineSmall,
            modifier = Modifier.padding(bottom = 16.dp))

        // ── 採集者名 ──────────────────────────────────────────────────────────
        SectionHeader("採集者名", Icons.Default.Person)
        Column(
            modifier = Modifier.padding(start = 16.dp, end = 0.dp, bottom = 8.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            OutlinedTextField(
                value = nameField, onValueChange = { nameField = it },
                label = { Text("デフォルト採集者名") },
                leadingIcon = { Icon(Icons.Default.Person, null) },
                singleLine = true, modifier = Modifier.fillMaxWidth()
            )
            Button(
                onClick  = { viewModel.saveCollectorName(nameField) },
                enabled  = nameField.isNotBlank() && nameField != collectorName,
                modifier = Modifier.fillMaxWidth()
            ) { Text("採集者名を保存") }
        }

        HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))

        // ── 印刷設定（サブページへナビゲーション） ────────────────────────────
        NavigationRow(
            icon  = Icons.Default.Print,
            title = "印刷設定",
            subtitle = "プリンター・テープ幅・レイアウト・表示項目",
            onClick = onNavigateToPrintSettings
        )

        HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))

        // ── 地点ID命名規則（展開式） ──────────────────────────────────────────
        ExpandableSectionHeader(
            icon     = Icons.Default.Tag,
            title    = "地点ID命名規則",
            subtitle = run {
                val pfx = locIdPrefix.ifBlank { "LOC" }
                val sep = locIdSeparator
                val cnt = "1".padStart(locIdCounterDigits, '0')
                val yr  = if (locIdIncludeYear) {
                    val y = java.time.Year.now().value
                    (if (locIdYearDigits == "YY") (y % 100).toString().padStart(2, '0') else y.toString())
                } else null
                "例: " + if (yr != null) "$pfx$sep$yr$sep$cnt" else "$pfx$sep$cnt"
            },
            expanded = locIdExpanded,
            onToggle = { locIdExpanded = !locIdExpanded }
        )
        if (locIdExpanded) {
            LocIdSection(
                locPrefixDraft         = locPrefixDraft,
                onPrefixDraftChange    = { locPrefixDraft = it },
                locIdPrefix            = locIdPrefix,
                locIdSeparator         = locIdSeparator,
                locIdIncludeYear       = locIdIncludeYear,
                locIdYearDigits        = locIdYearDigits,
                locIdCounterDigits     = locIdCounterDigits,
                locIdCounterResetYearly = locIdCounterResetYearly,
                viewModel              = viewModel
            )
        }

        HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))

        // ── マップ設定（展開式） ───────────────────────────────────────────────
        ExpandableSectionHeader(
            icon     = Icons.Default.Map,
            title    = "マップ設定",
            subtitle = "${tileSourceLabel(mapTileSource)} · ${pinStyleLabel(mapPinStyle)}",
            expanded = mapExpanded,
            onToggle = { mapExpanded = !mapExpanded }
        )
        if (mapExpanded) {
            MapSettingsSection(
                mapTileSource    = mapTileSource,
                mapPinStyle      = mapPinStyle,
                showThumbnails   = showThumbnails,
                onTileSource     = { viewModel.saveMapTileSource(it) },
                onPinStyle       = { viewModel.saveMapPinStyle(it) },
                onShowThumbnails = { viewModel.saveShowThumbnails(it) }
            )
        }

        HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))

        // ── ハンズフリー設定（展開式） ─────────────────────────────────────────
        ExpandableSectionHeader(
            icon     = Icons.Default.Mic,
            title    = "ハンズフリー",
            subtitle = if (hfEnabled) {
                val langLabel = if (hfLanguage == "ja") "日本語" else "English"
                val wakeLabel = if (hfRequireWakeWord) "ウェイクワード: $hfWakeWord" else "ウェイクワード不要"
                "有効 · $langLabel · $wakeLabel"
            } else "無効",
            expanded = hfExpanded,
            onToggle = { hfExpanded = !hfExpanded }
        )
        if (hfExpanded) {
            HfSettingsSection(
                hfEnabled         = hfEnabled,
                hfScreenLock      = hfScreenLock,
                hfVoiceResponse   = hfVoiceResponse,
                hfWakeWord        = hfWakeWord,
                hfRequireWakeWord = hfRequireWakeWord,
                wakeWordDraft     = wakeWordDraft,
                hfLanguage        = hfLanguage,
                onWakeWordDraftChange = { wakeWordDraft = it },
                onNavigateToVoiceManual = onNavigateToVoiceManual,
                viewModel         = viewModel
            )
        }

        HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))

        // ── カスタムフィールド（値）設定（展開式） ────────────────────────────
        ExpandableSectionHeader(
            icon     = Icons.Default.Tune,
            title    = "値（カスタムフィールド）",
            subtitle = if (customFieldDefs.isEmpty()) "未設定" else "${customFieldDefs.size} 件のフィールド定義",
            expanded = customFieldExpanded,
            onToggle = { customFieldExpanded = !customFieldExpanded }
        )
        if (customFieldExpanded) {
            CustomFieldsSection(
                defs      = customFieldDefs,
                onAdd     = { label, unit, valueType, appliesTo ->
                    viewModel.addCustomFieldDef(label, unit, valueType, appliesTo)
                },
                onDelete  = { viewModel.deleteCustomFieldDef(it) },
                onUpdate  = { viewModel.updateCustomFieldDef(it) }
            )
        }

        HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))

        // ── アプリ情報 ────────────────────────────────────────────────────────
        NavigationRow(
            icon     = Icons.Default.PrivacyTip,
            title    = "プライバシーポリシー",
            subtitle = "データの取り扱いについて",
            onClick  = onNavigateToPrivacyPolicy
        )
    }
}

// ─────────────────────────────────────────────────────────────────────────────
// 共通コンポーネント
// ─────────────────────────────────────────────────────────────────────────────

@Composable
private fun SectionHeader(title: String, icon: ImageVector) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 8.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(10.dp)
    ) {
        Icon(icon, null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(20.dp))
        Text(title, style = MaterialTheme.typography.titleMedium,
            color = MaterialTheme.colorScheme.primary)
    }
}

@Composable
private fun NavigationRow(
    icon: ImageVector,
    title: String,
    subtitle: String,
    onClick: () -> Unit
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick)
            .padding(vertical = 12.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Icon(icon, null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(22.dp))
        Column(modifier = Modifier.weight(1f)) {
            Text(title, style = MaterialTheme.typography.titleMedium)
            Text(subtitle, style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.outline)
        }
        Icon(Icons.Default.ChevronRight, null,
            tint = MaterialTheme.colorScheme.outline, modifier = Modifier.size(20.dp))
    }
}

@Composable
private fun ExpandableSectionHeader(
    icon: ImageVector,
    title: String,
    subtitle: String,
    expanded: Boolean,
    onToggle: () -> Unit
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onToggle)
            .padding(vertical = 12.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Icon(icon, null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(22.dp))
        Column(modifier = Modifier.weight(1f)) {
            Text(title, style = MaterialTheme.typography.titleMedium)
            Text(subtitle, style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.outline)
        }
        Icon(
            if (expanded) Icons.Default.ExpandLess else Icons.Default.ExpandMore,
            null, tint = MaterialTheme.colorScheme.outline, modifier = Modifier.size(20.dp)
        )
    }
}

// ─────────────────────────────────────────────────────────────────────────────
// 地点ID命名規則セクション
// ─────────────────────────────────────────────────────────────────────────────

@Composable
private fun LocIdSection(
    locPrefixDraft: String,
    onPrefixDraftChange: (String) -> Unit,
    locIdPrefix: String,
    locIdSeparator: String,
    locIdIncludeYear: Boolean,
    locIdYearDigits: String,
    locIdCounterDigits: Int,
    locIdCounterResetYearly: Boolean,
    viewModel: SettingsViewModel
) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(start = 16.dp, bottom = 12.dp),
        verticalArrangement = Arrangement.spacedBy(10.dp)
    ) {
        OutlinedTextField(
            value = locPrefixDraft, onValueChange = onPrefixDraftChange,
            label = { Text("プレフィックス") }, singleLine = true,
            modifier = Modifier.fillMaxWidth(),
            supportingText = { Text("空白の場合は「LOC」が使用されます") }
        )
        Button(
            onClick  = { viewModel.saveLocIdPrefix(locPrefixDraft) },
            enabled  = locPrefixDraft != locIdPrefix,
            modifier = Modifier.fillMaxWidth()
        ) { Text("プレフィックスを保存") }

        Text("区切り文字", style = MaterialTheme.typography.labelMedium,
            color = MaterialTheme.colorScheme.outline)
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) {
            listOf("-" to "ハイフン", "_" to "アンスコ", "." to "ドット", "" to "なし").forEach { (sep, label) ->
                FilterChip(selected = locIdSeparator == sep, onClick = { viewModel.saveLocIdSeparator(sep) },
                    label = { Text(label, style = MaterialTheme.typography.bodySmall) })
            }
        }

        Row(modifier = Modifier.fillMaxWidth().clickable { viewModel.saveLocIdIncludeYear(!locIdIncludeYear) }
                .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically) {
            Text("年を含む", modifier = Modifier.weight(1f))
            Switch(checked = locIdIncludeYear, onCheckedChange = { viewModel.saveLocIdIncludeYear(it) })
        }

        if (locIdIncludeYear) {
            Text("年の形式", style = MaterialTheme.typography.labelMedium,
                color = MaterialTheme.colorScheme.outline)
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                listOf("YYYY" to "4桁 (2026)", "YY" to "2桁 (26)").forEach { (fmt, label) ->
                    FilterChip(selected = locIdYearDigits == fmt, onClick = { viewModel.saveLocIdYearDigits(fmt) },
                        label = { Text(label, style = MaterialTheme.typography.bodySmall) })
                }
            }
            Row(modifier = Modifier.fillMaxWidth()
                    .clickable { viewModel.saveLocIdCounterResetYearly(!locIdCounterResetYearly) }
                    .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically) {
                Column(modifier = Modifier.weight(1f)) {
                    Text("年ごとにカウンターをリセット")
                    Text("オフの場合は通算カウント", style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.outline)
                }
                Switch(checked = locIdCounterResetYearly, onCheckedChange = { viewModel.saveLocIdCounterResetYearly(it) })
            }
        }

        Text("カウンター桁数", style = MaterialTheme.typography.labelMedium,
            color = MaterialTheme.colorScheme.outline)
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            listOf(3 to "3桁 (001)", 4 to "4桁 (0001)", 5 to "5桁 (00001)").forEach { (digits, label) ->
                FilterChip(selected = locIdCounterDigits == digits,
                    onClick = { viewModel.saveLocIdCounterDigits(digits) },
                    label = { Text(label, style = MaterialTheme.typography.bodySmall) })
            }
        }

        // ライブプレビュー
        val locPreviewYear = remember { java.time.Year.now().value }
        val pfx = locIdPrefix.ifBlank { "LOC" }
        val sep = locIdSeparator
        val yr  = if (locIdYearDigits == "YY") (locPreviewYear % 100).toString().padStart(2, '0')
                  else locPreviewYear.toString()
        val cnt = "1".padStart(locIdCounterDigits, '0')
        val locPreviewId = if (locIdIncludeYear) "$pfx$sep$yr$sep$cnt" else "$pfx$sep$cnt"

        Card(colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.secondaryContainer),
            modifier = Modifier.fillMaxWidth()
        ) {
            Column(modifier = Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(2.dp)) {
                Text("プレビュー（次に採番される地点ID）",
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.7f))
                Text(locPreviewId, style = MaterialTheme.typography.titleMedium,
                    color = MaterialTheme.colorScheme.onSecondaryContainer)
                Text("標本ID: $locPreviewId${sep}01",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.7f))
            }
        }
    }
}

// ─────────────────────────────────────────────────────────────────────────────
// マップ設定セクション
// ─────────────────────────────────────────────────────────────────────────────

@Composable
private fun MapSettingsSection(
    mapTileSource: String,
    mapPinStyle: String,
    showThumbnails: Boolean,
    onTileSource: (String) -> Unit,
    onPinStyle: (String) -> Unit,
    onShowThumbnails: (Boolean) -> Unit
) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(start = 16.dp, bottom = 12.dp),
        verticalArrangement = Arrangement.spacedBy(10.dp)
    ) {
        // 地図スタイル
        Text("地図スタイル", style = MaterialTheme.typography.labelMedium,
            color = MaterialTheme.colorScheme.outline)
        Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
            listOf(
                "MAPNIK"    to ("標準地図"   to "CartoDB Voyager（全世界対応）"),
                "TOPO"      to ("地理院標準" to "国土地理院 標準地図（日本）"),
                "SATELLITE" to ("地理院空中写真" to "国土地理院 シームレス空中写真（日本）")
            ).forEach { (key, labels) ->
                val (title, desc) = labels
                Surface(
                    shape = MaterialTheme.shapes.small,
                    color = if (mapTileSource == key)
                        MaterialTheme.colorScheme.primaryContainer
                    else
                        MaterialTheme.colorScheme.surfaceVariant,
                    modifier = Modifier.fillMaxWidth().clickable { onTileSource(key) }
                ) {
                    Row(
                        modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.spacedBy(10.dp)
                    ) {
                        RadioButton(selected = mapTileSource == key, onClick = { onTileSource(key) })
                        Column(modifier = Modifier.weight(1f)) {
                            Text(title, style = MaterialTheme.typography.bodyMedium)
                            Text(desc, style = MaterialTheme.typography.bodySmall,
                                color = MaterialTheme.colorScheme.outline)
                        }
                    }
                }
            }
        }

        // ピンスタイル
        Text("ピンスタイル", style = MaterialTheme.typography.labelMedium,
            color = MaterialTheme.colorScheme.outline)
        Row(
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            modifier = Modifier.fillMaxWidth()
        ) {
            listOf(
                "default" to "標準ピン",
                "circle"  to "丸",
                "star"    to "星形",
                "diamond" to "ひし形"
            ).forEach { (key, label) ->
                FilterChip(
                    selected = mapPinStyle == key,
                    onClick  = { onPinStyle(key) },
                    label    = { Text(label, style = MaterialTheme.typography.bodySmall) },
                    modifier = Modifier.weight(1f)
                )
            }
        }

        // サムネイル表示
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { onShowThumbnails(!showThumbnails) }
                .padding(vertical = 4.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Column(modifier = Modifier.weight(1f)) {
                Text("地点一覧にサムネイル表示", style = MaterialTheme.typography.bodyMedium)
                Text("地点情報・採集入力ページで写真サムネイルを表示する",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.outline)
            }
            Switch(checked = showThumbnails, onCheckedChange = onShowThumbnails)
        }
    }
}

// ─────────────────────────────────────────────────────────────────────────────
// ハンズフリー設定セクション
// ─────────────────────────────────────────────────────────────────────────────

@Composable
private fun HfSettingsSection(
    hfEnabled: Boolean,
    hfScreenLock: Boolean,
    hfVoiceResponse: Boolean,
    hfWakeWord: String,
    hfRequireWakeWord: Boolean,
    wakeWordDraft: String,
    hfLanguage: String,
    onWakeWordDraftChange: (String) -> Unit,
    onNavigateToVoiceManual: () -> Unit,
    viewModel: SettingsViewModel
) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(start = 16.dp, bottom = 12.dp),
        verticalArrangement = Arrangement.spacedBy(10.dp)
    ) {
        // ハンズフリー有効/無効
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { viewModel.saveHfEnabled(!hfEnabled) }
                .padding(vertical = 4.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Column(modifier = Modifier.weight(1f)) {
                Text("ハンズフリーモード", style = MaterialTheme.typography.bodyMedium)
                Text("採集入力ページにハンズフリーボタンを表示する",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.outline)
            }
            Switch(checked = hfEnabled, onCheckedChange = { viewModel.saveHfEnabled(it) })
        }

        if (hfEnabled) {
            HorizontalDivider()

            // 画面操作ロック
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable { viewModel.saveHfScreenLock(!hfScreenLock) }
                    .padding(vertical = 4.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Column(modifier = Modifier.weight(1f)) {
                    Text("ハンズフリー中の画面ロック", style = MaterialTheme.typography.bodyMedium)
                    Text("長押しで解除できるタッチロックオーバーレイを表示する",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.outline)
                }
                Switch(checked = hfScreenLock, onCheckedChange = { viewModel.saveHfScreenLock(it) })
            }

            // 音声応答
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable { viewModel.saveHfVoiceResponse(!hfVoiceResponse) }
                    .padding(vertical = 4.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Column(modifier = Modifier.weight(1f)) {
                    Text("音声フィードバック", style = MaterialTheme.typography.bodyMedium)
                    Text("操作結果を音声で読み上げる",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.outline)
                }
                Switch(checked = hfVoiceResponse, onCheckedChange = { viewModel.saveHfVoiceResponse(it) })
            }

            HorizontalDivider()

            // ウェイクワード要求 ON/OFF
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable { viewModel.saveHfRequireWakeWord(!hfRequireWakeWord) }
                    .padding(vertical = 4.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Column(modifier = Modifier.weight(1f)) {
                    Text("ウェイクワードを要求する", style = MaterialTheme.typography.bodyMedium)
                    Text("オフにするとコマンドを直接認識します",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.outline)
                }
                Switch(
                    checked = hfRequireWakeWord,
                    onCheckedChange = { viewModel.saveHfRequireWakeWord(it) }
                )
            }

            // ウェイクワード設定（要求する場合のみ表示）
            if (hfRequireWakeWord) {
                Text("ウェイクワード", style = MaterialTheme.typography.labelMedium,
                    color = MaterialTheme.colorScheme.outline)
                OutlinedTextField(
                    value = wakeWordDraft,
                    onValueChange = onWakeWordDraftChange,
                    label = { Text("ウェイクワード") },
                    leadingIcon = { Icon(Icons.Default.Mic, null) },
                    singleLine = true,
                    modifier = Modifier.fillMaxWidth(),
                    supportingText = { Text("例: れこちゃん / hey recorder") }
                )
                Button(
                    onClick  = { viewModel.saveHfWakeWord(wakeWordDraft) },
                    enabled  = wakeWordDraft.isNotBlank() && wakeWordDraft != hfWakeWord,
                    modifier = Modifier.fillMaxWidth()
                ) { Text("ウェイクワードを保存") }
            }

            HorizontalDivider()

            // 音声認識言語
            Text("音声エンジン言語", style = MaterialTheme.typography.labelMedium,
                color = MaterialTheme.colorScheme.outline)
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                listOf("ja" to "日本語", "en" to "English").forEach { (code, label) ->
                    FilterChip(
                        selected = hfLanguage == code,
                        onClick  = { viewModel.saveHfLanguage(code) },
                        label    = { Text(label) }
                    )
                }
            }

            HorizontalDivider()

            // 音声コマンドマニュアルへのリンク
            NavigationRow(
                icon     = Icons.Default.MenuBook,
                title    = "音声コマンド一覧",
                subtitle = "利用可能な音声コマンドを確認する",
                onClick  = onNavigateToVoiceManual
            )
        }
    }
}

// ─────────────────────────────────────────────────────────────────────────────
// ユーティリティ
// ─────────────────────────────────────────────────────────────────────────────

// ─────────────────────────────────────────────────────────────────────────────
// カスタムフィールドセクション
// ─────────────────────────────────────────────────────────────────────────────

@Composable
private fun CustomFieldsSection(
    defs: List<CustomFieldDef>,
    onAdd: (label: String, unit: String, valueType: String, appliesTo: String) -> Unit,
    onDelete: (CustomFieldDef) -> Unit,
    onUpdate: (CustomFieldDef) -> Unit
) {
    var showAddDialog    by remember { mutableStateOf(false) }
    var editingDef       by remember { mutableStateOf<CustomFieldDef?>(null) }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(start = 16.dp, bottom = 12.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Text(
            "標本や地点に自由な数値・テキスト値を記録できます。ラベルと単位を設定し、地点または標本に紐づけます。",
            style = MaterialTheme.typography.bodySmall,
            color = MaterialTheme.colorScheme.outline
        )

        if (defs.isEmpty()) {
            Text("フィールドがまだ定義されていません",
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.outline,
                modifier = Modifier.padding(vertical = 8.dp))
        } else {
            defs.forEach { def ->
                Card(
                    modifier = Modifier.fillMaxWidth(),
                    colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant)
                ) {
                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(horizontal = 12.dp, vertical = 8.dp),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Column(modifier = Modifier.weight(1f)) {
                            Text(def.displayLabel, style = MaterialTheme.typography.bodyMedium)
                            Text(
                                buildString {
                                    append(if (def.valueType == "number") "数値" else "テキスト")
                                    append(" · ")
                                    append(appliesToLabel(def.appliesTo))
                                },
                                style = MaterialTheme.typography.bodySmall,
                                color = MaterialTheme.colorScheme.outline
                            )
                        }
                        IconButton(onClick = { editingDef = def }) {
                            Icon(Icons.Default.Edit, "編集", modifier = Modifier.size(18.dp))
                        }
                        IconButton(onClick = { onDelete(def) }) {
                            Icon(Icons.Default.Delete, "削除",
                                tint = MaterialTheme.colorScheme.error,
                                modifier = Modifier.size(18.dp))
                        }
                    }
                }
            }
        }

        OutlinedButton(
            onClick = { showAddDialog = true },
            modifier = Modifier.fillMaxWidth()
        ) {
            Icon(Icons.Default.Add, null, modifier = Modifier.size(16.dp))
            Spacer(Modifier.width(4.dp))
            Text("フィールドを追加")
        }
    }

    // 追加ダイアログ
    if (showAddDialog) {
        CustomFieldEditDialog(
            initial   = null,
            onConfirm = { label, unit, valueType, appliesTo ->
                onAdd(label, unit, valueType, appliesTo)
                showAddDialog = false
            },
            onDismiss = { showAddDialog = false }
        )
    }

    // 編集ダイアログ
    editingDef?.let { def ->
        CustomFieldEditDialog(
            initial   = def,
            onConfirm = { label, unit, valueType, appliesTo ->
                onUpdate(def.copy(label = label, unit = unit, valueType = valueType, appliesTo = appliesTo))
                editingDef = null
            },
            onDismiss = { editingDef = null }
        )
    }
}

@Composable
private fun CustomFieldEditDialog(
    initial: CustomFieldDef?,
    onConfirm: (label: String, unit: String, valueType: String, appliesTo: String) -> Unit,
    onDismiss: () -> Unit
) {
    var label     by remember { mutableStateOf(initial?.label     ?: "") }
    var unit      by remember { mutableStateOf(initial?.unit      ?: "") }
    var valueType by remember { mutableStateOf(initial?.valueType ?: "number") }
    var appliesTo by remember { mutableStateOf(initial?.appliesTo ?: "specimen") }

    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text(if (initial == null) "フィールドを追加" else "フィールドを編集") },
        text = {
            Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
                OutlinedTextField(
                    value = label, onValueChange = { label = it },
                    label = { Text("フィールド名") },
                    placeholder = { Text("例: 体重, 翼長") },
                    singleLine = true, modifier = Modifier.fillMaxWidth()
                )
                OutlinedTextField(
                    value = unit, onValueChange = { unit = it },
                    label = { Text("単位（省略可）") },
                    placeholder = { Text("例: g, mm, ℃") },
                    singleLine = true, modifier = Modifier.fillMaxWidth()
                )
                Text("値の種類", style = MaterialTheme.typography.labelMedium,
                    color = MaterialTheme.colorScheme.outline)
                Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                    listOf("number" to "数値", "text" to "テキスト").forEach { (key, lbl) ->
                        FilterChip(selected = valueType == key, onClick = { valueType = key },
                            label = { Text(lbl) })
                    }
                }
                Text("適用先", style = MaterialTheme.typography.labelMedium,
                    color = MaterialTheme.colorScheme.outline)
                Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                    listOf("specimen" to "標本", "location" to "地点", "both" to "両方").forEach { (key, lbl) ->
                        FilterChip(selected = appliesTo == key, onClick = { appliesTo = key },
                            label = { Text(lbl) })
                    }
                }
            }
        },
        confirmButton = {
            TextButton(
                onClick = { if (label.isNotBlank()) onConfirm(label, unit, valueType, appliesTo) },
                enabled = label.isNotBlank()
            ) { Text("保存") }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) { Text("キャンセル") }
        }
    )
}

private fun appliesToLabel(key: String) = when (key) {
    "specimen" -> "標本ごと"
    "location" -> "地点ごと"
    "both"     -> "標本・地点"
    else       -> key
}

private fun tileSourceLabel(key: String) = when (key) {
    "TOPO"      -> "地理院標準"
    "SATELLITE" -> "地理院空中写真"
    else        -> "標準地図"
}

private fun pinStyleLabel(key: String) = when (key) {
    "circle"  -> "丸ピン"
    "star"    -> "星形ピン"
    "diamond" -> "ひし形ピン"
    else      -> "標準ピン"
}
