<template>
  <div class="novel-comic-page">
    <CreationHeader />

    <!-- 主内容区域 -->
    <div class="main-content">
      <!-- 左侧面板 -->
      <div class="left-panel">
        <div class="left-panel-content">
          <CreationTabs active="novel-comic" />

          <div>
              <h3 class="form-section-title">创作设置</h3>

              <!-- 主题（选填） -->
              <div class="form-group">
                <label class="form-label">
                  主题
                  <span class="form-optional">选填</span>
                </label>
                <a-input
                  v-model:value="form.theme"
                  placeholder="例如：都市奇幻、校园恋爱、科幻冒险..."
                  :maxlength="100"
                  @input="checkThemeLength"
                />
              </div>

              <!-- 故事背景（必填） -->
              <div class="form-group">
                <label class="form-label">
                  故事背景
                  <span class="form-required">*必填</span>
                </label>
                <a-textarea
                  v-model:value="form.storyBackground"
                  placeholder="描述故事发生的世界观、时代背景、环境设定等..."
                  :rows="4"
                  :maxlength="2000"
                  @input="checkStoryBackgroundLength"
                />
              </div>

              <!-- 背景音乐文件上传（选填） -->
              <div class="form-group">
                <label class="form-label">
                  背景音乐
                  <span class="form-optional">选填</span>
                </label>
                <div
                  class="music-upload-area"
                  :class="{ 'has-file': musicFile, 'drag-over': isDraggingMusic }"
                  @click="triggerMusicUpload"
                  @dragover.prevent="isDraggingMusic = true"
                  @dragleave.prevent="isDraggingMusic = false"
                  @drop.prevent="handleMusicDrop"
                >
                  <div v-if="!musicFile" class="upload-placeholder">
                    <CustomerServiceOutlined class="upload-icon" />
                    <p class="upload-text">点击或拖拽上传音乐文件</p>
                    <p class="upload-hint">支持 MP3、WAV、AAC、OGG 等格式，最大 50MB</p>
                  </div>
                  <div v-else class="upload-file-info">
                    <CustomerServiceOutlined class="file-icon" />
                    <div class="file-detail">
                      <p class="file-name">{{ musicFile.name }}</p>
                      <p class="file-size">{{ formatFileSize(musicFile.size) }}</p>
                    </div>
                    <button class="file-remove" @click.stop="removeMusicFile">
                      <CloseOutlined />
                    </button>
                  </div>
                </div>
              </div>

              <!-- 故事文案（必填） -->
              <div class="form-group">
                <label class="form-label">
                  故事文案
                  <span class="form-required">*必填</span>
                </label>
                <a-textarea
                  v-model:value="form.storyScript"
                  placeholder="输入完整的故事文案/剧本内容，AI 将基于此生成漫剧..."
                  :rows="8"
                  :maxlength="10000"
                  @input="checkStoryScriptLength"
                />
              </div>

              <!-- 提交按钮 -->
              <CreationGenerateButton
                button-text="开始生成"
                :points="30"
                :disabled="!canSubmit"
                :loading="submitting"
                loading-text="生成中..."
                icon="✨"
                :is-authenticated="true"
                @click="handleSubmit"
              />
          </div>
        </div>
      </div>

      <!-- 右侧面板 -->
      <div class="right-panel">
        <div class="preview-area">
            <div class="result-card">
              <h3 class="form-card-title">生成结果</h3>

              <!-- 空状态 -->
              <div v-if="!taskResult && !submitting && !polling" class="result-empty">
                <div class="empty-illustration">📚</div>
                <p class="empty-title">等待创作</p>
                <p class="empty-desc">填写左侧表单并点击"开始生成"，AI 将为你创作小说漫剧</p>
              </div>

              <!-- 生成中 -->
              <div v-else-if="submitting || polling" class="result-loading">
                <div v-if="polling && pollingElapsed > 0" class="polling-timer">
                  ⏱ 已等待 {{ formatElapsed(pollingElapsed) }}
                </div>
                <div class="loading-animation">
                  <div class="loading-dot"></div>
                  <div class="loading-dot"></div>
                  <div class="loading-dot"></div>
                </div>
                <p class="loading-title">{{ submitting ? '正在提交任务...' : 'AI 正在创作中...' }}</p>
                <p class="loading-desc">这可能需要几分钟时间，请耐心等待</p>
                <div class="loading-progress">
                  <div class="loading-progress-bar"></div>
                </div>
              </div>

              <!-- 生成结果 -->
              <div v-else-if="taskResult" class="result-content">
                <div v-if="taskResult.status === 'SUCCESS'" class="result-success">
                  <div class="result-header">
                    <span class="result-badge success">✅ 生成完成</span>
                  </div>
                  <div class="result-body">
                    <div class="result-text" v-html="formatResult(taskResult.data)"></div>
                  </div>
                  <div class="result-actions">
                    <a-button type="primary" @click="copyResult">
                      <CopyOutlined /> 复制结果
                    </a-button>
                    <a-button @click="resetForm">
                      重新生成
                    </a-button>
                  </div>
                </div>

                <div v-else-if="taskResult.status === 'FAILED'" class="result-failed">
                  <div class="result-header">
                    <span class="result-badge failed">❌ 生成失败</span>
                  </div>
                  <p class="result-error">{{ taskResult.message || '未知错误，请重试' }}</p>
                  <a-button type="primary" @click="handleSubmit">重新尝试</a-button>
                </div>
              </div>
            </div>

            <!-- 历史记录 -->
            <div class="history-card">
              <h3 class="form-card-title">历史记录</h3>
              <div class="history-list" v-if="historyList.length > 0">
                <div
                  v-for="item in historyList"
                  :key="item.id || item.taskId"
                  class="history-item"
                >
                  <div class="history-item-top">
                    <span class="history-status" :class="getHistoryStatusClass(item.status)">
                      {{ getHistoryStatusText(item.status) }}
                    </span>
                    <span class="history-date">{{ formatFriendlyDate(item.createdAt) }}</span>
                  </div>
                  <div class="history-theme" v-if="item.theme">{{ item.theme }}</div>
                  <div class="history-preview-text">
                    {{ truncateText(item.storyBackground || item.storyScript || '', 80) }}
                  </div>
                  
                  <!-- 展开详情 -->
                  <div class="history-expand" v-if="expandedItemId === item.id">
                    <div class="history-detail-section">
                      <div class="history-detail-label">故事背景</div>
                      <div class="history-detail-content">{{ item.storyBackground || '-' }}</div>
                    </div>
                    <div class="history-detail-section">
                      <div class="history-detail-label">故事文案</div>
                      <div class="history-detail-content">{{ item.storyScript || '-' }}</div>
                    </div>
                  </div>
                  
                  <div class="history-item-actions">
                    <a-button size="small" @click.stop="toggleExpand(item)">
                      {{ expandedItemId === item.id ? '收起' : '展开' }}
                    </a-button>
                    <a-button size="small" @click.stop="reuseHistory(item)">复用设置</a-button>
                    <a-button size="small" type="primary" v-if="item.status === 'SUCCESS' || item.status === 'COMPLETED'" @click.stop="viewHistoryItem(item)">
                      <CopyOutlined /> 查看结果
                    </a-button>
                    <a-button size="small" danger @click.stop="handleDeleteHistory(item)">
                      删除
                    </a-button>
                  </div>
                </div>
              </div>
              <!-- 空状态 -->
              <div class="history-empty" v-else-if="!loadingHistory">
                <div class="empty-illustration">📝</div>
                <p class="empty-title">暂无历史记录</p>
                <p class="empty-desc">完成创作后，记录将显示在这里</p>
              </div>
              <!-- 加载中 -->
              <div class="history-loading" v-else>
                <LoadingOutlined class="is-loading" />
                <span>加载中...</span>
              </div>
              <!-- 加载更多 -->
              <div class="history-load-more" v-if="hasMoreHistory && historyList.length > 0">
                <a-button size="small" :loading="loadingHistory" @click="loadMoreHistory">加载更多</a-button>
              </div>
            </div>
        </div>
      </div>
    </div>
    <!-- 免费会员升级弹窗 -->
    <a-modal
      v-model:open="showUpgradeModal"
      :title="null"
      :footer="null"
      :closable="true"
      :maskClosable="false"
      centered
      width="420px"
      class="upgrade-modal"
    >
      <div class="upgrade-modal-content">
        <div class="upgrade-icon">🔒</div>
        <h3 class="upgrade-title">功能受限</h3>
        <p class="upgrade-desc">小说漫剧创作为付费会员专属功能</p>
        <p class="upgrade-hint">请升级至入门会员及以上等级后使用</p>
        <div class="upgrade-actions">
          <a-button type="primary" size="large" block @click="goToSubscription">立即升级会员</a-button>
          <a-button size="large" block @click="goBack">返回首页</a-button>
        </div>
      </div>
    </a-modal>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import { useRouter } from 'vue-router'
import { LoadingOutlined, CopyOutlined, CustomerServiceOutlined, CloseOutlined } from '@ant-design/icons-vue'
import { useUserStore } from '@/stores/user'
import { createNovelComicTask, getNovelComicTaskStatus, getNovelComicHistory, deleteNovelComicHistory } from '@/api/novelComic'
import { getUserSubscriptionInfo } from '@/api/payments'
import CreationHeader from '@/components/CreationHeader.vue'
import CreationTabs from '@/components/CreationTabs.vue'
import CreationGenerateButton from '@/components/CreationGenerateButton.vue'

const router = useRouter()
const userStore = useUserStore()

// 会员权限检查
const showUpgradeModal = ref(false)
const isFreeMember = ref(false)
const membershipLoaded = ref(false)

const checkMembership = async () => {
  if (!userStore.isAuthenticated) {
    isFreeMember.value = true
    showUpgradeModal.value = true
    membershipLoaded.value = true
    return
  }
  try {
    const response = await getUserSubscriptionInfo()
    const data = response.data
    if (data?.success && data?.data) {
      const plan = data.data.currentPlan || ''
      // 免费会员 或 无会员信息 → 限制访问
      const isFree = plan.includes('免费') || plan.toLowerCase().includes('free') || !plan
      isFreeMember.value = isFree
      if (isFree) {
        showUpgradeModal.value = true
      }
    }
  } catch (error) {
    console.error('获取会员信息失败:', error)
  } finally {
    membershipLoaded.value = true
  }
}

const goToSubscription = () => {
  router.push('/subscription')
}

const goBack = () => {
  router.push('/')
}

// 音乐文件
const musicFile = ref(null)
const isDraggingMusic = ref(false)
const ALLOWED_MUSIC_TYPES = ['audio/mpeg', 'audio/wav', 'audio/aac', 'audio/ogg', 'audio/mp4', 'audio/x-m4a', 'audio/flac']
const MAX_MUSIC_SIZE = 50 * 1024 * 1024 // 50MB

const triggerMusicUpload = () => {
  const input = document.createElement('input')
  input.type = 'file'
  input.accept = 'audio/*'
  input.onchange = (e) => {
    const file = e.target.files[0]
    if (file) validateAndSetMusic(file)
  }
  input.click()
}

const handleMusicDrop = (e) => {
  isDraggingMusic.value = false
  const file = e.dataTransfer.files[0]
  if (file) validateAndSetMusic(file)
}

const validateAndSetMusic = (file) => {
  if (!file.type.startsWith('audio/') && !ALLOWED_MUSIC_TYPES.includes(file.type)) {
    message.error('请上传音频文件（MP3、WAV、AAC、OGG 等格式）')
    return
  }
  if (file.size > MAX_MUSIC_SIZE) {
    message.error('音乐文件不能超过 50MB')
    return
  }
  musicFile.value = file
  message.success(`已选择: ${file.name}`)
}

const removeMusicFile = () => {
  musicFile.value = null
}

const formatFileSize = (bytes) => {
  if (bytes < 1024) return bytes + ' B'
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
}

// 表单数据
const form = ref({
  theme: '',
  storyBackground: '',
  storyScript: ''
})

const submitting = ref(false)
const polling = ref(false)
const taskResult = ref(null)
let pollingTimer = null

// 是否可以提交（必填项校验 + 会员权限）
const canSubmit = computed(() => {
  return !isFreeMember.value && form.value.storyBackground.trim() !== '' && form.value.storyScript.trim() !== ''
})

// 提交生成任务
const handleSubmit = async () => {
  if (!canSubmit.value || submitting.value) return

  submitting.value = true
  taskResult.value = null

  try {
    const response = await createNovelComicTask({
      theme: form.value.theme,
      storyBackground: form.value.storyBackground,
      storyScript: form.value.storyScript,
      musicFile: musicFile.value
    })

    if (response.data?.success && response.data?.taskId) {
      const taskId = response.data.taskId
      message.success('任务已提交，后台生成中，请耐心等待...')
      submitting.value = false
      // 异步任务：开始轮询状态
      polling.value = true
      startPolling(taskId)
      // 刷新历史记录
      loadHistory()
    } else {
      taskResult.value = {
        status: 'FAILED',
        message: response.data?.message || '任务提交失败'
      }
    }
  } catch (error) {
    console.error('创建任务失败:', error)
    taskResult.value = {
      status: 'FAILED',
      message: error.message || '网络错误，请重试'
    }
  } finally {
    submitting.value = false
  }
}

// 轮询任务状态（支持长时间运行的工作流）
const pollingElapsed = ref(0) // 已轮询时间（秒）
const startPolling = (taskId) => {
  let attempts = 0
  const maxAttempts = 720 // 最多轮询 720 次（每 10 秒一次 = 2 小时）
  const intervalMs = 10000 // 每 10 秒轮询一次
  pollingElapsed.value = 0

  pollingTimer = setInterval(async () => {
    attempts++
    pollingElapsed.value = attempts * (intervalMs / 1000)

    if (attempts > maxAttempts) {
      clearInterval(pollingTimer)
      polling.value = false
      taskResult.value = {
        status: 'FAILED',
        message: '生成超时（已等待 2 小时），请重试'
      }
      return
    }

    try {
      const response = await getNovelComicTaskStatus(taskId)
      const data = response.data

      if (data?.status === 'SUCCESS' || data?.status === 'COMPLETED') {
        clearInterval(pollingTimer)
        polling.value = false
        taskResult.value = {
          status: 'SUCCESS',
          data: data.data || data.result || data
        }
        message.success('生成完成！')
      } else if (data?.status === 'FAIL' || data?.status === 'FAILED') {
        clearInterval(pollingTimer)
        polling.value = false
        taskResult.value = {
          status: 'FAILED',
          message: data.message || '生成失败'
        }
      }
      // RUNNING 状态继续轮询
    } catch (error) {
      console.error('轮询状态失败:', error)
      // 网络错误不中断轮询，继续重试
    }
  }, intervalMs)
}

// 格式化已等待时间
const formatElapsed = (seconds) => {
  const m = Math.floor(seconds / 60)
  const s = Math.round(seconds % 60)
  if (m === 0) return `${s} 秒`
  return `${m} 分 ${s} 秒`
}

// 格式化结果显示
const formatResult = (data) => {
  if (typeof data === 'string') {
    return data.replace(/\n/g, '<br>')
  }
  if (typeof data === 'object') {
    // 尝试提取常见字段
    const output = data.output || data.result || data.content || data.text || JSON.stringify(data, null, 2)
    return typeof output === 'string' ? output.replace(/\n/g, '<br>') : `<pre>${JSON.stringify(output, null, 2)}</pre>`
  }
  return String(data)
}

// 复制结果
const copyResult = () => {
  if (!taskResult.value?.data) return
  const text = typeof taskResult.value.data === 'string'
    ? taskResult.value.data
    : JSON.stringify(taskResult.value.data, null, 2)

  navigator.clipboard.writeText(text).then(() => {
    message.success('已复制到剪贴板')
  }).catch(() => {
    message.error('复制失败')
  })
}

// 重置表单
const resetForm = () => {
  taskResult.value = null
}

// 字数限制检查
const THEME_MAX_LENGTH = 100
const STORY_BACKGROUND_MAX_LENGTH = 2000
const STORY_SCRIPT_MAX_LENGTH = 10000

const checkThemeLength = (e) => {
  if (e.target.value.length >= THEME_MAX_LENGTH) {
    message.warning(`主题最多 ${THEME_MAX_LENGTH} 个字`)
  }
}

const checkStoryBackgroundLength = (e) => {
  if (e.target.value.length >= STORY_BACKGROUND_MAX_LENGTH) {
    message.warning(`故事背景最多 ${STORY_BACKGROUND_MAX_LENGTH} 个字`)
  }
}

const checkStoryScriptLength = (e) => {
  if (e.target.value.length >= STORY_SCRIPT_MAX_LENGTH) {
    message.warning(`故事文案最多 ${STORY_SCRIPT_MAX_LENGTH} 个字`)
  }
}

// ===== 历史记录 =====
const historyList = ref([])
const loadingHistory = ref(false)
const historyPage = ref(0)
const hasMoreHistory = ref(false)
const expandedItemId = ref(null)

const loadHistory = async (page = 0) => {
  loadingHistory.value = true
  try {
    const response = await getNovelComicHistory({ page, size: 10 })
    const data = response.data
    if (data?.success && data?.data) {
      const items = data.data.content || data.data || []
      if (page === 0) {
        historyList.value = items
      } else {
        historyList.value.push(...items)
      }
      historyPage.value = page
      const totalElements = data.data.totalElements || 0
      hasMoreHistory.value = historyList.value.length < totalElements
    }
  } catch (error) {
    console.error('加载历史记录失败:', error)
  } finally {
    loadingHistory.value = false
  }
}

const loadMoreHistory = () => {
  loadHistory(historyPage.value + 1)
}

const getHistoryStatusClass = (status) => {
  const s = (status || '').toUpperCase()
  if (s === 'SUCCESS' || s === 'COMPLETED') return 'status-success'
  if (s === 'FAILED' || s === 'FAIL') return 'status-failed'
  if (s === 'RUNNING' || s === 'PROCESSING' || s === 'PENDING') return 'status-running'
  return ''
}

const getHistoryStatusText = (status) => {
  const s = (status || '').toUpperCase()
  if (s === 'SUCCESS' || s === 'COMPLETED') return '✅ 完成'
  if (s === 'FAILED' || s === 'FAIL') return '❌ 失败'
  if (s === 'RUNNING' || s === 'PROCESSING') return '⏳ 生成中'
  if (s === 'PENDING') return '⏳ 排队中'
  return status
}

const formatDate = (dateStr) => {
  if (!dateStr) return ''
  const d = new Date(dateStr)
  const month = String(d.getMonth() + 1).padStart(2, '0')
  const day = String(d.getDate()).padStart(2, '0')
  const hour = String(d.getHours()).padStart(2, '0')
  const min = String(d.getMinutes()).padStart(2, '0')
  return `${month}-${day} ${hour}:${min}`
}

const formatFriendlyDate = (dateStr) => {
  if (!dateStr) return ''
  const date = new Date(dateStr)
  const now = new Date()
  const diff = now - date
  const oneDay = 24 * 60 * 60 * 1000
  const oneHour = 60 * 60 * 1000
  const oneMinute = 60 * 1000

  if (diff < oneMinute) {
    return '刚刚'
  } else if (diff < oneHour) {
    const minutes = Math.floor(diff / oneMinute)
    return `${minutes} 分钟前`
  } else if (diff < oneDay) {
    const hours = Math.floor(diff / oneHour)
    return `${hours} 小时前`
  } else if (diff < 2 * oneDay) {
    return '昨天'
  } else if (diff < 7 * oneDay) {
    const days = Math.floor(diff / oneDay)
    return `${days} 天前`
  } else {
    return formatDate(dateStr)
  }
}

const truncateText = (text, maxLen) => {
  if (!text) return '暂无描述'
  return text.length > maxLen ? text.slice(0, maxLen) + '...' : text
}

// 展开/收起历史记录
const toggleExpand = (item) => {
  if (expandedItemId.value === item.id) {
    expandedItemId.value = null
  } else {
    expandedItemId.value = item.id
  }
}

// 查看历史结果
const viewHistoryItem = (item) => {
  const s = (item.status || '').toUpperCase()
  if (s === 'SUCCESS' || s === 'COMPLETED') {
    taskResult.value = {
      status: 'SUCCESS',
      data: item.result || item.data || item.output || ''
    }
  } else if (s === 'FAILED' || s === 'FAIL') {
    taskResult.value = {
      status: 'FAILED',
      message: item.errorMessage || item.message || '生成失败'
    }
  }
}

// 复用历史设置
const reuseHistory = (item) => {
  if (item.theme) form.value.theme = item.theme
  if (item.storyBackground) form.value.storyBackground = item.storyBackground
  if (item.storyScript) form.value.storyScript = item.storyScript
  taskResult.value = null
  message.success('已填充历史设置')
}

// 删除历史记录
const handleDeleteHistory = (item) => {
  Modal.confirm({
    title: '确认删除',
    content: `确定要删除这条历史记录吗？`,
    okText: '删除',
    cancelText: '取消',
    okType: 'danger',
    onOk: async () => {
      try {
        const response = await deleteNovelComicHistory(item.id)
        if (response.data?.success) {
          message.success('删除成功')
          historyList.value = historyList.value.filter(i => i.id !== item.id)
          if (expandedItemId.value === item.id) {
            expandedItemId.value = null
          }
        } else {
          message.error(response.data?.message || '删除失败')
        }
      } catch (error) {
        console.error('删除历史记录失败:', error)
        message.error('删除失败，请重试')
      }
    }
  })
}

onMounted(() => {
  checkMembership()
  loadHistory()
})
</script>

<style scoped>
.novel-comic-page {
  height: 100vh;
  background: var(--bg-base);
  color: var(--text-primary);
  display: flex;
  flex-direction: column;
  font-family: var(--font-sans);
  overflow: hidden;
  margin: 0;
  padding: 0;
}

/* 主内容区域 */
.main-content {
  flex: 1;
  display: grid;
  grid-template-columns: 520px 1fr;
  gap: 0;
  height: calc(100vh - 100px);
}

/* 左侧面板 */
.left-panel {
  background: var(--bg-surface);
  border-right: 1px solid var(--border-subtle);
  padding: 32px;
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  overflow: hidden;
}

/* 左侧面板内容区域（可滚动） */
.left-panel-content {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding-right: 8px;
}

/* 优化滚动条样式 */
.left-panel-content::-webkit-scrollbar {
  width: 8px;
}

.left-panel-content::-webkit-scrollbar-track {
  background: var(--bg-base);
  border-radius: var(--radius-xs);
}

.left-panel-content::-webkit-scrollbar-thumb {
  background: var(--bg-overlay);
  border-radius: var(--radius-xs);
}

.left-panel-content::-webkit-scrollbar-thumb:hover {
  background: var(--bg-overlay);
}

/* 右侧面板 */
.right-panel {
  overflow-y: auto;
  padding: 32px;
}

.preview-area {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.result-card {
  background: var(--bg-surface);
  border-radius: 20px;
  padding: 28px;
  border: 1px solid var(--border-subtle);
  box-shadow: 0 2px 12px rgba(124, 58, 237, 0.04);
}

.form-section-title {
  font-size: 1.1rem;
  font-weight: 700;
  margin: 0 0 24px 0;
  color: var(--text-primary);
  position: relative;
  padding-bottom: 12px;
}

.form-section-title::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 48px;
  height: 3px;
  background: var(--gradient-brand);
  border-radius: 2px;
}

/* Form Groups */
.form-group {
  margin-bottom: 20px;
}

.form-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 8px;
}

.form-required {
  font-size: 11px;
  font-weight: 600;
  color: var(--error-500);
  background: rgba(239, 68, 68, 0.08);
  padding: 2px 8px;
  border-radius: 10px;
}

.form-optional {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  background: var(--bg-hover);
  padding: 2px 8px;
  border-radius: 10px;
}

/* Ant Design 输入框覆盖 */
.form-group :deep(.ant-input),
.form-group :deep(.ant-input-textarea textarea) {
  background: var(--bg-root) !important;
  border: 1.5px solid var(--border-default) !important;
  border-radius: 12px !important;
  color: var(--text-primary) !important;
  font-size: 14px !important;
  padding: 10px 14px !important;
  transition: all 0.25s ease !important;
}

.form-group :deep(.ant-input:focus),
.form-group :deep(.ant-input-textarea textarea:focus),
.form-group :deep(.ant-input-focused),
.form-group :deep(.ant-input-affix-wrapper-focused) {
  border-color: var(--primary-400) !important;
  box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1) !important;
}

.form-group :deep(.ant-input::placeholder),
.form-group :deep(.ant-input-textarea textarea::placeholder) {
  color: var(--text-tertiary) !important;
}

.form-group :deep(.ant-input-textarea-show-count::after),
.form-group :deep(.ant-input-show-count-suffix) {
  color: var(--text-tertiary) !important;
  font-size: 12px !important;
}

/* Music Upload Area */
.music-upload-area {
  border: 2px dashed var(--border-default);
  border-radius: 14px;
  padding: 20px;
  cursor: pointer;
  transition: all 0.25s ease;
  background: var(--bg-root);
  text-align: center;
}

.music-upload-area:hover,
.music-upload-area.drag-over {
  border-color: var(--primary-400);
  background: rgba(124, 58, 237, 0.04);
}

.music-upload-area.has-file {
  border-style: solid;
  border-color: var(--primary-300);
  background: rgba(124, 58, 237, 0.04);
}

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.upload-icon {
  font-size: 28px;
  color: var(--primary-400);
  opacity: 0.7;
}

.upload-text {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0;
}

.upload-hint {
  font-size: 12px;
  color: var(--text-tertiary);
  margin: 0;
}

.upload-file-info {
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: left;
}

.file-icon {
  font-size: 24px;
  color: var(--primary-500);
  flex-shrink: 0;
}

.file-detail {
  flex: 1;
  min-width: 0;
}

.file-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-size {
  font-size: 12px;
  color: var(--text-tertiary);
  margin: 2px 0 0 0;
}

.file-remove {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1.5px solid var(--error-400);
  background: rgba(239, 68, 68, 0.06);
  color: var(--error-500);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  flex-shrink: 0;
  transition: all 0.2s ease;
}

.file-remove:hover {
  background: var(--error-500);
  color: #fff;
}


.result-card {
  display: flex;
  flex-direction: column;
}

/* Empty State */
.result-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  text-align: center;
}

.empty-illustration {
  font-size: 64px;
  margin-bottom: 16px;
  opacity: 0.6;
}

.empty-title {
  font-size: 18px;
  font-weight: 700;
  color: var(--text-secondary);
  margin: 0 0 8px 0;
}

.empty-desc {
  font-size: 14px;
  color: var(--text-tertiary);
  margin: 0;
  max-width: 300px;
  line-height: 1.6;
}

/* Loading State */
.result-loading {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  text-align: center;
}

.loading-animation {
  display: flex;
  gap: 8px;
  margin-bottom: 24px;
}

.loading-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--gradient-brand);
  animation: bounce 1.4s ease-in-out infinite;
}

.loading-dot:nth-child(2) { animation-delay: 0.2s; }
.loading-dot:nth-child(3) { animation-delay: 0.4s; }

@keyframes bounce {
  0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
  40% { transform: scale(1); opacity: 1; }
}

.loading-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--text-primary);
  margin: 0 0 8px 0;
}

.loading-desc {
  font-size: 13px;
  color: var(--text-tertiary);
  margin: 0 0 24px 0;
}

.loading-progress {
  width: 200px;
  height: 4px;
  background: var(--bg-active);
  border-radius: 2px;
  overflow: hidden;
}

.loading-progress-bar {
  width: 30%;
  height: 100%;
  background: var(--gradient-brand);
  border-radius: 2px;
  animation: progressSlide 1.5s ease-in-out infinite;
}

@keyframes progressSlide {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(400%); }
}

/* Result Content */
.result-content {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.result-header {
  margin-bottom: 16px;
}

.result-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 14px;
  border-radius: 20px;
  font-size: 13px;
  font-weight: 600;
}

.result-badge.success {
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.1), rgba(6, 182, 212, 0.08));
  color: #059669;
  border: 1px solid rgba(16, 185, 129, 0.2);
}

.result-badge.failed {
  background: rgba(239, 68, 68, 0.08);
  color: var(--error-500);
  border: 1px solid rgba(239, 68, 68, 0.2);
}

.result-body {
  flex: 1;
  overflow-y: auto;
  margin-bottom: 16px;
}

.result-text {
  font-size: 14px;
  line-height: 1.8;
  color: var(--text-secondary);
  white-space: pre-wrap;
  word-break: break-word;
}

.result-text :deep(pre) {
  background: var(--bg-root);
  border-radius: 12px;
  padding: 16px;
  overflow-x: auto;
  font-size: 13px;
  border: 1px solid var(--border-subtle);
}

.result-actions {
  display: flex;
  gap: 12px;
  padding-top: 16px;
  border-top: 1px solid var(--border-subtle);
}

.result-failed {
  text-align: center;
  padding: 40px 20px;
}

.result-error {
  color: var(--error-500);
  font-size: 14px;
  margin: 12px 0 20px;
}

/* History Card */
.history-card {
  background: var(--bg-surface);
  border-radius: 20px;
  padding: 28px;
  border: 1px solid var(--border-subtle);
  box-shadow: 0 2px 12px rgba(124, 58, 237, 0.04);
  margin-top: 20px;
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.history-item {
  background: var(--bg-root);
  border: 1px solid var(--border-default);
  border-radius: 14px;
  padding: 16px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.history-item:hover {
  border-color: var(--primary-400);
  box-shadow: 0 2px 12px rgba(124, 58, 237, 0.1);
}

.history-item-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.history-status {
  font-size: 12px;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 10px;
}

.history-status.status-success {
  background: rgba(16, 185, 129, 0.1);
  color: #10B981;
}

.history-status.status-failed {
  background: rgba(239, 68, 68, 0.1);
  color: #EF4444;
}

.history-status.status-running {
  background: rgba(245, 158, 11, 0.1);
  color: #F59E0B;
}

.history-date {
  font-size: 12px;
  color: var(--text-tertiary);
}

.history-theme {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
}

.history-preview-text {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-bottom: 10px;
}

.history-item-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

/* 展开区域 */
.history-expand {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--border-subtle);
}

.history-detail-section {
  margin-bottom: 12px;
}

.history-detail-section:last-child {
  margin-bottom: 0;
}

.history-detail-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  margin-bottom: 4px;
}

.history-detail-content {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
  background: var(--bg-base);
  padding: 10px 12px;
  border-radius: 10px;
  word-break: break-word;
}

/* 空状态和加载中 */
.history-empty,
.history-loading {
  text-align: center;
  padding: 40px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.history-empty .empty-illustration,
.history-loading .empty-illustration {
  font-size: 48px;
  opacity: 0.6;
}

.history-empty .empty-title,
.history-loading .empty-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0;
}

.history-empty .empty-desc,
.history-loading .empty-desc {
  font-size: 13px;
  color: var(--text-tertiary);
  margin: 0;
}

.history-loading .is-loading {
  font-size: 28px;
}

.history-load-more {
  text-align: center;
  margin-top: 12px;
}

.polling-timer {
  font-size: 13px;
  color: var(--text-tertiary);
  margin-bottom: 12px;
}

/* 升级弹窗 */
.upgrade-modal-content {
  text-align: center;
  padding: 24px 16px;
}

.upgrade-icon {
  font-size: 48px;
  margin-bottom: 16px;
}

.upgrade-title {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-primary);
  margin: 0 0 8px 0;
}

.upgrade-desc {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  margin: 0 0 4px 0;
}

.upgrade-hint {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin: 0 0 24px 0;
}

.upgrade-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Responsive */
@media (max-width: 1024px) {
  .main-content {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 768px) {
  .left-panel {
    padding: 16px;
  }
  .right-panel {
    padding: 16px;
  }
}
</style>
