<template>
  <div class="dev-page">
    <!-- 页面头部 -->
    <div class="page-header">
      <div>
        <h2 class="page-title">🔨 构建任务</h2>
        <p class="page-desc">管理应用的 CI/CD 构建任务，触发构建、查看构建状态和日志</p>
      </div>
      <a-space>
        <a-button @click="loadBuilds">
          <template #icon><ReloadOutlined /></template>
          刷新
        </a-button>
        <a-button type="primary" :loading="triggering" @click="showTriggerModal = true">
          <template #icon><PlayCircleOutlined /></template>
          触发构建
        </a-button>
      </a-space>
    </div>

    <!-- 统计卡片 -->
    <a-row :gutter="[16, 16]" class="mb-6">
      <a-col :xs="12" :md="6" v-for="stat in buildStats" :key="stat.key">
        <div class="stat-card" :class="stat.color">
          <div class="stat-icon">{{ stat.icon }}</div>
          <div class="stat-info">
            <div class="stat-value">{{ stat.value }}</div>
            <div class="stat-label">{{ stat.label }}</div>
          </div>
        </div>
      </a-col>
    </a-row>

    <!-- 筛选栏 -->
    <div class="panel mb-4">
      <div class="panel-header">
        <span class="panel-title">📋 构建记录</span>
        <a-space>
          <a-select v-model:value="filterStatus" style="width: 120px" placeholder="构建状态" allow-clear @change="loadBuilds">
            <a-select-option value="">全部状态</a-select-option>
            <a-select-option value="pending">排队中</a-select-option>
            <a-select-option value="running">构建中</a-select-option>
            <a-select-option value="success">成功</a-select-option>
            <a-select-option value="failed">失败</a-select-option>
            <a-select-option value="cancelled">已取消</a-select-option>
          </a-select>
          <a-select v-model:value="filterAppId" style="width: 200px" placeholder="选择应用" allow-clear @change="loadBuilds">
            <a-select-option v-for="app in apps" :key="app.productId" :value="app.productId">
              {{ app.productName }}
            </a-select-option>
          </a-select>
          <a-input-search v-model:value="searchKeyword" placeholder="构建编号/分支" style="width: 180px" @search="loadBuilds" />
        </a-space>
      </div>

      <!-- 构建列表 -->
      <a-spin :spinning="loading">
        <div v-if="builds.length > 0" class="build-list">
          <div v-for="build in builds" :key="build.id" class="build-item" :class="'status-' + build.status">
            <div class="build-status-bar" :class="build.status">
              <div class="status-indicator">
                <span class="status-dot"></span>
                <span class="status-text">{{ statusText(build.status) }}</span>
              </div>
              <span class="build-time">{{ formatTime(build.createTime) }}</span>
            </div>

            <div class="build-content">
              <div class="build-main">
                <div class="build-info">
                  <div class="build-number">
                    <span class="ci-badge" :class="build.ciType">{{ ciTypeText(build.ciType) }}</span>
                    <span class="number-text">#{{ build.buildNumber || build.id }}</span>
                  </div>
                  <div class="build-meta">
                    <span v-if="build.branch" class="meta-item">
                      <CodeSandboxOutlined /> {{ build.branch }}
                    </span>
                    <span v-if="build.commitAuthor" class="meta-item">
                      <UserOutlined /> {{ build.commitAuthor }}
                    </span>
                    <span v-if="build.duration" class="meta-item">
                      <ClockCircleOutlined /> {{ formatDuration(build.duration) }}
                    </span>
                  </div>
                  <div v-if="build.commitMessage" class="commit-message">{{ build.commitMessage }}</div>
                </div>
              </div>

              <div class="build-actions">
                <a-button size="small" type="link" @click="viewLog(build)">查看日志</a-button>

                <template v-if="build.status === 'pending' || build.status === 'running'">
                  <a-popconfirm title="确定要取消此构建？" @confirm="handleCancel(build)">
                    <a-button danger size="small">取消</a-button>
                  </a-popconfirm>
                </template>

                <template v-if="build.status === 'failed'">
                  <a-button type="primary" size="small" @click="handleRetry(build)">
                    <template #icon><ReloadOutlined /></template>
                    重试
                  </a-button>
                </template>

                <template v-if="build.artifactUrl">
                  <a-button size="small" type="link">
                    <template #icon><DownloadOutlined /></template>
                    <a :href="build.artifactUrl" target="_blank">下载产物</a>
                  </a-button>
                </template>
              </div>
            </div>

            <div v-if="build.status === 'failed' && build.errorMessage" class="build-error">
              <WarningOutlined /> {{ build.errorMessage }}
            </div>
          </div>
        </div>

        <a-empty v-else description="暂无构建记录" class="py-8">
          <template #image>
            <div class="empty-icon">🔨</div>
          </template>
        </a-empty>
      </a-spin>

      <!-- 分页 -->
      <div v-if="pagination.total > 0" class="pagination-wrapper">
        <a-pagination
          v-model:current="pagination.current"
          v-model:pageSize="pagination.pageSize"
          :total="pagination.total"
          :show-size-changer="true"
          :show-quick-jumper="true"
          @change="handlePageChange"
        />
      </div>
    </div>

    <!-- 触发构建弹窗 -->
    <a-modal v-model:open="showTriggerModal" title="触发构建" :confirm-loading="triggering" @ok="handleTrigger" @cancel="resetTriggerForm">
      <a-form :model="triggerForm" layout="vertical">
        <a-form-item label="选择应用" required>
          <a-select v-model:value="triggerForm.appId" placeholder="选择要构建的应用" @change="handleAppChange">
            <a-select-option v-for="app in apps" :key="app.productId" :value="app.productId">
              {{ app.productName }}
            </a-select-option>
          </a-select>
        </a-form-item>

        <a-form-item label="选择流水线（可选）">
          <a-select v-model:value="triggerForm.pipelineId" placeholder="默认使用第一个可用流水线">
            <a-select-option v-for="p in pipelines" :key="p.id" :value="p.id">
              {{ p.name }} ({{ p.env }})
            </a-select-option>
          </a-select>
        </a-form-item>

        <a-form-item label="分支">
          <a-input v-model:value="triggerForm.branch" placeholder="留空则使用默认分支（main）" />
        </a-form-item>

        <a-alert v-if="triggerForm.appId" type="info" show-icon>
          <template #message>
            提示：构建任务将在 CI 系统后台执行，可随时刷新页面查看构建进度。
          </template>
        </a-alert>
      </a-form>
    </a-modal>

    <!-- 构建日志弹窗 -->
    <a-modal v-model:open="showLogModal" title="构建日志" width="800px" :footer="null">
      <div class="log-container">
        <pre class="log-content">{{ buildLog || '加载中...' }}</pre>
      </div>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import {
  ReloadOutlined,
  PlayCircleOutlined,
  CodeSandboxOutlined,
  UserOutlined,
  ClockCircleOutlined,
  DownloadOutlined,
  WarningOutlined,
} from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import {
  pageBuild,
  listBuildByApp,
  triggerBuild,
  cancelBuild,
  retryBuild,
  getBuildLog,
  getBuildStats,
} from '@/api/app/cicd'
import type { AppBuild } from '@/api/app/cicd'
import { getDeveloperApps } from '@/api/app/appProduct'
import type { AppProduct } from '@/api/app/appProduct/model'
import { listPipelineByApp } from '@/api/app/cicd'
import type { AppPipeline } from '@/api/app/cicd'

definePageMeta({ layout: 'developer' })
useHead({ title: '构建任务 - 开发者中心' })

const userId = import.meta.client ? localStorage.getItem('UserId') : null

// 加载状态
const loading = ref(false)
const triggering = ref(false)
const apps = ref<AppProduct[]>([])
const builds = ref<AppBuild[]>([])
const pipelines = ref<AppPipeline[]>([])

// 筛选
const filterStatus = ref('')
const filterAppId = ref<number | undefined>()
const searchKeyword = ref('')

// 分页
const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0,
})

// 构建统计
const buildStats = reactive([
  { key: 'total', icon: '📊', label: '总构建', value: 0, color: 'blue' },
  { key: 'running', icon: '⏳', label: '进行中', value: 0, color: 'orange' },
  { key: 'success', icon: '✅', label: '成功', value: 0, color: 'green' },
  { key: 'failed', icon: '❌', label: '失败', value: 0, color: 'red' },
])

// 触发构建弹窗
const showTriggerModal = ref(false)
const triggerForm = reactive({
  appId: undefined as number | undefined,
  pipelineId: undefined as number | undefined,
  branch: '',
})

// 日志弹窗
const showLogModal = ref(false)
const buildLog = ref('')
const currentBuild = ref<AppBuild | null>(null)

// ========== 加载数据 ==========

async function loadApps() {
  try {
    const res = await getDeveloperApps({ page: 1, limit: 100, userId: userId ? Number(userId) : undefined })
    apps.value = (res as any)?.data?.records || res?.list || []
  } catch (e) {
    console.error('加载应用列表失败:', e)
  }
}

async function loadBuilds() {
  loading.value = true
  try {
    const res = await pageBuild({
      page: pagination.current,
      limit: pagination.pageSize,
      appId: filterAppId.value,
      status: filterStatus.value || undefined,
    })

    if (res?.data?.code === 200) {
      builds.value = res.data.data.records || []
      pagination.total = res.data.data.total || 0
      updateStats()
    } else {
      builds.value = []
      pagination.total = 0
    }
  } catch (e) {
    console.error('加载构建记录失败:', e)
    builds.value = []
  } finally {
    loading.value = false
  }
}

async function loadPipelines(appId: number) {
  try {
    const res = await listPipelineByApp(appId)
    if (res?.data?.code === 200) {
      pipelines.value = res.data.data || []
    } else {
      pipelines.value = []
    }
  } catch (e) {
    pipelines.value = []
  }
}

async function loadStats() {
  if (!filterAppId.value) return

  try {
    const res = await getBuildStats(filterAppId.value)
    if (res?.data?.code === 200) {
      const stats = res.data.data
      buildStats[0].value = stats.total || 0
      buildStats[1].value = stats.running || 0
      buildStats[2].value = stats.success || 0
      buildStats[3].value = stats.failed || 0
    }
  } catch (e) {
    console.error('加载统计数据失败:', e)
  }
}

function updateStats() {
  buildStats[0].value = builds.value.length
  buildStats[1].value = builds.value.filter(b => b.status === 'pending' || b.status === 'running').length
  buildStats[2].value = builds.value.filter(b => b.status === 'success').length
  buildStats[3].value = builds.value.filter(b => b.status === 'failed').length
}

// ========== 操作 ==========

async function handleTrigger() {
  if (!triggerForm.appId) {
    message.error('请选择应用')
    return
  }

  triggering.value = true
  try {
    const res = await triggerBuild(triggerForm.appId, triggerForm.branch || undefined)
    if (res?.data?.code === 200) {
      message.success('构建已触发！')
      showTriggerModal.value = false
      resetTriggerForm()
      loadBuilds()
    } else {
      message.error(res?.data?.message || '触发失败')
    }
  } catch (e: any) {
    message.error(e?.message || '触发构建失败')
  } finally {
    triggering.value = false
  }
}

function handleCancel(build: AppBuild) {
  cancelBuild(build.id!).then(res => {
    if (res?.data?.code === 200) {
      message.success('构建已取消')
      loadBuilds()
    } else {
      message.error(res?.data?.message || '取消失败')
    }
  })
}

function handleRetry(build: AppBuild) {
  retryBuild(build.id!).then(res => {
    if (res?.data?.code === 200) {
      message.success('构建已重试')
      loadBuilds()
    } else {
      message.error(res?.data?.message || '重试失败')
    }
  })
}

async function viewLog(build: AppBuild) {
  currentBuild.value = build
  showLogModal.value = true
  buildLog.value = ''

  try {
    const res = await getBuildLog(build.id!)
    if (res?.data?.code === 200) {
      buildLog.value = res.data.data?.log || '暂无日志'
    } else {
      buildLog.value = res?.data?.message || '获取日志失败'
    }
  } catch (e: any) {
    buildLog.value = '获取日志失败: ' + (e?.message || '未知错误')
  }
}

function handleAppChange(appId: number) {
  triggerForm.pipelineId = undefined
  triggerForm.branch = ''
  if (appId) {
    loadPipelines(appId)
  }
}

function resetTriggerForm() {
  triggerForm.appId = undefined
  triggerForm.pipelineId = undefined
  triggerForm.branch = ''
  pipelines.value = []
}

function handlePageChange(page: number, pageSize: number) {
  pagination.current = page
  pagination.pageSize = pageSize
  loadBuilds()
}

// ========== 辅助函数 ==========

function statusText(status?: string) {
  const map: Record<string, string> = {
    pending: '排队中',
    running: '构建中',
    success: '成功',
    failed: '失败',
    cancelled: '已取消',
  }
  return map[status || ''] || '未知'
}

function ciTypeText(type?: string) {
  const map: Record<string, string> = {
    gitea: 'Gitea',
    jenkins: 'Jenkins',
    github: 'GitHub',
  }
  return map[type || ''] || type || 'CI'
}

function formatTime(time?: string) {
  if (!time) return ''
  return new Date(time).toLocaleString('zh-CN')
}

function formatDuration(seconds?: number) {
  if (!seconds) return ''
  if (seconds < 60) return `${seconds}s`
  const mins = Math.floor(seconds / 60)
  const secs = seconds % 60
  if (mins < 60) return `${mins}m ${secs}s`
  const hours = Math.floor(mins / 60)
  const mins2 = mins % 60
  return `${hours}h ${mins2}m`
}

// 初始化
onMounted(() => {
  loadApps()
  loadBuilds()
  loadStats()
})
</script>

<style scoped>
.dev-page {
  min-height: 100%;
  padding: 20px 24px 28px;
}

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

.page-title {
  font-size: 18px;
  font-weight: 700;
  color: #1f2937;
  margin: 0;
}

.page-desc {
  font-size: 13px;
  color: #9ca3af;
  margin: 4px 0 0;
}

/* 统计卡片 */
.stat-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px;
  border-radius: 12px;
  border: 1px solid transparent;
  transition: all 0.2s;
}
.stat-card:hover { transform: translateY(-1px); }
.stat-card.blue { background: #eff6ff; border-color: #dbeafe; }
.stat-card.orange { background: #fff7ed; border-color: #fed7aa; }
.stat-card.green { background: #f0fdf4; border-color: #bbf7d0; }
.stat-card.red { background: #fff1f2; border-color: #fecdd3; }
.stat-icon { font-size: 28px; flex-shrink: 0; }
.stat-value { font-size: 22px; font-weight: 700; color: rgba(0,0,0,0.85); }
.stat-label { font-size: 12px; color: rgba(0,0,0,0.45); margin-top: 2px; }

/* 面板 */
.panel {
  background: #fff;
  border: 1px solid #f0f0f0;
  border-radius: 12px;
  overflow: hidden;
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid #f5f5f5;
}

.panel-title {
  font-size: 14px;
  font-weight: 600;
  color: rgba(0,0,0,0.85);
}

/* 构建列表 */
.build-list {
  padding: 0;
}

.build-item {
  border-bottom: 1px solid #f0f0f0;
  transition: background 0.2s;
}

.build-item:last-child {
  border-bottom: none;
}

.build-item:hover {
  background: #fafafa;
}

.build-status-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 18px;
  background: #f9f9f9;
  border-bottom: 1px solid #f0f0f0;
}

.status-indicator {
  display: flex;
  align-items: center;
  gap: 6px;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #999;
}

.status-pending .status-dot { background: #faad14; }
.status-running .status-dot { background: #1890ff; animation: pulse 1s infinite; }
.status-success .status-dot { background: #52c41a; }
.status-failed .status-dot { background: #ff4d4f; }
.status-cancelled .status-dot { background: #d9d9d9; }

.status-text {
  font-size: 12px;
  font-weight: 500;
}

.status-pending .status-text { color: #faad14; }
.status-running .status-text { color: #1890ff; }
.status-success .status-text { color: #52c41a; }
.status-failed .status-text { color: #ff4d4f; }
.status-cancelled .status-text { color: #999; }

.build-time {
  font-size: 12px;
  color: rgba(0,0,0,0.45);
}

.build-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  gap: 16px;
}

.build-main {
  flex: 1;
  min-width: 0;
}

.build-number {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.ci-badge {
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: 600;
}

.ci-badge.gitea { background: #f0f0f0; color: #333; }
.ci-badge.jenkins { background: #dbeafe; color: #1d4ed8; }
.ci-badge.github { background: #f0f9ff; color: #0366d6; }

.number-text {
  font-size: 14px;
  font-weight: 600;
  color: rgba(0,0,0,0.85);
}

.build-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 12px;
  color: rgba(0,0,0,0.45);
}

.meta-item {
  display: flex;
  align-items: center;
  gap: 4px;
}

.commit-message {
  margin-top: 6px;
  font-size: 12px;
  color: rgba(0,0,0,0.65);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 500px;
}

.build-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.build-error {
  padding: 10px 18px;
  background: #fff2f0;
  border-top: 1px solid #ffccc7;
  font-size: 12px;
  color: #ff4d4f;
}

.py-8 { padding: 40px 0; }
.mb-6 { margin-bottom: 24px; }
.mb-4 { margin-bottom: 16px; }

.empty-icon {
  font-size: 48px;
  margin-bottom: 8px;
}

/* 日志 */
.log-container {
  background: #1e1e1e;
  border-radius: 8px;
  padding: 16px;
  max-height: 500px;
  overflow: auto;
}

.log-content {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 12px;
  line-height: 1.6;
  color: #d4d4d4;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-all;
}

.pagination-wrapper {
  padding: 16px;
  display: flex;
  justify-content: flex-end;
  border-top: 1px solid #f0f0f0;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}
</style>
