<template>
  <v-container fluid class="pa-6">
    <v-card elevation="0" border rounded="lg">
      <v-card-title class="d-flex align-center flex-wrap ga-2">
        命令日志
        <v-spacer />
        <v-select
          v-model="viewMode"
          :items="viewModeOptions"
          item-title="title"
          item-value="value"
          variant="outlined"
          density="compact"
          hide-details
          style="max-width: 160px"
          @update:model-value="onViewModeChange"
        />
        <v-select
          v-if="viewMode === 'push'"
          v-model="pushStatusFilter"
          :items="pushStatusOptions"
          item-title="label"
          item-value="value"
          label="状态"
          variant="outlined"
          density="compact"
          hide-details
          clearable
          style="max-width: 120px"
          @update:model-value="onPushFilterChange"
        />
        <v-select
          v-if="viewMode === 'push'"
          v-model="pushSyncModeFilter"
          :items="pushSyncModeOptions"
          item-title="label"
          item-value="value"
          label="模式"
          variant="outlined"
          density="compact"
          hide-details
          clearable
          style="max-width: 120px"
          @update:model-value="onPushFilterChange"
        />
        <v-select
          v-if="viewMode === 'push'"
          v-model="pushTriggerFilter"
          :items="pushTriggerOptions"
          item-title="label"
          item-value="value"
          label="触发"
          variant="outlined"
          density="compact"
          hide-details
          clearable
          style="max-width: 120px"
          @update:model-value="onPushFilterChange"
        />
        <v-select
          v-model="serverFilter"
          :items="serverList"
          item-title="name"
          item-value="id"
          label="服务器"
          variant="outlined"
          density="compact"
          hide-details
          style="max-width: 180px"
          clearable
          @update:model-value="onServerFilterChange"
        />
      </v-card-title>

      <v-divider />

      <!-- Command View -->
      <v-data-table-server
        v-if="viewMode === 'commands'"
        :items="commands"
        :headers="commandHeaders"
        :items-length="total"
        :loading="loading"
        :page="page"
        :items-per-page="itemsPerPage"
        :items-per-page-options="dataTablePageOptions"
        hover
        density="compact"
        @update:page="onPageChange"
        @update:items-per-page="onItemsPerPageChange"
      >
        <template #item.command="{ item }">
          <code class="text-body-2">{{ item.command }}</code>
        </template>
        <template #item.server_name="{ item }">
          <span class="text-medium-emphasis">{{ item.server_name || '—' }}</span>
        </template>
        <template #item.admin_username="{ item }">
          <span class="text-medium-emphasis">{{ item.admin_username || '—' }}</span>
        </template>
        <template #item.created_at="{ item }">
          <span class="text-caption text-medium-emphasis">{{ formatDateTimeBeijing(item.created_at) }}</span>
        </template>
        <template #no-data>
          <div class="text-center text-medium-emphasis py-6">暂无数据</div>
        </template>
      </v-data-table-server>

      <!-- Session View -->
      <v-data-table-server
        v-else-if="viewMode === 'sessions'"
        :items="sessions"
        :headers="sessionHeaders"
        :items-length="total"
        :loading="loading"
        :page="page"
        :items-per-page="itemsPerPage"
        :items-per-page-options="dataTablePageOptions"
        hover
        density="compact"
        @update:page="onPageChange"
        @update:items-per-page="onItemsPerPageChange"
      >
        <template #item.server_name="{ item }">
          <span class="font-weight-medium">{{ item.server_name || '—' }}</span>
        </template>
        <template #item.status="{ item }">
          <v-chip :color="item.status === 'closed' ? 'grey' : 'success'" size="small" variant="tonal" label>
            {{ item.status }}
          </v-chip>
        </template>
        <template #item.started_at="{ item }">
          <span class="text-caption text-medium-emphasis">{{ formatDateTimeBeijing(item.started_at) }}</span>
        </template>
        <template #no-data>
          <div class="text-center text-medium-emphasis py-6">暂无数据</div>
        </template>
      </v-data-table-server>

      <!-- Push Log View -->
      <v-data-table-server
        v-else
        :items="pushLogs"
        :headers="pushHeaders"
        :items-length="total"
        :loading="loading"
        :page="page"
        :items-per-page="itemsPerPage"
        :items-per-page-options="dataTablePageOptions"
        hover
        density="compact"
        @update:page="onPageChange"
        @update:items-per-page="onItemsPerPageChange"
      >
        <template #item.started_at="{ item }">
          <span class="text-caption text-medium-emphasis">{{ formatDateTimeBeijing(item.started_at) }}</span>
        </template>
        <template #item.server_name="{ item }">
          <span class="text-medium-emphasis">{{ item.server_name || '—' }}</span>
        </template>
        <template #item.status="{ item }">
          <v-chip :color="pushStatusColor(item.status)" size="small" variant="tonal" label>
            {{ pushStatusLabel(item.status) }}
          </v-chip>
        </template>
        <template #item.sync_mode="{ item }">
          <span class="text-caption">{{ syncModeLabel(item.sync_mode) }}</span>
        </template>
        <template #item.trigger_type="{ item }">
          <span class="text-caption">{{ triggerLabel(item.trigger_type) }}</span>
        </template>
        <template #item.source_path="{ item }">
          <span class="text-caption text-truncate d-inline-block" style="max-width: 200px" :title="item.source_path">
            {{ item.source_path }}
          </span>
        </template>
        <template #item.target_path="{ item }">
          <span class="text-caption text-truncate d-inline-block" style="max-width: 160px" :title="item.target_path">
            {{ item.target_path }}
          </span>
        </template>
        <template #item.push_permission="{ item }">
          <span
            class="text-caption"
            :class="item.push_permission ? '' : 'text-medium-emphasis'"
            :title="item.push_permission || '未配置 rsync 属主/权限修正'"
          >{{ formatPushPermission(item.push_permission) }}</span>
        </template>
        <template #item.error_message="{ item }">
          <span
            v-if="item.error_message"
            class="text-caption text-error text-truncate d-inline-block"
            style="max-width: 180px"
            :title="item.error_message"
          >{{ item.error_message }}</span>
          <span v-else class="text-caption text-medium-emphasis">—</span>
        </template>
        <template #no-data>
          <div class="text-center text-medium-emphasis py-6">暂无推送记录</div>
        </template>
      </v-data-table-server>
    </v-card>
  </v-container>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { usePageActivateRefresh } from '@/composables/usePageActivateRefresh'
import { http } from '@/api'
import { useServerList } from '@/composables/useServerList'
import { useSnackbar } from '@/composables/useSnackbar'
import { formatApiError } from '@/utils/apiError'
import { formatPushPermission } from '@/composables/push/labels'
import { formatDateTimeBeijing } from '@/utils/datetime'
import type { CommandLogItem, PushItem, SshSessionItem } from '@/types/api'
import { DATA_TABLE_ITEMS_PER_PAGE_OPTIONS, headersWithoutSort } from '@/constants/dataTable'
import { fetchPagePerPage } from '@/utils/paginatedFetch'

defineOptions({ name: 'CommandsPage' })

type ViewMode = 'commands' | 'sessions' | 'push'

const dataTablePageOptions = [...DATA_TABLE_ITEMS_PER_PAGE_OPTIONS]
const snackbar = useSnackbar()
const { servers: serverList, loadServers } = useServerList()

const viewModeOptions = [
  { title: '命令视图', value: 'commands' as const },
  { title: '会话视图', value: 'sessions' as const },
  { title: '推送日志', value: 'push' as const },
]

const pushStatusOptions = [
  { label: '成功', value: 'success' },
  { label: '失败', value: 'failed' },
  { label: '进行中', value: 'running' },
  { label: '已取消', value: 'cancelled' },
]

const pushSyncModeOptions = [
  { label: '增量', value: 'incremental' },
  { label: '全量', value: 'full' },
  { label: '覆盖', value: 'overwrite' },
  { label: '校验和', value: 'checksum' },
]

const pushTriggerOptions = [
  { label: '手动', value: 'manual' },
  { label: '调度', value: 'schedule' },
  { label: '重试', value: 'retry' },
  { label: '批量', value: 'batch' },
]

const loading = ref(false)
const viewMode = ref<ViewMode>('commands')
const page = ref(1)
const total = ref(0)
const itemsPerPage = ref(30)
const serverFilter = ref<number | null>(null)

const pushStatusFilter = ref<string | null>(null)
const pushSyncModeFilter = ref<string | null>(null)
const pushTriggerFilter = ref<string | null>(null)

const commands = ref<CommandLogItem[]>([])
const sessions = ref<SshSessionItem[]>([])
const pushLogs = ref<PushItem[]>([])

const commandHeaders = headersWithoutSort([
  { title: '命令', key: 'command' },
  { title: '服务器', key: 'server_name' },
  { title: '用户', key: 'admin_username', width: 100 },
  { title: '时间', key: 'created_at', width: 160 },
])

const sessionHeaders = headersWithoutSort([
  { title: '服务器', key: 'server_name' },
  { title: '状态', key: 'status', width: 80 },
  { title: '来源', key: 'remote_addr', width: 120 },
  { title: '开始时间', key: 'started_at', width: 160 },
])

const pushHeaders = headersWithoutSort([
  { title: '时间', key: 'started_at', width: 160 },
  { title: '服务器', key: 'server_name', width: 120 },
  { title: '状态', key: 'status', width: 88 },
  { title: '模式', key: 'sync_mode', width: 80 },
  { title: '触发', key: 'trigger_type', width: 72 },
  { title: '源路径', key: 'source_path' },
  { title: '目标路径', key: 'target_path' },
  { title: '权限', key: 'push_permission', width: 130 },
  { title: '错误', key: 'error_message', width: 180 },
])

function pushStatusColor(status: string): string {
  switch (status) {
    case 'success': return 'success'
    case 'failed': return 'error'
    case 'running': return 'warning'
    case 'cancelled': return 'grey'
    default: return 'default'
  }
}

function pushStatusLabel(status: string): string {
  return pushStatusOptions.find((o) => o.value === status)?.label || status
}

function syncModeLabel(mode?: string): string {
  return pushSyncModeOptions.find((o) => o.value === mode)?.label || mode || '—'
}

function triggerLabel(trigger?: string): string {
  return pushTriggerOptions.find((o) => o.value === trigger)?.label || trigger || '—'
}

function onViewModeChange() {
  page.value = 1
  loadData()
}

function onServerFilterChange() {
  page.value = 1
  loadData()
}

function onPushFilterChange() {
  page.value = 1
  loadData()
}

function onPageChange(p: number) {
  page.value = p
  loadData()
}

function onItemsPerPageChange(n: number) {
  itemsPerPage.value = n
  page.value = 1
  loadData()
}

async function loadData(silent = false) {
  if (!silent) loading.value = true
  try {
    if (viewMode.value === 'commands') {
      const res = await fetchPagePerPage<CommandLogItem>(
        '/assets/command-logs',
        { server_id: serverFilter.value || undefined },
        page.value,
        itemsPerPage.value,
      )
      commands.value = res.items
      total.value = res.total
    } else if (viewMode.value === 'sessions') {
      const res = await fetchPagePerPage<SshSessionItem>(
        '/assets/ssh-sessions',
        { server_id: serverFilter.value || undefined },
        page.value,
        itemsPerPage.value,
      )
      sessions.value = res.items
      total.value = res.total
    } else {
      const params: Record<string, unknown> = {}
      if (serverFilter.value != null) params.server_id = serverFilter.value
      if (pushStatusFilter.value) params.status = pushStatusFilter.value
      if (pushSyncModeFilter.value) params.sync_mode = pushSyncModeFilter.value
      if (pushTriggerFilter.value) params.trigger_type = pushTriggerFilter.value
      const res = await fetchPagePerPage<PushItem>('/servers/logs', params, page.value, itemsPerPage.value)
      pushLogs.value = res.items
      total.value = res.total
    }
    if (itemsPerPage.value === -1) {
      page.value = 1
    }
  } catch (e: unknown) {
    commands.value = []
    sessions.value = []
    pushLogs.value = []
    total.value = 0
    snackbar(formatApiError(e, '加载失败'), 'error')
  } finally {
    if (!silent) loading.value = false
  }
}

async function refreshCommandsPage(silent = false) {
  await Promise.all([loadServers(), loadData(silent)])
}

usePageActivateRefresh((silent) => refreshCommandsPage(silent))
</script>
