<% @page_title = '任务报告 - 清巡' %>
<% @active_page = 'tasks' %>

<div id="app">
  <div class="app-wrapper">
    <main class="main-content">
      <div class="page-header">
        <h1>任务报告</h1>
        <div style="display: flex; gap: 8px;">
          <el-dropdown v-if="report" trigger="click">
            <el-button type="primary">
              导出报告
              <el-icon class="el-icon--right"><arrow-down /></el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="exportReport('json')">导出 JSON</el-dropdown-item>
                <el-dropdown-item @click="exportReport('html')">导出 HTML</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <el-button @click="goBack">返回详情</el-button>
        </div>
      </div>

      <div v-loading="loading">
        <template v-if="report">
          <!-- 报告头部 -->
          <el-card class="card">
            <div class="report-header">
              <div>
                <h2 style="margin-bottom: 8px;">{{ report.task.name }}</h2>
                <div style="color: #909399; font-size: 14px;">
                  <el-tag :type="getStatusType(report.task.status)" size="small" style="margin-right: 12px;">
                    {{ report.task.status_text }}
                  </el-tag>
                  <span v-if="report.task.started_at">开始: {{ formatTime(report.task.started_at) }}</span>
                  <span v-if="report.task.completed_at" style="margin-left: 12px;">完成: {{ formatTime(report.task.completed_at) }}</span>
                  <span v-if="report.task.duration" style="margin-left: 12px;">耗时: {{ report.task.duration }}</span>
                </div>
              </div>
            </div>
          </el-card>

          <!-- 统计概览 -->
          <el-card class="card" style="margin-top: 16px;">
            <template #header>
              <div class="card-header">
                <h2>概览统计</h2>
              </div>
            </template>
            <div class="stats-grid">
              <div class="stat-card">
                <div class="stat-value">{{ report.statistics.total_devices }}</div>
                <div class="stat-label">总设备数</div>
              </div>
              <div class="stat-card">
                <div class="stat-value" style="color: #67c23a;">{{ report.statistics.all_success_devices }}</div>
                <div class="stat-label">全部成功</div>
              </div>
              <div class="stat-card">
                <div class="stat-value" style="color: #e6a23c;">{{ report.statistics.partial_success_devices }}</div>
                <div class="stat-label">部分成功</div>
              </div>
              <div class="stat-card">
                <div class="stat-value" style="color: #f56c6c;">{{ report.statistics.all_failed_devices }}</div>
                <div class="stat-label">全部失败</div>
              </div>
              <div class="stat-card">
                <div class="stat-value">{{ report.statistics.total_scripts }}</div>
                <div class="stat-label">总脚本数</div>
              </div>
              <div class="stat-card">
                <div class="stat-value" style="color: #409eff;">{{ report.statistics.script_success_rate }}</div>
                <div class="stat-label">脚本成功率</div>
              </div>
            </div>
          </el-card>

          <!-- 视图切换 -->
          <el-card class="card" style="margin-top: 16px;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
              <h2 style="margin: 0;">执行详情</h2>
              <el-button-group>
                <el-button :type="viewMode === 'flat' ? 'primary' : ''" size="small" @click="setViewMode('flat')">扁平表格</el-button>
                <el-button :type="viewMode === 'split' ? 'primary' : ''" size="small" @click="setViewMode('split')">左右分栏</el-button>
              </el-button-group>
            </div>

            <!-- 视图A: 扁平表格 -->
            <div v-show="viewMode === 'flat'">
              <el-table :data="report.flat_scripts" style="width: 100%" :row-class-name="getFlatTableRowClassName">
                <el-table-column prop="device_ip" label="设备IP" width="130" fixed="left">
                  <template #default="scope">
                    <strong>{{ scope.row.device_ip }}</strong>
                  </template>
                </el-table-column>
                <el-table-column prop="device_name" label="设备名称" width="150">
                </el-table-column>
                <el-table-column prop="device_model" label="型号" width="120">
                </el-table-column>
                <el-table-column prop="name" label="脚本名称" min-width="180">
                </el-table-column>
                <el-table-column prop="status" label="状态" width="100">
                  <template #default="scope">
                    <el-tag :type="getScriptStatusType(scope.row.status)" size="small">
                      {{ scope.row.status_text }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="duration" label="耗时" width="90">
                </el-table-column>
                <el-table-column prop="conclusion" label="结论摘要" min-width="200" show-overflow-tooltip>
                  <template #default="scope">
                    <span :style="scope.row.status === 'failed' ? 'color: #f56c6c;' : ''">
                      {{ scope.row.conclusion || scope.row.error || '-' }}
                    </span>
                  </template>
                </el-table-column>
                <el-table-column label="操作" width="80" fixed="right">
                  <template #default="scope">
                    <el-button type="primary" size="small" link @click="showScriptLog(scope.row)">
                      日志
                    </el-button>
                  </template>
                </el-table-column>
              </el-table>
            </div>

            <!-- 视图B: 左右分栏 -->
            <div v-show="viewMode === 'split'" class="split-view">
              <div class="split-left">
                <div class="device-list">
                  <div
                    v-for="device in report.devices"
                    :key="device.id"
                    class="device-item"
                    :class="{ 'device-item--active': selectedDeviceId === device.id }"
                    @click="selectDevice(device)"
                  >
                    <div class="device-item__header">
                      <span class="device-status-icon" :class="device.status">
                        {{ getDeviceStatusIcon(device.status) }}
                      </span>
                      <span class="device-name">{{ device.name }}</span>
                    </div>
                    <div class="device-item__meta">
                      <span>{{ device.device_ip }}</span>
                      <span class="device-scripts-count">
                        {{ device.scripts_success }}/{{ device.scripts_count }}
                      </span>
                    </div>
                  </div>
                </div>
              </div>
              <div class="split-right">
                <template v-if="selectedDevice">
                  <div class="selected-device-header">
                    <div>
                      <h3 style="margin: 0;">{{ selectedDevice.name }}</h3>
                      <div style="color: #909399; font-size: 13px; margin-top: 4px;">
                        {{ selectedDevice.device_ip }} · {{ selectedDevice.device_model || '未知型号' }}
                        <span style="margin-left: 12px;">
                          <el-tag :type="getDeviceStatusType(selectedDevice.status)" size="small">
                            {{ selectedDevice.status_text }}
                          </el-tag>
                        </span>
                        <span v-if="selectedDevice.duration" style="margin-left: 8px;">
                          耗时: {{ selectedDevice.duration }}
                        </span>
                      </div>
                    </div>
                  </div>
                  <el-table :data="selectedDevice.scripts" style="width: 100%; margin-top: 16px;">
                    <el-table-column prop="name" label="脚本名称" min-width="200">
                    </el-table-column>
                    <el-table-column prop="status" label="状态" width="100">
                      <template #default="scope">
                        <el-tag :type="getScriptStatusType(scope.row.status)" size="small">
                          {{ scope.row.status_text }}
                        </el-tag>
                      </template>
                    </el-table-column>
                    <el-table-column prop="duration" label="耗时" width="90">
                    </el-table-column>
                    <el-table-column prop="conclusion" label="结论摘要" min-width="250" show-overflow-tooltip>
                      <template #default="scope">
                        <span :style="scope.row.status === 'failed' ? 'color: #f56c6c;' : ''">
                          {{ scope.row.conclusion || scope.row.error || '-' }}
                        </span>
                      </template>
                    </el-table-column>
                    <el-table-column label="操作" width="80" fixed="right">
                      <template #default="scope">
                        <el-button
                          type="primary"
                          size="small"
                          link
                          @click="showScriptLogFromDevice(scope.row, selectedDevice)"
                        >
                          日志
                        </el-button>
                      </template>
                    </el-table-column>
                  </el-table>
                </template>
                <div v-else class="split-placeholder">
                  <el-empty description="请选择左侧设备查看详情" />
                </div>
              </div>
            </div>
          </el-card>

          <!-- 错误汇总 -->
          <el-card v-if="report.errors && report.errors.length > 0" class="card" style="margin-top: 16px;">
            <template #header>
              <div class="card-header">
                <h2 style="color: #f56c6c;">🔴 错误汇总</h2>
              </div>
            </template>
            <el-collapse>
              <el-collapse-item v-for="(error, index) in report.errors" :key="index">
                <template #title>
                  <div style="display: flex; justify-content: space-between; align-items: center; width: 100%; padding-right: 16px;">
                    <span style="color: #f56c6c;">{{ error.error.length > 80 ? error.error.substring(0, 80) + '...' : error.error }}</span>
                    <el-tag type="danger" size="small">{{ error.count }} 项</el-tag>
                  </div>
                </template>
                <div>
                  <div style="color: #606266; margin-bottom: 12px;">影响的设备和脚本：</div>
                  <el-tag
                    v-for="item in error.affected_devices"
                    :key="item.script_id"
                    style="margin: 4px;"
                    size="small"
                  >
                    {{ item.device_name }} - {{ item.script_name }}
                  </el-tag>
                </div>
              </el-collapse-item>
            </el-collapse>
          </el-card>
        </template>
      </div>
    </main>
  </div>

  <!-- 日志对话框 -->
  <el-dialog
    v-model="logDialogVisible"
    :title="`脚本日志 - ${currentScript?.name || ''}`"
    width="70%"
  >
    <div v-if="currentScript">
      <div style="margin-bottom: 16px;">
        <el-tag :type="getScriptStatusType(currentScript.status)" size="small">
          {{ currentScript.status_text }}
        </el-tag>
        <span v-if="currentScript.started_at" style="margin-left: 12px; color: #909399;">
          开始: {{ formatTime(currentScript.started_at) }}
        </span>
        <span v-if="currentScript.completed_at" style="margin-left: 12px; color: #909399;">
          完成: {{ formatTime(currentScript.completed_at) }}
        </span>
      </div>
      <div v-if="currentScript.error" style="margin-bottom: 16px; color: #f56c6c;">
        <strong>错误:</strong> {{ currentScript.error }}
      </div>
      <div style="margin-bottom: 12px;">
        <el-button type="primary" size="small" @click="refreshScriptLog">
          刷新日志
        </el-button>
        <el-button type="primary" size="small" @click="copyLog">
          复制日志
        </el-button>
      </div>
      <div class="json-preview" style="white-space: normal; max-height: 400px; overflow-y: auto; overflow-x: auto; background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 4px; font-family: monospace; font-size: 13px;" v-html="formattedScriptLog">
      </div>
    </div>
    <template #footer>
      <el-button @click="logDialogVisible = false">关闭</el-button>
    </template>
  </el-dialog>
</div>

<script>
  window.taskId = <%= @task_id.to_json %>;
</script>

<% content_for :xxx do %>
<style>
  .stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 16px;
  }
  .stat-card {
    background: #f5f7fa;
    padding: 20px;
    border-radius: 8px;
    text-align: center;
  }
  .stat-value {
    font-size: 32px;
    font-weight: bold;
    color: #303133;
  }
  .stat-label {
    font-size: 13px;
    color: #909399;
    margin-top: 8px;
  }
  .split-view {
    display: flex;
    height: 500px;
    border: 1px solid #ebeef5;
    border-radius: 8px;
    overflow: hidden;
  }
  .split-left {
    width: 280px;
    border-right: 1px solid #ebeef5;
    background: #fafafa;
    overflow-y: auto;
  }
  .split-right {
    flex: 1;
    padding: 16px;
    overflow-y: auto;
  }
  .device-list {
    padding: 8px;
  }
  .device-item {
    padding: 12px;
    background: white;
    border: 1px solid #ebeef5;
    border-radius: 6px;
    margin-bottom: 8px;
    cursor: pointer;
    transition: all 0.2s;
  }
  .device-item:hover {
    border-color: #409eff;
  }
  .device-item--active {
    border-color: #409eff;
    background: #ecf5ff;
  }
  .device-item__header {
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .device-status-icon {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    flex-shrink: 0;
  }
  .device-status-icon.completed { background: #e1f3d8; }
  .device-status-icon.partial { background: #faecd8; }
  .device-status-icon.failed { background: #fde2e2; }
  .device-status-icon.running { background: #d9ecff; }
  .device-status-icon.pending { background: #f4f4f5; }
  .device-name {
    font-weight: 500;
    color: #303133;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .device-item__meta {
    display: flex;
    justify-content: space-between;
    margin-top: 6px;
    font-size: 12px;
    color: #909399;
  }
  .device-scripts-count {
    font-weight: 500;
  }
  .selected-device-header {
    padding-bottom: 12px;
    border-bottom: 1px solid #ebeef5;
  }
  .split-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
  }
  .flat-table-row-device-group {
    background: #fafafa;
  }
  .report-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
</style>

<script>
  const { createApp, ref, reactive, onMounted, computed, watch } = Vue;
  const app = createApp({
    setup() {
      const taskId = window.taskId;
      const report = ref(null);
      const loading = ref(true);
      const viewMode = ref('flat');
      const selectedDeviceId = ref(null);
      const selectedDevice = ref(null);

      const logDialogVisible = ref(false);
      const currentScript = ref(null);
      const currentScriptLog = ref('');
      const currentScriptDevice = ref(null);

      // 格式化脚本日志（HTML转义 + 换行符处理）
      const formattedScriptLog = computed(() => {
        const log = currentScriptLog.value;
        if (!log || log.trim() === '') return '暂无日志';
        // HTML转义
        const escaped = log
          .replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
          .replace(/'/g, '&#039;');
        // 换行符转换
        return escaped.replace(/\r\n/g, '<br>').replace(/\n/g, '<br>');
      });

      // 选择设备
      const selectDevice = (device) => {
        selectedDeviceId.value = device.id;
        selectedDevice.value = device;
      };

      // 获取扁平表格行样式
      const getFlatTableRowClassName = ({ rowIndex }) => {
        return '';
      };

      // 获取设备状态图标
      const getDeviceStatusIcon = (status) => {
        const icons = {
          'completed': '✓',
          'partial': '!',
          'failed': '✗',
          'running': '…',
          'pending': '○'
        };
        return icons[status] || '○';
      };

      // 获取设备状态类型
      const getDeviceStatusType = (status) => {
        const types = {
          'completed': 'success',
          'partial': 'warning',
          'failed': 'danger',
          'running': 'info',
          'pending': 'info'
        };
        return types[status] || 'info';
      };

      // 获取脚本状态类型
      const getScriptStatusType = (status) => {
        const types = {
          'completed': 'success',
          'failed': 'danger',
          'running': 'info',
          'pending': 'warning',
          'cancelled': 'info'
        };
        return types[status] || 'info';
      };

      // 获取任务状态类型
      const getStatusType = (status) => {
        const types = {
          'completed': 'success',
          'failed': 'danger',
          'running': 'info',
          'pending': 'warning',
          'cancelled': 'info'
        };
        return types[status] || 'info';
      };

      // 格式化时间
      const formatTime = (timestamp) => {
        if (!timestamp) return '';
        const date = new Date(timestamp);
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        const hours = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        const seconds = String(date.getSeconds()).padStart(2, '0');
        return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
      };

      // 从扁平表格显示日志
      const showScriptLog = async (script) => {
        currentScript.value = script;
        currentScriptDevice.value = {
          device_ip: script.device_ip,
          id: script.device_id
        };
        await loadScriptLog();
        logDialogVisible.value = true;
      };

      // 从设备视图显示日志
      const showScriptLogFromDevice = async (script, device) => {
        currentScript.value = script;
        currentScriptDevice.value = device;
        await loadScriptLog();
        logDialogVisible.value = true;
      };

      // 加载脚本日志
      const loadScriptLog = async () => {
        if (!currentScript.value || !currentScriptDevice.value || !report.value?.task?.execution_id) return;

        try {
          const deviceIp = currentScriptDevice.value.device_ip;
          const scriptName = currentScript.value.script_name || currentScript.value.name;
          const executionId = report.value.task.execution_id;

          if (deviceIp && scriptName && executionId) {
            const response = await fetch(`/api/executions/${encodeURIComponent(executionId)}/logs/${encodeURIComponent(deviceIp)}/${encodeURIComponent(scriptName)}`);
            if (response.ok) {
              const data = await response.json();
              if (data?.log && data.log.trim() !== '') {
                currentScriptLog.value = data.log;
                return;
              }
            }
          }
        } catch (err) {
          console.error('读取日志失败:', err);
        }

        // 如果文件日志读取失败，使用内存中的 output
        currentScriptLog.value = currentScript.value?.output || currentScript.value?.log || '暂无日志';
      };

      // 刷新日志
      const refreshScriptLog = loadScriptLog;

      // 复制日志
      const copyLog = async () => {
        try {
          await navigator.clipboard.writeText(currentScriptLog.value);
          ElementPlus.ElMessage.success('日志已复制到剪贴板');
        } catch (err) {
          ElementPlus.ElMessage.error('复制失败');
        }
      };

      // 导出报告
      const exportReport = (format) => {
        const url = `/api/tasks/${taskId}/report/export?format=${format}`;
        window.open(url, '_blank');
      };

      // 返回详情页
      const goBack = () => {
        window.location.href = `/tasks/${taskId}/vue`;
      };

      // 获取报告数据
      const fetchReport = async () => {
        try {
          loading.value = true;
          const response = await fetch(`/api/tasks/${taskId}/report`);
          if (!response.ok) {
            throw new Error('获取报告失败');
          }
          report.value = await response.json();

          // 默认选中第一个设备
          if (report.value.devices && report.value.devices.length > 0) {
            selectDevice(report.value.devices[0]);
          }
        } catch (error) {
          console.error('获取报告失败:', error);
          ElementPlus.ElMessage.error('获取报告失败');
        } finally {
          loading.value = false;
        }
      };

      // 切换视图模式
      const setViewMode = (mode) => {
        viewMode.value = mode;
        localStorage.setItem('report_view_mode', mode);
      };

      onMounted(() => {
        // 从 localStorage 恢复视图模式
        const savedMode = localStorage.getItem('report_view_mode');
        if (savedMode === 'flat' || savedMode === 'split') {
          viewMode.value = savedMode;
        }
        fetchReport();
      });

      return {
        report,
        loading,
        viewMode,
        setViewMode,
        selectedDeviceId,
        selectedDevice,
        logDialogVisible,
        currentScript,
        currentScriptLog,
        selectDevice,
        getFlatTableRowClassName,
        getDeviceStatusIcon,
        getDeviceStatusType,
        getScriptStatusType,
        getStatusType,
        formatTime,
        showScriptLog,
        showScriptLogFromDevice,
        refreshScriptLog,
        copyLog,
        exportReport,
        formattedScriptLog,
        goBack
      };
    }
  });
  app.use(ElementPlus);
  app.mount('#app');
</script>
<% end %>
