<script setup lang="ts">
import type { AgentBuiltinToolKey } from '../builtin-tools';
import type { AgentInfo } from '../types';

import { ElForm, ElMessageBox, ElSwitch, ElTooltip } from 'element-plus';

const props = defineProps<{
  agent: AgentInfo;
  canDisableShellApproval: boolean;
}>();

const emit = defineEmits<{ change: [] }>();

const builtinToolOptions: Array<{
  description: string;
  key: AgentBuiltinToolKey;
  label: string;
}> = [
  { description: '读取工作区内的 UTF-8 文本', key: 'read', label: '读取文件' },
  { description: '在工作区内写入或插入文本', key: 'write', label: '写入文件' },
  {
    description: '以补丁方式安全修改工作区文件',
    key: 'patch',
    label: '补丁修改',
  },
  { description: '执行平台白名单中的受控命令', key: 'shell', label: 'Shell' },
  {
    description: '将工作区文件发布为可下载产物',
    key: 'artifactPublish',
    label: '发布产物',
  },
];

function builtinTool(key: AgentBuiltinToolKey) {
  return props.agent.executionConfigJson!.builtinTools![key];
}

function handleBuiltinToolEnabledChange(key: AgentBuiltinToolKey) {
  if (key === 'shell' && !props.canDisableShellApproval) {
    builtinTool('shell').approvalRequired = true;
    delete props.agent.executionConfigJson!.builtinTools!
      .shellApprovalRiskConfirmed;
  }
  emit('change');
}

async function confirmUnsafeShellExecution() {
  try {
    await ElMessageBox.confirm(
      '关闭后，命令和脚本将以后端服务权限在宿主环境运行，当前没有沙箱隔离。确认继续？',
      '关闭 Shell 调用确认',
      {
        cancelButtonText: '保持开启',
        confirmButtonText: '确认关闭',
        type: 'warning',
      },
    );
    props.agent.executionConfigJson!.builtinTools!.shellApprovalRiskConfirmed = true;
    return true;
  } catch {
    return false;
  }
}

async function confirmBuiltinToolEnabledChange(key: AgentBuiltinToolKey) {
  if (
    key !== 'shell' ||
    builtinTool('shell').enabled ||
    builtinTool('shell').approvalRequired
  ) {
    return true;
  }
  if (!props.canDisableShellApproval) {
    builtinTool('shell').approvalRequired = true;
    return true;
  }
  return confirmUnsafeShellExecution();
}

async function confirmShellApprovalChange() {
  if (!props.canDisableShellApproval) {
    return false;
  }
  if (!builtinTool('shell').approvalRequired) {
    delete props.agent.executionConfigJson!.builtinTools!
      .shellApprovalRiskConfirmed;
    return true;
  }
  return confirmUnsafeShellExecution();
}

function handleApprovalChange(key: AgentBuiltinToolKey, value: unknown) {
  if (key === 'shell' && value === true) {
    delete props.agent.executionConfigJson!.builtinTools!
      .shellApprovalRiskConfirmed;
  }
  emit('change');
}
</script>

<template>
  <ElForm class="agent-builtin-tools">
    <section aria-labelledby="builtin-tools-description">
      <div class="agent-builtin-tools__head">
        <div
          id="builtin-tools-description"
          class="agent-builtin-tools__description"
        >
          为当前智能体配置工作区能力
        </div>
        <div class="agent-builtin-tools__columns" aria-hidden="true">
          <span>启用</span>
          <span>调用前确认</span>
        </div>
      </div>
      <div class="agent-builtin-tools__list">
        <div
          v-for="item in builtinToolOptions"
          :key="item.key"
          class="agent-builtin-tools__row"
        >
          <div class="agent-builtin-tools__copy">
            <div class="agent-builtin-tools__name">{{ item.label }}</div>
            <div class="agent-builtin-tools__description">
              {{ item.description }}
            </div>
          </div>
          <ElSwitch
            v-model="builtinTool(item.key).enabled"
            :aria-label="`启用${item.label}`"
            :before-change="() => confirmBuiltinToolEnabledChange(item.key)"
            @change="handleBuiltinToolEnabledChange(item.key)"
          />
          <ElTooltip
            :disabled="item.key !== 'shell' || canDisableShellApproval"
            content="Shell 调用确认仅平台超级管理员可以关闭"
            effect="light"
            placement="top"
          >
            <span class="agent-builtin-tools__approval">
              <ElSwitch
                v-model="builtinTool(item.key).approvalRequired"
                :aria-label="`${item.label}调用前确认`"
                :before-change="
                  item.key === 'shell' ? confirmShellApprovalChange : undefined
                "
                :disabled="
                  !builtinTool(item.key).enabled ||
                  (item.key === 'shell' && !canDisableShellApproval)
                "
                @change="handleApprovalChange(item.key, $event)"
              />
            </span>
          </ElTooltip>
        </div>
      </div>
    </section>
  </ElForm>
</template>

<style scoped>
.agent-builtin-tools {
  --agent-tool-approval-column: 96px;
  --agent-tool-enabled-column: 48px;

  padding: var(--space-4);
}

.agent-builtin-tools__head {
  display: grid;
  grid-template-columns:
    minmax(0, 1fr)
    calc(var(--agent-tool-enabled-column) + var(--agent-tool-approval-column));
  gap: var(--space-3);
  align-items: end;
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.agent-builtin-tools__description,
.agent-builtin-tools__columns {
  font-size: 12px;
  line-height: 18px;
  color: var(--el-text-color-secondary);
}

.agent-builtin-tools__columns {
  display: grid;
  grid-template-columns: var(--agent-tool-enabled-column) var(
      --agent-tool-approval-column
    );
  text-align: center;
}

.agent-builtin-tools__list {
  display: flex;
  flex-direction: column;
}

.agent-builtin-tools__row {
  display: grid;
  grid-template-columns:
    minmax(0, 1fr) var(--agent-tool-enabled-column)
    var(--agent-tool-approval-column);
  gap: var(--space-3);
  align-items: center;
  min-height: 56px;
  border-bottom: 1px solid var(--el-border-color-extra-light);
}

.agent-builtin-tools__copy {
  min-width: 0;
}

.agent-builtin-tools__name {
  font-size: 13px;
  font-weight: 500;
  line-height: 20px;
  color: var(--el-text-color-primary);
}

.agent-builtin-tools__copy .agent-builtin-tools__description {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-builtin-tools__row > :deep(.el-switch),
.agent-builtin-tools__approval {
  justify-self: center;
}

.agent-builtin-tools__approval {
  display: inline-flex;
}

@media (max-width: 480px) {
  .agent-builtin-tools {
    --agent-tool-approval-column: 72px;

    padding: var(--space-3);
  }

  .agent-builtin-tools__head,
  .agent-builtin-tools__row {
    gap: var(--space-2);
  }

  .agent-builtin-tools__row {
    min-height: calc(var(--space-8) * 2);
  }

  .agent-builtin-tools__copy .agent-builtin-tools__description {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    white-space: normal;
  }
}
</style>
