<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useServerStore } from '@/stores/server'
import { useAuthStore } from '@/stores/auth'
import { useToastStore } from '@/stores/toast'
import { useThemeGame } from '@/composables/useThemeGame'
import { useGameProfile } from '@/config/gameProfiles'
import type { DeploymentConfig, DeploymentStatus } from '@/types'
import { useWebSocket } from '@/composables/useWebSocket'
import Panel from '@/components/ds/data/Panel.vue'
import Button from '@/components/ds/core/Button.vue'
import Badge from '@/components/ds/core/Badge.vue'
import StatusDot from '@/components/ds/core/StatusDot.vue'
import Icon from '@/components/ds/core/Icon.vue'
import Alert from '@/components/ds/feedback/Alert.vue'
import EmptyState from '@/components/ds/feedback/EmptyState.vue'
import Input from '@/components/ds/forms/Input.vue'
import Switch from '@/components/ds/forms/Switch.vue'
import Tabs from '@/components/ds/navigation/Tabs.vue'

const server = useServerStore()
const auth = useAuthStore()
const toast = useToastStore()
const { activeGame } = useThemeGame()

// Profile follows the GameSwitcher. 'all' defaults to rust (neutral house skin).
const profile = computed(() => {
  const game = activeGame.value === 'all' ? 'rust' : activeGame.value
  return useGameProfile(game)
})

// Game-specific derived flags
const isRust = computed(() => profile.value.mods === 'umod')
const hasPluginSystem = computed(() => profile.value.mods === 'umod')
const isDockerManaged = computed(() => profile.value.managementModel === 'docker-compose')

// Management model human label for the identity badge
const managementModelLabel = computed(() => {
  const m = profile.value.managementModel
  const c = profile.value.console
  if (m === 'docker-compose') {
    return profile.value.clustering === 'battlegroup' ? 'Docker · BattleGroup' : 'Docker · Compose'
  }
  if (c === 'rcon+ingame') return 'Process · RCON + In-game'
  if (c === 'rcon+gm') return 'Process · RCON + GM'
  return 'Process · RCON'
})

// Clustering section label per game
const clusterLabel = computed(() => {
  const cl = profile.value.clustering
  if (cl === 'battlegroup') return 'BattleGroups & Sietches'
  if (cl === 'main-client') return 'Cluster'
  if (cl === 'character-transfer') return 'Clans & Character Transfer'
  return ''
})

const editMode = ref(false)
const saving = ref(false)
const actionLoading = ref<string | null>(null)
const copied = ref(false)
const setupTab = ref<'linux' | 'windows'>('linux')
const windowsCopied = ref(false)
const showDeployForm = ref(false)
const deployLoading = ref(false)
const oxideStatus = ref<{ stage: string; progress: number; message: string; error?: string } | null>(null)
const isInstallingOxide = ref(false)

const deployForm = ref<DeploymentConfig>({
  server_name: 'My Rust Server',
  max_players: 100,
  world_size: 4000,
  seed: Math.floor(Math.random() * 2147483647),
  server_port: 28015,
  rcon_port: 28016,
  rcon_password: '',
})

const isAgentConnected = computed(() =>
  server.connection?.connection_type === 'bare_metal' &&
  server.connection?.connection_status === 'connected'
)

const agentLastSeen = computed(() => {
  const ts = server.connection?.companion_last_seen
  if (!ts) return null
  return new Date(ts)
})

const agentLastSeenLabel = computed(() => {
  const d = agentLastSeen.value
  if (!d) return 'Never'
  const diff = Math.floor((Date.now() - d.getTime()) / 1000)
  if (diff < 60) return `${diff}s ago`
  if (diff < 3600) return `${Math.floor(diff / 60)}m ago`
  if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`
  return d.toLocaleDateString()
})

const licenseKey = computed(() => auth.license?.license_key || 'YOUR-LICENSE-KEY')

const linuxCommands = computed(() => `# Download the agent
curl -LO https://cdn.corrosionmgmt.com/host-agent/latest/corrosion-host-agent-linux-amd64
chmod +x corrosion-host-agent-linux-amd64

# Start with your license key
export LICENSE_ID="${licenseKey.value}"
export NATS_URL="nats://nats.corrosionmgmt.com:4222"
./corrosion-host-agent-linux-amd64`)

const windowsCommands = computed(() => `# Requires PowerShell (not Command Prompt)
# Download the agent
Invoke-WebRequest -Uri "https://cdn.corrosionmgmt.com/host-agent/latest/corrosion-host-agent-windows-amd64.exe" -OutFile "corrosion-host-agent-windows-amd64.exe"

# Start with your license key
$env:LICENSE_ID="${licenseKey.value}"
$env:NATS_URL="nats://nats.corrosionmgmt.com:4222"
.\\corrosion-host-agent-windows-amd64.exe`)

async function copySetupCommands() {
  try {
    const text = setupTab.value === 'linux' ? linuxCommands.value : windowsCommands.value
    await navigator.clipboard.writeText(text)
    if (setupTab.value === 'linux') {
      copied.value = true
      setTimeout(() => { copied.value = false }, 2000)
    } else {
      windowsCopied.value = true
      setTimeout(() => { windowsCopied.value = false }, 2000)
    }
  } catch {
    // Clipboard API unavailable
  }
}

async function startDeploy() {
  if (!deployForm.value.rcon_password || deployForm.value.rcon_password.length < 6) return
  deployLoading.value = true
  try {
    await server.deployServer(deployForm.value)
    showDeployForm.value = false
  } catch {
    toast.error('Failed to start deployment')
  } finally {
    deployLoading.value = false
  }
}

const deployStages = [
  { key: 'downloading_steamcmd', label: 'Download SteamCMD' },
  { key: 'installing_steamcmd', label: 'Install SteamCMD' },
  { key: 'downloading_rust', label: 'Download Rust Server' },
  { key: 'configuring', label: 'Configure' },
  { key: 'starting', label: 'Start Server' },
  { key: 'online', label: 'Online' },
] as const

function getStageState(stageKey: string): 'pending' | 'active' | 'complete' | 'failed' {
  const status = server.deploymentStatus
  if (!status) return 'pending'
  if (status.stage === 'failed') {
    const idx = deployStages.findIndex(s => s.key === stageKey)
    const failIdx = deployStages.findIndex(s => s.key === status.stage)
    if (idx < failIdx) return 'complete'
    if (idx === failIdx) return 'failed'
    return 'pending'
  }
  const currentIdx = deployStages.findIndex(s => s.key === status.stage)
  const thisIdx = deployStages.findIndex(s => s.key === stageKey)
  if (thisIdx < currentIdx) return 'complete'
  if (thisIdx === currentIdx) return status.stage === 'online' ? 'complete' : 'active'
  return 'pending'
}

const oxideStages = [
  { key: 'fetching_release', label: 'Check latest release' },
  { key: 'downloading', label: 'Download Oxide' },
  { key: 'installing', label: 'Extract files' },
  { key: 'restarting', label: 'Restart server' },
  { key: 'complete', label: 'Complete' },
] as const

function getOxideStageState(stageKey: string): 'pending' | 'active' | 'complete' | 'failed' {
  if (!oxideStatus.value) return 'pending'
  const status = oxideStatus.value
  if (status.stage === 'failed') {
    const currentStages = oxideStages
    const idx = currentStages.findIndex(s => s.key === stageKey)
    return idx === 0 ? 'failed' : 'pending'
  }
  const currentIdx = oxideStages.findIndex(s => s.key === status.stage)
  const thisIdx = oxideStages.findIndex(s => s.key === stageKey)
  if (thisIdx < currentIdx) return 'complete'
  if (thisIdx === currentIdx) return status.stage === 'complete' ? 'complete' : 'active'
  return 'pending'
}

async function installOxide() {
  isInstallingOxide.value = true
  oxideStatus.value = null
  try {
    await server.installOxide()
  } catch {
    toast.error('Failed to start Oxide installation')
    isInstallingOxide.value = false
  }
}

const form = ref({
  server_name: '',
  max_players: 0,
  world_size: 0,
  current_seed: 0,
})

function loadFormFromConfig() {
  if (server.config) {
    form.value = {
      server_name: server.config.server_name || '',
      max_players: server.config.max_players ?? 100,
      world_size: server.config.world_size ?? 4000,
      current_seed: server.config.current_seed ?? 0,
    }
  }
}

async function saveConfig() {
  saving.value = true
  try {
    await server.updateConfig(form.value)
    editMode.value = false
    toast.success('Server configuration saved')
  } catch {
    toast.error('Failed to save server configuration')
  } finally {
    saving.value = false
  }
}

async function serverAction(action: 'start' | 'stop' | 'restart') {
  actionLoading.value = action
  try {
    if (action === 'start') await server.startServer()
    else if (action === 'stop') await server.stopServer()
    else await server.restartServer()
    await server.fetchServer()
    toast.success(`Server ${action} command sent`)
  } catch {
    toast.error(`Failed to ${action} server`)
  } finally {
    actionLoading.value = null
  }
}

async function toggleAutomation(field: 'crash_recovery_enabled' | 'auto_update_on_force_wipe' | 'force_wipe_eligible') {
  if (!server.config) return
  const newValue = !server.config[field]
  try {
    await server.updateConfig({ [field]: newValue })
    toast.success('Automation setting saved')
  } catch {
    toast.error('Failed to save automation setting')
  }
}

// Deploy form string bindings (DS Input uses string v-model)
const deployServerName = computed({
  get: () => deployForm.value.server_name,
  set: (v: string) => { deployForm.value.server_name = v },
})
const deployRconPassword = computed({
  get: () => deployForm.value.rcon_password,
  set: (v: string) => { deployForm.value.rcon_password = v },
})

// Config form string bindings
const formServerName = computed({
  get: () => form.value.server_name,
  set: (v: string) => { form.value.server_name = v },
})

// Setup tab items
const setupTabItems = [
  { value: 'linux', label: 'Linux' },
  { value: 'windows', label: 'Windows' },
]

// Connection status derived values
const connStatusTone = computed<'online' | 'offline' | 'warn'>(() => {
  const cs = server.connection?.connection_status
  if (cs === 'connected') return 'online'
  if (cs === 'degraded') return 'warn'
  return 'offline'
})

onMounted(async () => {
  await server.fetchServer()
  loadFormFromConfig()

  const ws = useWebSocket()
  ws.subscribe((msg) => {
    if (msg.type === 'event' && msg.event === 'deploy_status') {
      server.updateDeploymentStatus(msg.data as DeploymentStatus)
    }
    if (msg.type === 'event' && msg.event === 'oxide_status') {
      oxideStatus.value = msg.data as { stage: string; progress: number; message: string; error?: string }
      if (msg.data && (msg.data as any).stage === 'complete' || (msg.data as any).stage === 'failed') {
        isInstallingOxide.value = false
      }
    }
  })
})
</script>

<template>
  <div class="sv">
    <!-- Page head — game-aware identity -->
    <div class="sv__head">
      <div class="sv__head-id">
        <div class="sv__head-chip">
          <Icon name="server" :size="20" :stroke-width="2" />
        </div>
        <div>
          <div class="t-eyebrow">{{ profile.label }} · Server management</div>
          <h1 class="sv__title">Server</h1>
        </div>
      </div>
      <Badge tone="neutral" :mono="true" class="sv__model-badge">{{ managementModelLabel }}</Badge>
    </div>

    <!-- Connection -->
    <Panel title="Connection">
      <template #actions>
        <Badge :tone="connStatusTone" :dot="true" :pulse="connStatusTone === 'online'">
          {{ server.connection?.connection_status ?? 'Unknown' }}
        </Badge>
      </template>
      <div class="sv__grid4">
        <div class="sv__field">
          <div class="sv__field-label">Status</div>
          <div class="sv__field-val sv__field-val--inline">
            <StatusDot :tone="connStatusTone" :pulse="connStatusTone === 'online'" />
            <span>{{ server.connection?.connection_status ?? 'Unknown' }}</span>
          </div>
        </div>
        <div class="sv__field">
          <div class="sv__field-label">Connection type</div>
          <div class="sv__field-val sv__field-val--mono">{{ server.connection?.connection_type ?? '—' }}</div>
        </div>
        <div class="sv__field">
          <div class="sv__field-label">Server IP</div>
          <div class="sv__field-val sv__field-val--mono">
            {{ server.connection?.server_ip ?? '—' }}{{ server.connection?.server_port ? `:${server.connection.server_port}` : '' }}
          </div>
        </div>
        <div class="sv__field">
          <div class="sv__field-label">Game port</div>
          <div class="sv__field-val sv__field-val--mono">{{ server.connection?.game_port ?? '—' }}</div>
        </div>
      </div>
    </Panel>

    <!-- Controls -->
    <Panel title="Controls">
      <div class="sv__controls">
        <Button
          variant="outline"
          icon="play"
          :loading="actionLoading === 'start'"
          :disabled="server.connection?.connection_status === 'connected' || actionLoading !== null"
          @click="serverAction('start')"
        >Start server</Button>
        <Button
          variant="danger-soft"
          icon="power"
          :loading="actionLoading === 'stop'"
          :disabled="server.connection?.connection_status !== 'connected' || actionLoading !== null"
          @click="serverAction('stop')"
        >Stop server</Button>
        <Button
          variant="secondary"
          icon="refresh-cw"
          :loading="actionLoading === 'restart'"
          :disabled="server.connection?.connection_status !== 'connected' || actionLoading !== null"
          @click="serverAction('restart')"
        >Restart server</Button>
      </div>
    </Panel>

    <!-- Host agent -->
    <Panel title="Host agent" subtitle="Bare-metal server management binary">
      <template #actions>
        <Badge :tone="isAgentConnected ? 'online' : 'offline'" :dot="true" :pulse="isAgentConnected">
          {{ isAgentConnected ? 'Active' : 'Inactive' }}
        </Badge>
      </template>

      <!-- Agent status row -->
      <div class="sv__grid3 sv__mb">
        <div class="sv__field">
          <div class="sv__field-label">Agent status</div>
          <div class="sv__field-val sv__field-val--inline">
            <StatusDot :tone="isAgentConnected ? 'online' : 'offline'" :pulse="isAgentConnected" />
            <span>{{ isAgentConnected ? 'Active' : 'Inactive' }}</span>
          </div>
        </div>
        <div class="sv__field">
          <div class="sv__field-label">Connection type</div>
          <div class="sv__field-val sv__field-val--mono">{{ server.connection?.connection_type ?? '—' }}</div>
        </div>
        <div class="sv__field">
          <div class="sv__field-label">Last heartbeat</div>
          <div class="sv__field-val">{{ agentLastSeenLabel }}</div>
        </div>
      </div>

      <!-- Download -->
      <div class="sv__section-head">
        <Icon name="download" :size="14" />
        <span>Download host agent</span>
      </div>
      <div class="sv__downloads sv__mb">
        <a
          href="https://cdn.corrosionmgmt.com/host-agent/latest/corrosion-host-agent-linux-amd64"
          download="corrosion-host-agent-linux-amd64"
          class="sv__dl-link"
        >
          <Icon name="download" :size="15" />
          Linux (amd64)
        </a>
        <a
          href="https://cdn.corrosionmgmt.com/host-agent/latest/corrosion-host-agent-windows-amd64.exe"
          download="corrosion-host-agent-windows-amd64.exe"
          class="sv__dl-link"
        >
          <Icon name="download" :size="15" />
          Windows (amd64)
        </a>
      </div>

      <!-- Quick setup -->
      <div class="sv__setup-head">
        <div class="sv__section-head">
          <Icon name="terminal" :size="14" />
          <span>Quick setup</span>
        </div>
        <Button
          variant="secondary"
          size="sm"
          :icon="(setupTab === 'linux' ? copied : windowsCopied) ? 'check' : 'copy'"
          @click="copySetupCommands"
        >{{ (setupTab === 'linux' ? copied : windowsCopied) ? 'Copied' : 'Copy' }}</Button>
      </div>

      <Tabs v-model="setupTab" :items="setupTabItems" class="sv__mb-sm" />

      <Alert v-if="setupTab === 'windows'" tone="warn" class="sv__mb-sm">
        PowerShell required — Command Prompt is not supported.
      </Alert>

      <!-- Linux commands -->
      <div v-if="setupTab === 'linux'" class="sv__codeblock">
        <p class="sv__cmt"># Download the agent</p>
        <p>curl -LO https://cdn.corrosionmgmt.com/host-agent/latest/corrosion-host-agent-linux-amd64</p>
        <p>chmod +x corrosion-host-agent-linux-amd64</p>
        <p class="sv__cmt sv__mt">&#x23; Start with your license key</p>
        <p>export LICENSE_ID=<span class="sv__accent">"{{ licenseKey }}"</span></p>
        <p>export NATS_URL=<span class="sv__accent">"nats://nats.corrosionmgmt.com:4222"</span></p>
        <p>./corrosion-host-agent-linux-amd64</p>
      </div>

      <!-- Windows commands -->
      <div v-if="setupTab === 'windows'" class="sv__codeblock">
        <p class="sv__cmt"># Requires PowerShell (not Command Prompt)</p>
        <p class="sv__cmt"># Download the agent</p>
        <p>Invoke-WebRequest -Uri <span class="sv__accent">"https://cdn.corrosionmgmt.com/host-agent/latest/corrosion-host-agent-windows-amd64.exe"</span> -OutFile <span class="sv__accent">"corrosion-host-agent-windows-amd64.exe"</span></p>
        <p class="sv__cmt sv__mt">&#x23; Start with your license key</p>
        <p>$env:LICENSE_ID=<span class="sv__accent">"{{ licenseKey }}"</span></p>
        <p>$env:NATS_URL=<span class="sv__accent">"nats://nats.corrosionmgmt.com:4222"</span></p>
        <p>.\corrosion-host-agent-windows-amd64.exe</p>
      </div>
    </Panel>

    <!-- Deploy Server — Rust only (SteamCMD path). Other games use docker-compose or external tooling. -->
    <Panel v-if="isRust" title="Deploy Rust server" subtitle="One-click: SteamCMD, download, configure, start">
      <template #title-append>
        <Icon name="rocket" :size="15" />
      </template>

      <!-- Deployment progress -->
      <div v-if="server.deploymentStatus || server.isDeploying" class="sv__stages">
        <div
          v-for="stage in deployStages"
          :key="stage.key"
          class="sv__stage"
        >
          <div
            class="sv__stage-dot"
            :data-state="getStageState(stage.key)"
          >
            <Icon v-if="getStageState(stage.key) === 'active'" name="loader" :size="13" class="sv__spin" />
            <Icon v-else-if="getStageState(stage.key) === 'complete'" name="check" :size="13" />
            <Icon v-else-if="getStageState(stage.key) === 'failed'" name="triangle-alert" :size="13" />
            <span v-else class="sv__stage-nub" />
          </div>
          <span
            class="sv__stage-label"
            :data-state="getStageState(stage.key)"
          >{{ stage.label }}</span>
        </div>

        <Alert v-if="server.deploymentStatus?.message" tone="neutral" class="sv__mt">
          {{ server.deploymentStatus.message }}
        </Alert>
        <Alert v-if="server.deploymentStatus?.error" tone="danger" class="sv__mt">
          {{ server.deploymentStatus.error }}
        </Alert>

        <div v-if="server.deploymentStatus?.stage === 'failed'" class="sv__mt">
          <Button
            variant="secondary"
            icon="refresh-cw"
            @click="server.clearDeploymentStatus(); showDeployForm = true"
          >Retry deployment</Button>
        </div>
      </div>

      <!-- Deploy form / prompt -->
      <div v-else>
        <div v-if="!showDeployForm" class="sv__deploy-prompt">
          <p class="sv__deploy-desc">Automatically install SteamCMD, download Rust Dedicated Server, configure, and start — all with one click.</p>
          <Button icon="rocket" @click="showDeployForm = true">Deploy server</Button>
        </div>

        <form v-else @submit.prevent="startDeploy" class="sv__form">
          <div class="sv__form-grid">
            <Input
              v-model="deployServerName"
              label="Server name"
              :required="true"
              class="sv__col-span2"
            />
            <Input
              :model-value="String(deployForm.max_players)"
              @update:model-value="v => { deployForm.max_players = Number(v) }"
              label="Max players"
              type="number"
              :mono="true"
            />
            <Input
              :model-value="String(deployForm.world_size)"
              @update:model-value="v => { deployForm.world_size = Number(v) }"
              label="World size"
              type="number"
              :mono="true"
            />
            <Input
              :model-value="String(deployForm.seed)"
              @update:model-value="v => { deployForm.seed = Number(v) }"
              label="Map seed"
              type="number"
              :mono="true"
            />
            <Input
              :model-value="String(deployForm.server_port)"
              @update:model-value="v => { deployForm.server_port = Number(v) }"
              label="Server port"
              type="number"
              :mono="true"
            />
            <Input
              :model-value="String(deployForm.rcon_port)"
              @update:model-value="v => { deployForm.rcon_port = Number(v) }"
              label="RCON port"
              type="number"
              :mono="true"
            />
            <Input
              v-model="deployRconPassword"
              label="RCON password"
              type="password"
              placeholder="Minimum 6 characters"
              :required="true"
              class="sv__col-span2"
            />
          </div>
          <div class="sv__form-actions">
            <Button
              type="submit"
              icon="rocket"
              :loading="deployLoading"
              :disabled="deployLoading || !deployForm.rcon_password || deployForm.rcon_password.length < 6"
            >{{ deployLoading ? 'Deploying…' : 'Deploy server' }}</Button>
            <Button variant="ghost" type="button" @click="showDeployForm = false">Cancel</Button>
          </div>
        </form>
      </div>
    </Panel>

    <!-- Non-Rust: Docker-managed server note -->
    <Panel
      v-if="isDockerManaged"
      :title="profile.label + ' server deployment'"
      subtitle="Managed via Docker Compose"
    >
      <template #title-append>
        <Icon name="box" :size="15" />
      </template>
      <EmptyState
        icon="box"
        title="Docker-managed deployment"
        :description="profile.label + ' servers are managed via Docker Compose. Connect the host agent on your Docker host to enable lifecycle management.'"
      >
        <template #action>
          <Badge tone="info">Docker · Compose</Badge>
        </template>
      </EmptyState>
    </Panel>

    <!-- Install Oxide / uMod — Rust only -->
    <Panel v-if="hasPluginSystem" title="Install Oxide / uMod" subtitle="Required for all plugins including CorrosionCompanion">
      <template #title-append>
        <Icon name="puzzle" :size="15" />
      </template>

      <!-- Installation progress -->
      <div v-if="oxideStatus || isInstallingOxide" class="sv__stages">
        <div
          v-for="stage in oxideStages"
          :key="stage.key"
          class="sv__stage"
        >
          <div
            class="sv__stage-dot"
            :data-state="getOxideStageState(stage.key)"
          >
            <Icon v-if="getOxideStageState(stage.key) === 'active'" name="loader" :size="13" class="sv__spin" />
            <Icon v-else-if="getOxideStageState(stage.key) === 'complete'" name="check" :size="13" />
            <Icon v-else-if="getOxideStageState(stage.key) === 'failed'" name="triangle-alert" :size="13" />
            <span v-else class="sv__stage-nub" />
          </div>
          <span
            class="sv__stage-label"
            :data-state="getOxideStageState(stage.key)"
          >{{ stage.label }}</span>
        </div>

        <Alert v-if="oxideStatus?.message" tone="neutral" class="sv__mt">
          {{ oxideStatus.message }}
        </Alert>
        <Alert v-if="oxideStatus?.error" tone="danger" class="sv__mt">
          {{ oxideStatus.error }}
        </Alert>

        <div v-if="oxideStatus?.stage === 'failed'" class="sv__mt">
          <Button
            variant="secondary"
            icon="refresh-cw"
            @click="oxideStatus = null; installOxide()"
          >Retry installation</Button>
        </div>
      </div>

      <!-- Install prompt -->
      <div v-else class="sv__deploy-prompt">
        <p class="sv__deploy-desc">Install or update Oxide / uMod. Required for all plugins including CorrosionCompanion.</p>
        <Button icon="puzzle" @click="installOxide()">Install Oxide</Button>
      </div>
    </Panel>

    <!-- Workshop Mods info — Conan / Soulmask (Steam Workshop, no install step needed) -->
    <Panel
      v-else-if="profile.mods === 'workshop'"
      :title="(profile.terminology.mods ?? 'Workshop Mods')"
      :subtitle="profile.label + ' uses Steam Workshop — no manual install step required'"
    >
      <template #title-append>
        <Icon name="layers" :size="15" />
      </template>
      <EmptyState
        icon="layers"
        :title="profile.label + ' mod management'"
        :description="profile.label + ' loads mods directly from Steam Workshop. Manage your mod list in server config — no Corrosion install step needed.'"
      />
    </Panel>

    <!-- Conan Exiles special concepts (Clans / Thralls / Purge) -->
    <Panel
      v-if="profile.accent === 'conan'"
      title="Conan Exiles concepts"
      subtitle="Key admin mechanics for Conan Exiles servers"
    >
      <div class="sv__concept-grid">
        <div class="sv__concept">
          <Icon name="users" :size="16" />
          <div>
            <div class="sv__concept-label">Clans</div>
            <div class="sv__concept-desc">Player factions. Clan management via in-game admin panel or RCON.</div>
          </div>
        </div>
        <div class="sv__concept">
          <Icon name="zap" :size="16" />
          <div>
            <div class="sv__concept-label">Thralls &amp; Avatars</div>
            <div class="sv__concept-desc">Server-controlled NPCs and deity summons. Purge cycle managed via server settings.</div>
          </div>
        </div>
        <div class="sv__concept">
          <Icon name="shield" :size="16" />
          <div>
            <div class="sv__concept-label">Purge</div>
            <div class="sv__concept-desc">NPC raid events targeting player bases. Enable / tune via server config.</div>
          </div>
        </div>
      </div>
    </Panel>

    <!-- Soulmask clustering section -->
    <Panel
      v-if="profile.clustering === 'main-client'"
      :title="clusterLabel"
      subtitle="Main-client cluster topology for Soulmask"
    >
      <EmptyState
        icon="network"
        title="Cluster management coming soon"
        :description="'Connect a ' + profile.label + ' host to manage the main-client cluster from this panel. Cluster configuration requires the host agent.'"
      />
    </Panel>

    <!-- Dune BattleGroup / Sietches section -->
    <Panel
      v-if="profile.clustering === 'battlegroup'"
      title="BattleGroups &amp; Sietches"
      subtitle="Dune: Awakening server cluster topology"
    >
      <EmptyState
        icon="map"
        title="Sietch management requires a connected Dune host"
        description="Connect the host agent on your Dune: Awakening Docker host to manage BattleGroups and Sietches from this panel."
      />
    </Panel>

    <!-- Configuration -->
    <Panel title="Configuration">
      <template #actions>
        <Button
          v-if="!editMode"
          variant="ghost"
          size="sm"
          icon="settings"
          @click="editMode = true; loadFormFromConfig()"
        >Edit</Button>
        <template v-else>
          <Button
            variant="secondary"
            size="sm"
            type="button"
            @click="editMode = false"
          >Cancel</Button>
          <Button
            size="sm"
            icon="check"
            :loading="saving"
            :disabled="saving"
            @click="saveConfig"
          >Save changes</Button>
        </template>
      </template>

      <!-- Read mode -->
      <div v-if="!editMode" class="sv__grid4">
        <div class="sv__field">
          <div class="sv__field-label">Server name</div>
          <div class="sv__field-val">{{ server.config?.server_name ?? 'Not configured' }}</div>
        </div>
        <div class="sv__field">
          <div class="sv__field-label">Max players</div>
          <div class="sv__field-val sv__field-val--mono">{{ server.config?.max_players ?? '—' }}</div>
        </div>
        <div class="sv__field">
          <div class="sv__field-label">World size</div>
          <div class="sv__field-val sv__field-val--mono">{{ server.config?.world_size ?? '—' }}</div>
        </div>
        <div class="sv__field">
          <div class="sv__field-label">Current seed</div>
          <div class="sv__field-val sv__field-val--mono">{{ server.config?.current_seed ?? '—' }}</div>
        </div>
      </div>

      <!-- Edit mode -->
      <form v-else @submit.prevent="saveConfig" class="sv__form">
        <div class="sv__form-grid">
          <Input
            v-model="formServerName"
            label="Server name"
            class="sv__col-span2"
          />
          <Input
            :model-value="String(form.max_players)"
            @update:model-value="v => { form.max_players = Number(v) }"
            label="Max players"
            type="number"
            :mono="true"
          />
          <Input
            :model-value="String(form.world_size)"
            @update:model-value="v => { form.world_size = Number(v) }"
            label="World size"
            type="number"
            :mono="true"
          />
          <Input
            :model-value="String(form.current_seed)"
            @update:model-value="v => { form.current_seed = Number(v) }"
            label="Current seed"
            type="number"
            :mono="true"
            class="sv__col-span2"
          />
        </div>
      </form>
    </Panel>

    <!-- Automation -->
    <Panel title="Automation">
      <div class="sv__toggles">
        <div class="sv__toggle-row">
          <div class="sv__toggle-body">
            <div class="sv__toggle-label">Auto-restart</div>
            <div class="sv__toggle-sub">Restart on crash detection</div>
          </div>
          <Switch
            :model-value="server.config?.crash_recovery_enabled ?? false"
            :disabled="!server.config"
            @update:model-value="toggleAutomation('crash_recovery_enabled')"
          />
        </div>
        <div class="sv__toggle-row">
          <div class="sv__toggle-body">
            <div class="sv__toggle-label">
              <!-- Rust: "force wipe" is a Facepunch concept. Others: plain "auto-update" -->
              {{ isRust ? 'Auto-update on force wipe' : 'Auto-update on patch' }}
            </div>
            <div class="sv__toggle-sub">
              {{ isRust ? 'Update when Facepunch pushes' : 'Update when the developer pushes a patch' }}
            </div>
          </div>
          <Switch
            :model-value="server.config?.auto_update_on_force_wipe ?? false"
            :disabled="!server.config"
            @update:model-value="toggleAutomation('auto_update_on_force_wipe')"
          />
        </div>
        <!-- Rust-only: force wipe eligibility is a Facepunch concept -->
        <div v-if="isRust" class="sv__toggle-row">
          <div class="sv__toggle-body">
            <div class="sv__toggle-label">Force wipe eligible</div>
            <div class="sv__toggle-sub">Server participates in force wipes</div>
          </div>
          <Switch
            :model-value="server.config?.force_wipe_eligible ?? false"
            :disabled="!server.config"
            @update:model-value="toggleAutomation('force_wipe_eligible')"
          />
        </div>
      </div>
    </Panel>
  </div>
</template>

<style scoped>
.sv { max-width: 900px; margin: 0 auto; display: flex; flex-direction: column; gap: 16px; }

/* Page head */
.sv__head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; }
.sv__head-id { display: flex; align-items: center; gap: 12px; }
.sv__head-chip {
  width: 40px; height: 40px; flex: none; border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center;
  color: var(--accent); background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-border);
}
.sv__title {
  font-size: var(--text-2xl); font-weight: 700; letter-spacing: -0.02em;
  color: var(--text-primary); margin-top: 3px;
}

/* Layout grids */
.sv__grid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.sv__grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 768px) {
  .sv__grid4 { grid-template-columns: repeat(2, 1fr); }
  .sv__grid3 { grid-template-columns: repeat(2, 1fr); }
}

/* Field */
.sv__field-label { font-size: var(--text-xs); color: var(--text-tertiary); margin-bottom: 4px; }
.sv__field-val { font-size: var(--text-sm); font-weight: 500; color: var(--text-primary); }
.sv__field-val--mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.sv__field-val--inline { display: flex; align-items: center; gap: 7px; }

/* Spacing helpers */
.sv__mb { margin-bottom: 20px; }
.sv__mb-sm { margin-bottom: 12px; }
.sv__mt { margin-top: 12px; }

/* Controls */
.sv__controls { display: flex; flex-wrap: wrap; gap: 10px; }

/* Section head (label inside panel body) */
.sv__section-head {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--text-xs); font-weight: 600; color: var(--text-tertiary);
  text-transform: uppercase; letter-spacing: var(--tracking-wider);
  margin-bottom: 10px;
}

/* Download links */
.sv__downloads { display: flex; flex-wrap: wrap; gap: 10px; }
.sv__dl-link {
  display: inline-flex; align-items: center; gap: 8px;
  height: var(--control-h-md); padding: 0 14px;
  background: var(--surface-raised-2); border-radius: var(--radius-md);
  box-shadow: var(--ring-default);
  font-size: var(--text-sm); font-weight: 600; color: var(--text-primary);
  text-decoration: none; transition: var(--transition-colors);
}
.sv__dl-link:hover { background: var(--surface-active); }

/* Setup head */
.sv__setup-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }

/* Code block */
.sv__codeblock {
  background: var(--surface-inset); border-radius: var(--radius-md);
  box-shadow: var(--ring-default);
  padding: 14px 16px; font-family: var(--font-mono); font-size: var(--text-xs);
  color: var(--text-secondary); overflow-x: auto; line-height: 1.7;
}
.sv__cmt { color: var(--text-muted); }
.sv__accent { color: var(--accent-text); }
.sv__mt { margin-top: 12px; }

/* Deploy prompt */
.sv__deploy-prompt { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 14px; padding: 12px 0; }
.sv__deploy-desc { font-size: var(--text-sm); color: var(--text-tertiary); max-width: 420px; line-height: 1.5; }

/* Form */
.sv__form { display: flex; flex-direction: column; gap: 16px; }
.sv__form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.sv__col-span2 { grid-column: 1 / -1; }
.sv__form-actions { display: flex; align-items: center; gap: 10px; }

/* Deployment / Oxide stages */
.sv__stages { display: flex; flex-direction: column; gap: 10px; }
.sv__stage { display: flex; align-items: center; gap: 11px; }
.sv__stage-dot {
  width: 24px; height: 24px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-raised-2); color: var(--text-muted);
  box-shadow: var(--ring-default);
}
.sv__stage-dot[data-state="active"] { background: var(--status-warn-soft); color: var(--status-warn); box-shadow: inset 0 0 0 1px var(--status-warn-border); }
.sv__stage-dot[data-state="complete"] { background: var(--status-online-soft); color: var(--status-online); box-shadow: inset 0 0 0 1px var(--status-online-border); }
.sv__stage-dot[data-state="failed"] { background: var(--status-offline-soft); color: var(--status-offline); box-shadow: inset 0 0 0 1px var(--status-offline-border); }
.sv__stage-nub { width: 6px; height: 6px; border-radius: 50%; background: var(--text-muted); }
.sv__stage-label { font-size: var(--text-sm); color: var(--text-tertiary); }
.sv__stage-label[data-state="active"] { color: var(--status-warn); font-weight: 600; }
.sv__stage-label[data-state="complete"] { color: var(--status-online); }
.sv__stage-label[data-state="failed"] { color: var(--status-offline); }

@keyframes sv-spin { to { transform: rotate(360deg); } }
.sv__spin { animation: sv-spin 0.7s linear infinite; }

/* Automation toggles */
.sv__toggles { display: flex; flex-direction: column; gap: 0; }
.sv__toggle-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 14px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.sv__toggle-row:last-child { border-bottom: 0; padding-bottom: 0; }
.sv__toggle-row:first-child { padding-top: 0; }
.sv__toggle-label { font-size: var(--text-sm); font-weight: 500; color: var(--text-primary); }
.sv__toggle-sub { font-size: var(--text-xs); color: var(--text-tertiary); margin-top: 2px; }

/* Management model badge in page head */
.sv__model-badge { align-self: center; }

/* Game concept cards (Conan Exiles special features) */
.sv__concept-grid { display: flex; flex-direction: column; gap: 14px; }
.sv__concept {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 14px;
  background: var(--surface-raised); border-radius: var(--radius-md);
  box-shadow: var(--ring-default);
  color: var(--accent);
}
.sv__concept-label { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); margin-bottom: 2px; }
.sv__concept-desc { font-size: var(--text-xs); color: var(--text-tertiary); line-height: 1.5; }
</style>
