<template>
  <section class="digital-employees-view skill-center">
    <Transition name="skill-view" mode="out-in">
      <article
        v-if="selectedEmployee"
        key="detail"
        class="skill-detail digital-employee-detail"
      >
        <div class="detail-scroll">
          <section v-if="detailError" class="detail-inline-state panel error">
            <i class="mdi mdi-alert-circle-outline"></i>
            <div>
              <strong>数字员工详情加载失败</strong>
              <p>{{ detailError }}</p>
            </div>
          </section>

          <TableLoadingState
            v-else-if="detailLoading && selectedEmployee.loading"
            class="detail-loading-state panel"
            variant="panel"
            title="正在加载数字员工详情"
            message="列表数据已就绪，正在补充 Skills 源文件和执行配置"
            icon="mdi mdi-account-cog-outline"
            :show-skeleton="false"
          />

          <AuditDigitalEmployeeDetail
            v-else
            :selected-skill="selectedEmployee"
            :can-edit="canEditDigitalEmployeeSource"
            :detail-busy="detailBusy"
            :action-state="actionState"
            @save-source="saveDigitalEmployeeSource"
          />
        </div>

        <footer class="detail-actions digital-employee-detail-actions">
          <button class="back-action" type="button" @click="closeEmployeeDetail">
            <i class="mdi mdi-arrow-left"></i>
            <span>返回数字员工列表</span>
          </button>

          <div class="detail-action-group">
            <button
              class="minor-action enable-action"
              :class="{ 'is-on': selectedEmployee.statusValue === 'active' }"
              type="button"
              :disabled="!canOperateDigitalEmployee || detailBusy"
              @click="toggleDigitalEmployeeRunning(selectedEmployee)"
            >
              <i :class="selectedEmployee.statusValue === 'active' ? 'mdi mdi-toggle-switch' : 'mdi mdi-toggle-switch-off-outline'"></i>
              <span>{{ selectedEmployee.statusValue === 'active' ? '停止运行' : '启用运行' }}</span>
            </button>
            <button
              class="minor-action"
              type="button"
              :disabled="!canOperateDigitalEmployee || detailBusy"
              @click="openDigitalEmployeeSchedule(selectedEmployee)"
            >
              <i class="mdi mdi-clock-edit-outline"></i>
              <span>定时设置</span>
            </button>
            <button
              class="minor-action success-action"
              type="button"
              :disabled="!canOperateDigitalEmployee || detailBusy"
              @click="runDigitalEmployeeNow(selectedEmployee)"
            >
              <i class="mdi mdi-play-circle-outline"></i>
              <span>{{ actionBusy(selectedEmployee.id, 'run-digital-now') ? '运行中...' : '立即运行' }}</span>
            </button>
          </div>
        </footer>
      </article>

      <article v-else key="list" class="skill-list panel digital-employees-list">
        <nav class="status-tabs" aria-label="数字员工页签">
          <button
            type="button"
            :class="{ active: activeSection === 'skills' }"
            @click="activeSection = 'skills'"
          >
            数字员工
          </button>
          <button
            type="button"
            :class="{ active: activeSection === 'workRecords' }"
            @click="activeSection = 'workRecords'"
          >
            工作记录
          </button>
        </nav>

        <template v-if="activeSection === 'skills'">
        <div class="list-toolbar">
          <div class="filter-set">
            <label class="search-filter">
              <i class="mdi mdi-magnify"></i>
              <input v-model="keyword" type="search" placeholder="搜索技能名称、编号、执行计划或维护人" />
            </label>

            <AuditPickerFilter
              id="status"
              title="选择资产状态"
              close-label="关闭资产状态选择"
              :active-filter-popover="activeFilterPopover"
              :label="selectedStatusLabel"
              :options="statusOptions"
              :selected-value="selectedStatus"
              @toggle="toggleFilterPopover"
              @close="closeFilterPopover"
              @select="selectFilter('status', $event)"
            />

            <AuditPickerFilter
              id="enabled"
              title="选择启动状态"
              close-label="关闭启动状态选择"
              :active-filter-popover="activeFilterPopover"
              :label="selectedEnabledLabel"
              :options="enabledStateOptions"
              :selected-value="selectedEnabledState"
              @toggle="toggleFilterPopover"
              @close="closeFilterPopover"
              @select="selectFilter('enabled', $event)"
            />

            <AuditPickerFilter
              id="executionMode"
              title="选择执行方式"
              close-label="关闭执行方式选择"
              :active-filter-popover="activeFilterPopover"
              :label="selectedExecutionModeLabel"
              :options="executionModeOptions"
              :selected-value="selectedExecutionMode"
              @toggle="toggleFilterPopover"
              @close="closeFilterPopover"
              @select="selectFilter('executionMode', $event)"
            />
          </div>

          <div class="toolbar-actions">
            <button
              v-if="keyword || activeFilterTokens.length"
              class="ghost-filter-btn"
              type="button"
              @click="resetFilters"
            >
              <i class="mdi mdi-filter-remove-outline"></i>
              <span>清空筛选</span>
            </button>
            <button
              class="create-btn digital-refresh-action"
              type="button"
              :disabled="loading"
              @click="loadEmployees"
            >
              <i class="mdi mdi-refresh"></i>
              <span>{{ loading ? '刷新中...' : '刷新' }}</span>
            </button>
          </div>
        </div>

        <p class="hint">
          <i class="mdi mdi-information-outline"></i>
          集中查看后台自动执行的技能、执行计划和运行状态。
        </p>

        <div v-if="activeFilterTokens.length" class="active-filter-strip">
          <span v-for="token in activeFilterTokens" :key="token" class="active-filter-chip">
            {{ token }}
          </span>
        </div>

        <div
          class="table-wrap digital-table-wrap"
          :class="{ 'is-empty': !loading && !errorMessage && !visibleEmployees.length }"
        >
          <div v-if="loading" class="table-state">
            <TableLoadingState
              variant="panel"
              title="数字员工同步中"
              message="正在读取后台自动执行技能列表"
              icon="mdi mdi-account-cog-outline"
            />
          </div>

          <div v-else-if="errorMessage" class="table-state error">
            <i class="mdi mdi-alert-circle-outline"></i>
            <strong>数字员工加载失败</strong>
            <p>{{ errorMessage }}</p>
          </div>

          <TableEmptyState
            v-else-if="!visibleEmployees.length"
            eyebrow="数字员工"
            title="暂无匹配的数字员工"
            description="当前没有符合搜索条件的后台执行技能。"
            icon="mdi mdi-account-cog-outline"
            tone="theme"
            art-label="STAFF"
            :tips="['数字员工已从规则中心拆出为独立入口', '运行与定时操作统一进入详情后处理']"
          />

          <table v-else class="digital-employees-table">
            <colgroup>
              <col class="col-skill">
              <col class="col-schedule">
              <col class="col-mode">
              <col class="col-skill-type">
              <col class="col-status">
              <col class="col-enabled">
              <col class="col-updated">
            </colgroup>
            <thead>
              <tr>
                <th>技能名称</th>
                <th>执行计划</th>
                <th>触发方式</th>
                <th>技能类型</th>
                <th>资产状态</th>
                <th>启动状态</th>
                <th>最近更新</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="employee in visibleEmployees"
                :key="employee.id"
                @click="openEmployeeDetail(employee)"
              >
                <td>
                  <div class="skill-name-cell">
                    <span class="skill-avatar" :class="employee.badgeTone">{{ employee.short }}</span>
                    <div>
                      <strong>{{ employee.name }}</strong>
                      <span class="skill-list-subtitle">{{ employee.code }}</span>
                    </div>
                  </div>
                </td>
                <td><span class="scope-pill">{{ employee.scope }}</span></td>
                <td>{{ employee.executionMode }}</td>
                <td><span class="scope-pill skill-type-pill">{{ employee.skillCategory }}</span></td>
                <td>
                  <span :class="['status-pill', employee.statusTone]">{{ employee.status }}</span>
                </td>
                <td><span :class="['status-pill', employee.enabledTone]">{{ employee.enabledLabel }}</span></td>
                <td>{{ employee.updatedAt || '-' }}</td>
              </tr>
            </tbody>
          </table>
        </div>

        <footer v-if="!loading && !errorMessage && visibleEmployees.length" class="list-foot">
          <span class="page-summary">当前展示 {{ visibleEmployees.length }} 条数字员工</span>
        </footer>
        </template>

        <DigitalEmployeeWorkRecords
          v-else
          class="digital-work-records-section"
        />
      </article>
    </Transition>

    <DigitalEmployeeScheduleDialog
      v-model="scheduleForm"
      :open="scheduleEditorOpen"
      :target-name="scheduleTarget?.name || ''"
      :preview-label="schedulePreviewLabel"
      :error-message="scheduleEditorError"
      :busy="scheduleEditorBusy"
      :can-save="canOperateDigitalEmployee"
      @close="closeDigitalEmployeeSchedule"
      @save="saveDigitalEmployeeSchedule"
    />
  </section>
</template>

<script setup>
import { computed, onMounted, ref } from 'vue'

import AuditDigitalEmployeeDetail from '../components/audit/AuditDigitalEmployeeDetail.vue'
import AuditPickerFilter from '../components/audit/AuditPickerFilter.vue'
import DigitalEmployeeScheduleDialog from '../components/audit/DigitalEmployeeScheduleDialog.vue'
import DigitalEmployeeWorkRecords from '../components/audit/DigitalEmployeeWorkRecords.vue'
import TableEmptyState from '../components/shared/TableEmptyState.vue'
import TableLoadingState from '../components/shared/TableLoadingState.vue'
import { useSystemState } from '../composables/useSystemState.js'
import { useToast } from '../composables/useToast.js'
import {
  activateAgentAsset,
  createAgentAssetVersion,
  fetchAgentAssetDetail,
  fetchAgentAssets,
  updateAgentAsset
} from '../services/agentAssets.js'
import { runOrchestrator } from '../services/orchestrator.js'
import { isPlatformAdminUser } from '../utils/accessControl.js'
import {
  DIGITAL_EMPLOYEE_SKILL_CATEGORY_OPTIONS,
  buildDigitalEmployeeDetailMeta,
  buildDigitalEmployeeListMeta,
  formatDigitalEmployeeCron,
  isDigitalEmployeeAsset
} from './scripts/auditViewDigitalEmployeeModel.js'
import {
  buildDigitalEmployeeScheduleConfig,
  buildDigitalEmployeeScheduleCron,
  createDigitalEmployeeScheduleForm,
  resolveDigitalEmployeeScheduleValue
} from './scripts/digitalEmployeeScheduleModel.js'
import { incrementVersion } from './scripts/auditViewRuntimeModel.js'
import {
  ENABLED_STATE_OPTIONS,
  formatDateTime,
  normalizeText,
  resolveStatusMeta,
  STATUS_OPTIONS
} from './scripts/auditViewModel.js'

const { currentUser } = useSystemState()
const { toast } = useToast()

const employees = ref([])
const selectedEmployee = ref(null)
const selectedEmployeeId = ref('')
const activeSection = ref('skills')
const keyword = ref('')
const selectedStatus = ref('')
const selectedEnabledState = ref('')
const selectedExecutionMode = ref('')
const activeFilterPopover = ref('')
const loading = ref(false)
const detailLoading = ref(false)
const errorMessage = ref('')
const detailError = ref('')
const actionState = ref('')
const busyEmployeeId = ref('')
const scheduleEditorOpen = ref(false)
const scheduleTarget = ref(null)
const scheduleForm = ref(createDigitalEmployeeScheduleForm())
const scheduleEditorError = ref('')

const isAdmin = computed(() => isPlatformAdminUser(currentUser.value))
const detailBusy = computed(() => Boolean(detailLoading.value || actionState.value))
const canOperateDigitalEmployee = computed(() => isAdmin.value && Boolean(selectedEmployee.value))
const canEditDigitalEmployeeSource = computed(() => canOperateDigitalEmployee.value)
const scheduleEditorBusy = computed(() => actionState.value === 'save-digital-schedule')

const statusOptions = STATUS_OPTIONS
const enabledStateOptions = ENABLED_STATE_OPTIONS
const executionModeOptions = [
  { value: '', label: '全部执行方式' },
  { value: 'timed', label: '定时执行' },
  { value: 'manual', label: '手动触发' }
]

const selectedStatusLabel = computed(() =>
  statusOptions.find((item) => item.value === selectedStatus.value)?.label || '全部状态'
)
const selectedEnabledLabel = computed(() =>
  enabledStateOptions.find((item) => item.value === selectedEnabledState.value)?.label || '全部启动状态'
)
const selectedExecutionModeLabel = computed(() =>
  executionModeOptions.find((item) => item.value === selectedExecutionMode.value)?.label || '全部执行方式'
)
const activeFilterTokens = computed(() => {
  const tokens = []
  if (selectedStatus.value) {
    tokens.push(`资产状态：${selectedStatusLabel.value}`)
  }
  if (selectedEnabledState.value) {
    tokens.push(`启动状态：${selectedEnabledLabel.value}`)
  }
  if (selectedExecutionMode.value) {
    tokens.push(`执行方式：${selectedExecutionModeLabel.value}`)
  }
  return tokens
})

const schedulePreviewLabel = computed(() => {
  try {
    return formatDigitalEmployeeCron(buildDigitalEmployeeScheduleCron(scheduleForm.value))
  } catch {
    return '表达式待确认'
  }
})

const visibleEmployees = computed(() => {
  const searchText = normalizeText(keyword.value).toLowerCase()
  return employees.value.filter((item) => {
    const matchesKeyword = searchText
      ? [
          item.name,
          item.code,
          item.summary,
          item.owner,
          item.scope,
          item.executionMode,
          item.skillCategory,
          item.status,
          item.enabledLabel
        ]
          .filter(Boolean)
          .some((value) => String(value).toLowerCase().includes(searchText))
      : true
    const matchesStatus = selectedStatus.value ? item.statusValue === selectedStatus.value : true
    const matchesEnabled = selectedEnabledState.value
      ? (selectedEnabledState.value === 'enabled') === Boolean(item.isEnabledValue)
      : true
    const matchesExecutionMode = selectedExecutionMode.value
      ? item.executionModeValue === selectedExecutionMode.value
      : true

    return matchesKeyword && matchesStatus && matchesEnabled && matchesExecutionMode
  })
})

function toggleFilterPopover(id) {
  activeFilterPopover.value = activeFilterPopover.value === id ? '' : id
}

function closeFilterPopover() {
  activeFilterPopover.value = ''
}

function selectFilter(type, value) {
  if (type === 'status') {
    selectedStatus.value = value
  }
  if (type === 'enabled') {
    selectedEnabledState.value = value
  }
  if (type === 'executionMode') {
    selectedExecutionMode.value = value
  }
  closeFilterPopover()
}

function resetFilters() {
  keyword.value = ''
  selectedStatus.value = ''
  selectedEnabledState.value = ''
  selectedExecutionMode.value = ''
  closeFilterPopover()
}

function resolveActor() {
  const user = currentUser.value || {}
  return normalizeText(user.name) || normalizeText(user.username) || 'system'
}

function buildEmployeeListItem(asset) {
  const meta = buildDigitalEmployeeListMeta(asset)
  const statusMeta = resolveStatusMeta(asset.status)
  const displayName = meta.name || '数字员工技能'

  return {
    id: asset.id,
    rawCode: asset.code,
    short: displayName.slice(0, 2),
    badgeTone: 'blue',
    name: displayName,
    code: meta.code,
    summary: meta.summary,
    owner: meta.owner,
    scope: meta.scope,
    executionMode: meta.executionMode,
    executionModeValue: meta.executionMode === '定时执行' ? 'timed' : 'manual',
    skillCategory: meta.skillCategory,
    version: asset.working_version || asset.current_version || '-',
    currentVersion: asset.current_version || '-',
    status: statusMeta.label,
    statusValue: asset.status,
    statusTone: statusMeta.tone,
    enabledLabel: meta.enabledLabel,
    enabledTone: meta.enabledTone,
    isEnabledValue: meta.enabled,
    configJson: asset.config_json || {},
    updatedAt: formatDateTime(asset.updated_at),
    updatedAtRaw: asset.updated_at || '',
    digitalEmployee: meta
  }
}

function buildEmployeePlaceholder(employee) {
  return {
    ...employee,
    type: 'digitalEmployees',
    typeLabel: '数字员工',
    currentVersion: employee.currentVersion || employee.version || '-',
    workingVersion: employee.version || '-',
    markdownContent: '',
    loading: true
  }
}

function buildEmployeeDetail(asset) {
  const meta = buildDigitalEmployeeDetailMeta({
    ...asset,
    updated_at: formatDateTime(asset.updated_at)
  })
  const statusMeta = resolveStatusMeta(asset.status)

  return {
    id: asset.id,
    type: 'digitalEmployees',
    typeLabel: '数字员工',
    rawCode: asset.code,
    short: meta.name.slice(0, 2),
    name: meta.name,
    code: meta.code,
    summary: meta.description,
    owner: meta.owner,
    reviewer: meta.reviewer,
    category: meta.category,
    scope: meta.scope,
    version: asset.working_version || asset.current_version || '-',
    currentVersion: asset.current_version || '-',
    workingVersion: asset.working_version || asset.current_version || '-',
    status: statusMeta.label,
    statusValue: asset.status,
    statusTone: statusMeta.tone,
    configJson: asset.config_json || {},
    updatedAt: formatDateTime(asset.updated_at),
    markdownContent: meta.sourceMarkdown,
    digitalEmployee: meta,
    loading: false
  }
}

function sortEmployees(items) {
  return [...items].sort((left, right) =>
    String(right.updatedAtRaw || '').localeCompare(String(left.updatedAtRaw || ''))
  )
}

async function loadEmployees() {
  loading.value = true
  errorMessage.value = ''

  try {
    const payload = await fetchAgentAssets({ assetType: 'task' })
    const items = Array.isArray(payload)
      ? payload.filter(isDigitalEmployeeAsset).map(buildEmployeeListItem)
      : []

    employees.value = sortEmployees(items)
  } catch (error) {
    errorMessage.value = error?.message || '数字员工数据加载失败，请稍后重试。'
    toast(errorMessage.value)
  } finally {
    loading.value = false
  }
}

async function loadEmployeeDetail(assetId, placeholder = null, options = {}) {
  if (!assetId) {
    return
  }

  selectedEmployeeId.value = assetId
  selectedEmployee.value = placeholder
    ? buildEmployeePlaceholder(placeholder)
    : selectedEmployee.value || { id: assetId, name: '数字员工', loading: true, digitalEmployee: {} }
  detailLoading.value = true
  detailError.value = ''

  try {
    const detail = await fetchAgentAssetDetail(assetId)
    selectedEmployee.value = buildEmployeeDetail(detail)
  } catch (error) {
    detailError.value = error?.message || '数字员工详情加载失败，请稍后重试。'
    if (!options.silent) {
      toast(detailError.value)
    }
  } finally {
    detailLoading.value = false
  }
}

function openEmployeeDetail(employee) {
  loadEmployeeDetail(employee.id, employee).catch(() => {})
}

function closeEmployeeDetail() {
  closeDigitalEmployeeSchedule()
  selectedEmployee.value = null
  selectedEmployeeId.value = ''
  detailError.value = ''
  detailLoading.value = false
}

async function refreshAfterMutation(assetId) {
  await loadEmployees()
  if (selectedEmployee.value && selectedEmployeeId.value === assetId) {
    const placeholder = employees.value.find((item) => item.id === assetId) || selectedEmployee.value
    await loadEmployeeDetail(assetId, placeholder, { silent: true })
  }
}

function actionBusy(assetId, action) {
  return busyEmployeeId.value === assetId && actionState.value === action
}

async function toggleDigitalEmployeeRunning(employee) {
  if (!employee || !canOperateDigitalEmployee.value || actionState.value) {
    return
  }

  const assetId = employee.id
  const shouldEnable = employee.statusValue !== 'active'
  actionState.value = 'toggle-digital-running'
  busyEmployeeId.value = assetId

  try {
    await (shouldEnable
      ? activateAgentAsset(assetId, { actor: resolveActor() })
      : updateAgentAsset(assetId, { status: 'disabled' }, { actor: resolveActor() }))
    await refreshAfterMutation(assetId)
    toast(shouldEnable ? '已启用运行。' : '已停止运行。')
  } catch (error) {
    toast(error?.message || '运行状态更新失败，请稍后重试。')
  } finally {
    actionState.value = ''
    busyEmployeeId.value = ''
  }
}

async function saveDigitalEmployeeSource() {
  if (!selectedEmployee.value || !canEditDigitalEmployeeSource.value || detailBusy.value) {
    return
  }

  const markdown = normalizeText(selectedEmployee.value.markdownContent)
  if (!markdown) {
    toast('Skills Markdown 源文件不能为空。')
    return
  }

  const nextVersion = incrementVersion(selectedEmployee.value.currentVersion)
  actionState.value = 'save-digital-source'
  busyEmployeeId.value = selectedEmployee.value.id

  try {
    await createAgentAssetVersion(
      selectedEmployee.value.id,
      {
        version: nextVersion,
        content: markdown,
        content_type: 'markdown',
        change_note: '通过数字员工页面更新 Skills Markdown 源文件。',
        created_by: resolveActor()
      },
      { actor: resolveActor() }
    )
    await refreshAfterMutation(selectedEmployee.value.id)
    toast(`Skills 源文件已保存为 ${nextVersion}。`)
  } catch (error) {
    toast(error?.message || 'Skills 源文件保存失败，请稍后重试。')
  } finally {
    actionState.value = ''
    busyEmployeeId.value = ''
  }
}

function openDigitalEmployeeSchedule(employee) {
  if (!employee || !canOperateDigitalEmployee.value) {
    return
  }
  scheduleTarget.value = employee
  scheduleForm.value = createDigitalEmployeeScheduleForm(resolveDigitalEmployeeScheduleValue(employee))
  scheduleEditorError.value = ''
  scheduleEditorOpen.value = true
}

function closeDigitalEmployeeSchedule() {
  if (scheduleEditorBusy.value) {
    return
  }
  scheduleEditorOpen.value = false
  scheduleTarget.value = null
  scheduleEditorError.value = ''
}

async function saveDigitalEmployeeSchedule() {
  const employee = scheduleTarget.value || selectedEmployee.value
  if (!employee || !canOperateDigitalEmployee.value || actionState.value) {
    return
  }

  let cron = ''
  try {
    cron = buildDigitalEmployeeScheduleCron(scheduleForm.value)
  } catch (error) {
    scheduleEditorError.value = error?.message || '定时计划格式不正确。'
    return
  }

  const nextConfig = buildDigitalEmployeeScheduleConfig(employee.configJson, cron)
  nextConfig.skill_category = employee.digitalEmployee?.skillCategory || employee.skillCategory || '整理'
  nextConfig.skill_category_options = DIGITAL_EMPLOYEE_SKILL_CATEGORY_OPTIONS

  actionState.value = 'save-digital-schedule'
  busyEmployeeId.value = employee.id

  try {
    await updateAgentAsset(employee.id, { config_json: nextConfig }, { actor: resolveActor() })
    await refreshAfterMutation(employee.id)
    scheduleEditorOpen.value = false
    scheduleTarget.value = null
    scheduleEditorError.value = ''
    toast(cron ? `定时计划已更新为 ${formatDigitalEmployeeCron(cron)}。` : '已改为手动触发。')
  } catch (error) {
    scheduleEditorError.value = error?.message || '定时计划保存失败，请稍后重试。'
    toast(scheduleEditorError.value)
  } finally {
    actionState.value = ''
    busyEmployeeId.value = ''
  }
}

async function runDigitalEmployeeNow(employee) {
  if (!employee || !canOperateDigitalEmployee.value || actionState.value) {
    return
  }

  actionState.value = 'run-digital-now'
  busyEmployeeId.value = employee.id

  try {
    const result = await runOrchestrator({
      source: 'schedule',
      task_id: employee.id,
      message: employee.name,
      context_json: {
        manual_trigger: true,
        entry: 'digital_employees'
      }
    })
    toast(`已发起立即运行，Run ID：${result?.run_id || '-'}`)
  } catch (error) {
    toast(error?.message || '立即运行失败，请稍后重试。')
  } finally {
    actionState.value = ''
    busyEmployeeId.value = ''
  }
}

onMounted(() => {
  loadEmployees().catch(() => {})
})
</script>

<style scoped src="../assets/styles/views/audit-view.css"></style>
<style scoped src="../assets/styles/views/audit-view-part2.css"></style>
<style scoped src="../assets/styles/views/digital-employees-view.css"></style>
