<template>
  <view class="page">
    <!-- 顶部导航栏 -->
    <view class="nav-bar">
      <view class="nav-content">
        <text class="page-title">生成音频</text>
      </view>
    </view>

    <!-- 主内容区 -->
    <view class="main-content">
      <!-- 文档上传区 -->
      <view class="card doc-upload-card">
        <view class="card-header">
          <text class="card-title">📄 上传文档</text>
          <text v-if="uploading" class="upload-status uploading">解析中...</text>
        </view>
        <!-- 未上传时：选择文件 -->
        <view v-if="!uploadedDoc.fileName" class="doc-upload-area" @click="handleUploadDoc">
          <text class="doc-upload-icon">📁</text>
          <text class="doc-upload-text">点击上传文档</text>
          <text class="doc-upload-hint">支持 .txt .docx .pdf 格式，最大 20MB</text>
        </view>
        <!-- 已上传：显示文档信息 -->
        <view v-else class="doc-info-bar">
          <view class="doc-info-left">
            <text class="doc-format-badge">{{ uploadedDoc.format?.toUpperCase() || 'DOC' }}</text>
            <view class="doc-info-text">
              <text class="doc-filename">{{ uploadedDoc.fileName }}</text>
              <text class="doc-meta">{{ uploadedDoc.wordCount }} 字 · {{ formatFileSize(uploadedDoc.fileSize) }}</text>
              <text v-if="uploadedDoc.truncated" class="doc-truncated-hint">⚠ 内容过长，已截取前2000字</text>
            </view>
          </view>
          <text class="doc-remove-btn" @click="clearDoc">✕</text>
        </view>
        <!-- 上传中 -->
        <view v-if="uploading" class="doc-uploading-bar">
          <text>正在解析文档，请稍候...</text>
        </view>
      </view>

      <!-- 文本输入区 -->
      <view class="card input-card">
        <view class="card-header">
          <text class="card-title">输入文本</text>
          <text class="word-count" :class="{ warning: text.length > 1800, error: text.length >= 2000 }">
            {{ text.length }}/2000 字
          </text>
        </view>
        <textarea
          v-model="text"
          class="text-input"
          placeholder="请输入要转换的文本内容..."
          :maxlength="2000"
          auto-height
        />
        <view class="input-actions">
          <button class="action-btn ai-generate-btn" @click="goToAIGenerate">
            <text>🤖 AI 生成内容</text>
          </button>
          <button class="action-btn" @click="clearText">清空</button>
          <button class="action-btn" @click="pasteText">粘贴</button>
        </view>
        <view class="input-hint">
          <text>支持长按粘贴文本内容</text>
        </view>
      </view>

      <!-- 音色选择 - 网格布局 -->
      <view class="card voice-card">
        <text class="card-title">选择音色</text>
        <view class="voice-grid">
          <view
            v-for="voice in audioStore.voices"
            :key="voice.id"
            class="voice-item"
            :class="{ active: selectedVoice === voice.id }"
            @click="selectedVoice = voice.id"
          >
            <view class="voice-icon">
              <text>{{ voice.gender === 'female' ? '👩' : '👨' }}</text>
            </view>
            <text class="voice-name">{{ voice.name }}</text>
            <view class="voice-preview-btn" @click.stop="previewVoice(voice.id)">
              <text v-if="previewingVoice !== voice.id">▶</text>
              <text v-else>⏹</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 参数调节 -->
      <view class="card params-card">
        <text class="card-title">参数调节</text>
        <view class="param-item">
          <view class="param-header">
            <text class="param-label">语速</text>
            <view class="param-value">{{ voiceParams.speed.toFixed(1) }}x</view>
          </view>
          <slider
            :value="(voiceParams.speed - 0.5) * 100 / 1.5"
            :min="0"
            :max="100"
            @changing="(e: any) => voiceParams.speed = Number((0.5 + (e.detail.value / 100) * 1.5).toFixed(1))"
            activeColor="#4F46E5"
            backgroundColor="#e5e7eb"
            block-size="20"
          />
          <view class="param-range">
            <text>0.5x</text>
            <text>2.0x</text>
          </view>
        </view>
        <view class="param-item">
          <view class="param-header">
            <text class="param-label">音调</text>
            <view class="param-value">{{ voiceParams.pitch > 0 ? '+' : '' }}{{ voiceParams.pitch }}</view>
          </view>
          <slider
            :value="(voiceParams.pitch + 500) / 10"
            :min="0"
            :max="100"
            @changing="(e: any) => voiceParams.pitch = Math.round(e.detail.value * 10 - 500)"
            activeColor="#4F46E5"
            backgroundColor="#e5e7eb"
            block-size="20"
          />
          <view class="param-range">
            <text>-500</text>
            <text>+500</text>
          </view>
        </view>
        <view class="param-item">
          <view class="param-header">
            <text class="param-label">音量</text>
            <view class="param-value">{{ voiceParams.volume }}%</view>
          </view>
          <slider
            :value="voiceParams.volume"
            :min="0"
            :max="100"
            @changing="(e: any) => voiceParams.volume = e.detail.value"
            activeColor="#4F46E5"
            backgroundColor="#e5e7eb"
            block-size="20"
          />
          <view class="param-range">
            <text>0%</text>
            <text>100%</text>
          </view>
        </view>
      </view>

      <!-- 专辑选择 -->
      <view class="card album-card">
        <view class="card-header-row">
          <text class="card-title">📚 所属专辑</text>
          <text class="album-add-btn" @click="showAlbumPanel = true">+ 新建专辑</text>
        </view>
        <view class="album-selector" @click="showAlbumListPanel = true">
          <text v-if="selectedAlbum" class="album-name">{{ selectedAlbum.title }}</text>
          <text v-else class="album-placeholder">点击选择专辑（可选）</text>
          <text class="album-arrow">›</text>
        </view>
      </view>

      <!-- 音频生成入口 -->
      <view class="audio-entry-card" @click="handleGenerate">
        <view class="audio-entry-content">
          <text class="audio-entry-icon">🎵</text>
          <view class="audio-entry-text">
            <text class="audio-entry-title">音频生成</text>
            <text class="audio-entry-desc">将文字转换为语音</text>
          </view>
        </view>
        <text class="audio-entry-arrow">→</text>
      </view>

      <!-- 视频生成入口 -->
      <view v-if="false" class="video-entry-card" @click="goToVideoGenerator">
        <view class="video-entry-content">
          <text class="video-entry-icon">🎬</text>
          <view class="video-entry-text">
            <text class="video-entry-title">视频生成</text>
            <text class="video-entry-desc">图片 + 音频 = 精美视频</text>
          </view>
        </view>
        <text class="video-entry-arrow">→</text>
      </view>
    </view>

    <!-- 新手引导 -->
    <view v-if="showGuide" class="guide-overlay">
      <view class="guide-content">
        <view class="guide-header">
          <text class="guide-step">步骤 {{ guideStep }} / {{ guideSteps.length }}</text>
        </view>
        <view class="guide-body">
          <text class="guide-title">{{ guideSteps[guideStep - 1]?.title }}</text>
          <text class="guide-desc">{{ guideSteps[guideStep - 1]?.desc }}</text>
        </view>
        <view class="guide-dots">
          <view
            v-for="i in guideSteps.length"
            :key="i"
            class="guide-dot"
            :class="{ active: i === guideStep }"
          />
        </view>
        <view class="guide-actions">
          <button v-if="guideStep > 1" class="guide-btn skip" @click="closeGuide">
            <text>跳过</text>
          </button>
          <button v-if="guideStep < guideSteps.length" class="guide-btn next" @click="nextGuideStep">
            <text>下一步</text>
          </button>
          <button v-else class="guide-btn finish" @click="closeGuide">
            <text>开始使用</text>
          </button>
        </view>
      </view>
    </view>

    <!-- 额度用尽弹窗 -->
    <view v-if="showQuotaModal" class="quota-modal" @click="showQuotaModal = false">
      <view class="quota-content" @click.stop>
        <view class="quota-icon">👑</view>
        <text class="quota-title">今日免费额度已用完</text>
        <text class="quota-desc">开通会员解锁更多生成次数</text>
        <view class="quota-actions">
          <button class="quota-btn primary" @click="goToMember">
            <text>开通会员</text>
          </button>
          <button class="quota-btn secondary" @click="showQuotaModal = false">
            <text>稍后再说</text>
          </button>
        </view>
      </view>
    </view>

    <!-- 专辑列表面板 -->
    <view v-if="showAlbumListPanel" class="album-panel" @click="showAlbumListPanel = false">
      <view class="album-content" @click.stop>
        <view class="album-header">
          <text class="album-title">选择专辑</text>
          <text class="album-close" @click="showAlbumListPanel = false">✕</text>
        </view>
        <scroll-view scroll-y class="album-list" :scroll-top="scrollTop">
          <view
            v-for="album in albums"
            :key="album.id"
            class="album-item"
            :class="{ active: selectedAlbum?.id === album.id }"
            @click="selectAlbum(album)"
          >
            <view class="album-item-content">
              <text class="album-item-title">{{ album.title }}</text>
              <text class="album-item-desc">{{ album.totalChapters }} 个章节</text>
            </view>
            <text v-if="selectedAlbum?.id === album.id" class="album-check">✓</text>
          </view>
          <view v-if="albums.length === 0" class="album-empty">
            <text>暂无专辑</text>
          </view>
        </scroll-view>
        <button class="album-create-btn" @click="showAlbumListPanel = false; showAlbumPanel = true">
          <text>+ 新建专辑</text>
        </button>
      </view>
    </view>

    <!-- 新建专辑面板 -->
    <view v-if="showAlbumPanel" class="album-panel" @click="showAlbumPanel = false">
      <view class="album-content" @click.stop>
        <view class="album-header">
          <text class="album-title">新建专辑</text>
          <text class="album-close" @click="showAlbumPanel = false">✕</text>
        </view>
        <view class="album-form">
          <view class="form-item">
            <text class="form-label">专辑名称 *</text>
            <input
              v-model="newAlbumTitle"
              class="form-input"
              placeholder="例如：我的有声书"
              maxlength="50"
            />
          </view>
          <view class="form-item">
            <text class="form-label">描述（可选）</text>
            <textarea
              v-model="newAlbumDescription"
              class="form-textarea"
              placeholder="简单描述这个专辑..."
              maxlength="200"
            />
          </view>
        </view>
        <button class="album-submit-btn" :disabled="!newAlbumTitle.trim()" @click="createAlbum">
          <text>创建专辑</text>
        </button>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import { onShow } from '@dcloudio/uni-app';
import { useUserStore } from '../../store/user';
import { useAudioStore } from '../../store/audio';
import { get, post, uploadFile } from '../../utils/request';
import type { VoiceParams } from '../../types';

const userStore = useUserStore();
const audioStore = useAudioStore();

// 状态
const text = ref('');
const selectedVoice = ref('voice_01');
const voiceParams = ref<VoiceParams>({
  speed: 1.0,
  pitch: 0,
  volume: 50,
});
const generating = ref(false);
const btnPressed = ref(false);
const previewingVoice = ref<string | null>(null);
let previewAudio: HTMLAudioElement | null = null;

// 文档上传状态
interface UploadedDoc {
  fileName: string;
  wordCount: number;
  fileSize: number;
  format: string;
  truncated: boolean;
}
const uploadedDoc = ref<UploadedDoc>({
  fileName: '',
  wordCount: 0,
  fileSize: 0,
  format: '',
  truncated: false,
});
const uploading = ref(false);

// scroll-top 用于避免 scrollTop 错误
const scrollTop = ref(0);

// 专辑相关状态
const selectedAlbum = ref<{ id: string; title: string } | null>(null);
const albums = ref<any[]>([]);
const showAlbumListPanel = ref(false);
const showAlbumPanel = ref(false);
const newAlbumTitle = ref('');
const newAlbumDescription = ref('');

// 新手引导状态
const showGuide = ref(false); // 已禁用引导功能
const guideStep = ref(1);
const guideSteps = [
  { step: 1, title: '输入文本', desc: '在文本框中输入要转换的文本内容', target: '.input-card' },
  { step: 2, title: '选择音色', desc: '选择你喜欢的声音音色', target: '.voice-card' },
  { step: 3, title: '调整参数', desc: '可以调整语速、音调、音量', target: '.params-card' },
  { step: 4, title: '生成音频', desc: '点击按钮开始生成', target: '.generate-btn' },
];

// 额度用尽弹窗
const showQuotaModal = ref(false);

// 计算属性
const canGenerate = computed(() => {
  return text.value.trim().length > 0 && !generating.value;
});

// 专辑相关函数
async function fetchAlbums() {
  try {
    const result = await get<{ albums: any[] }>('/book-generator/albums');
    albums.value = result.albums || [];
  } catch (error) {
    console.error('获取专辑列表失败:', error);
  }
}

function selectAlbum(album: any) {
  selectedAlbum.value = { id: album.id, title: album.title };
  showAlbumListPanel.value = false;
}

async function createAlbum() {
  if (!newAlbumTitle.value.trim()) return;

  try {
    const result = await post<{ id: number | string; title: string; description?: string }>('/book-generator/albums', {
      title: newAlbumTitle.value.trim(),
      description: newAlbumDescription.value.trim(),
    });

    if (result && result.id) {
      selectedAlbum.value = { id: String(result.id), title: result.title };
      await fetchAlbums(); // 刷新列表
      showAlbumPanel.value = false;
      newAlbumTitle.value = '';
      newAlbumDescription.value = '';
      uni.showToast({ title: '专辑创建成功', icon: 'success' });
    }
  } catch (error) {
    console.error('创建专辑失败:', error);
    uni.showToast({ title: '创建失败', icon: 'none' });
  }
}

// 加载用户偏好设置
async function loadUserPreferences() {
  try {
    // 先尝试从本地加载
    const localPrefs = uni.getStorageSync('userPreferences');
    if (localPrefs) {
      if (localPrefs.defaultVoiceId) {
        selectedVoice.value = localPrefs.defaultVoiceId;
      }
      if (localPrefs.defaultVolume !== undefined) {
        voiceParams.value.volume = localPrefs.defaultVolume;
      }
    }

    // 从服务器加载
    const result = await get<any>('/user/preferences');
    if (result) {
      if (result.defaultVoiceId) {
        selectedVoice.value = result.defaultVoiceId;
      }
      if (result.defaultVolume !== undefined) {
        voiceParams.value.volume = result.defaultVolume;
      }
      // 保存到本地
      uni.setStorageSync('userPreferences', result);
    }
  } catch (error) {
    console.error('加载用户偏好设置失败:', error);
  }
}

// 初始化
onMounted(async () => {
  await audioStore.fetchVoices();
  await fetchAlbums(); // 获取专辑列表
  await loadUserPreferences(); // 加载用户偏好设置

  // 检查是否显示新手引导（已禁用）
  // const hasSeenGuide = uni.getStorageSync('hasSeenCreateGuide');
  // if (!hasSeenGuide) {
  //   setTimeout(() => {
  //     showGuide.value = true;
  //   }, 500);
  // }
});

// 跳转到视频生成页面
function goToVideoGenerator() {
  uni.navigateTo({ url: '/pages/video-generator/index' });
}

// 跳转到 AI 生成内容页面
function goToAIGenerate() {
  uni.navigateTo({ url: '/pages/ai-generate/index' });
}

// 页面显示时检查是否有 AI 生成的文本
onShow(() => {
  const aiText = uni.getStorageSync('ai_generated_text');
  if (aiText) {
    text.value = aiText;
    uni.removeStorageSync('ai_generated_text');
    uni.showToast({ title: '已填充 AI 生成的文本', icon: 'success' });
  }
});

// 清空文本
function clearText() {
  text.value = '';
}

// 粘贴文本
async function pasteText() {
  const content = await uni.getClipboardData();
  if (content.data) {
    text.value = content.data;
  }
}

// 上传文档
async function handleUploadDoc() {
  if (uploading.value) return;

  try {
    // 使用 uni.chooseFile 选择文件（H5和App端支持）
    // #ifdef H5
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = '.txt,.docx,.pdf';
    input.onchange = async (e: any) => {
      const file = e.target.files?.[0];
      if (!file) return;
      await processUploadedFile(file);
    };
    input.click();
    return;
    // #endif

    // #ifdef APP-PLUS
    // App 端使用系统文件选择器
    const result = await (uni as any).chooseFile({
      extension: ['.txt', '.docx', '.pdf'],
      type: 'file',
    });
    if (result?.tempFiles?.[0]) {
      await processUploadedFile(result.tempFiles[0]);
    }
    // #endif

    // 小程序端暂不支持
    // #ifdef MP-WEIXIN
    uni.showToast({ title: '小程序暂不支持文档上传', icon: 'none' });
    // #endif
  } catch (error: any) {
    console.error('选择文件失败:', error);
    if (error.message && !error.message.includes('cancel')) {
      uni.showToast({ title: '选择文件失败', icon: 'none' });
    }
  }
}

// 处理上传的文件
async function processUploadedFile(file: any) {
  uploading.value = true;

  // 检查文件大小（20MB）
  if (file.size && file.size > 20 * 1024 * 1024) {
    uni.showToast({ title: '文件过大，最大支持20MB', icon: 'none' });
    uploading.value = false;
    return;
  }

  // 检查格式
  const name = (file.name || '').toLowerCase();
  if (!name.endsWith('.txt') && !name.endsWith('.docx') && !name.endsWith('.pdf')) {
    uni.showToast({ title: '不支持的格式，请上传 .txt .docx .pdf', icon: 'none' });
    uploading.value = false;
    return;
  }

  uni.showLoading({ title: '解析文档中...', mask: true });

  try {
    const filePath = file.path || file.tempFilePath || file;
    let result: any;

    // #ifdef H5
    // H5 端直接使用 FormData 上传
    const formData = new FormData();
    formData.append('file', file);
    const baseUrl = (await import('../../utils/config')).getApiBaseUrl();
    const token = uni.getStorageSync('token');
    const headers: Record<string, string> = {};
    if (token) headers['Authorization'] = `Bearer ${token}`;

    const response = await fetch(baseUrl + '/tts/upload-document', {
      method: 'POST',
      headers,
      body: formData,
    });
    const json = await response.json();
    if (json.code === 0) {
      result = json.data;
    } else {
      throw new Error(json.message || '解析失败');
    }
    // #endif

    // #ifdef APP-PLUS
    result = await uploadFile('/tts/upload-document', filePath);
    // #endif

    if (result && result.text) {
      // 更新上传状态
      uploadedDoc.value = {
        fileName: result.fileName || file.name,
        wordCount: result.wordCount || result.text.length,
        fileSize: result.fileSize || file.size || 0,
        format: result.format || '',
        truncated: result.truncated || false,
      };

      // 截取前2000字填充到文本框
      const maxLen = 2000;
      let displayText = result.text;
      if (displayText.length > maxLen) {
        displayText = displayText.substring(0, maxLen);
        uploadedDoc.value.truncated = true;
      }
      text.value = displayText;

      uni.hideLoading();
      uni.showToast({ title: `解析成功，${uploadedDoc.value.wordCount}字`, icon: 'success' });
    } else {
      throw new Error('文档内容为空');
    }
  } catch (error: any) {
    uni.hideLoading();
    console.error('文档上传失败:', error);
    uni.showToast({
      title: error.message || '文档解析失败',
      icon: 'none',
      duration: 3000,
    });
  } finally {
    uploading.value = false;
  }
}

// 清除已上传的文档
function clearDoc() {
  uploadedDoc.value = {
    fileName: '',
    wordCount: 0,
    fileSize: 0,
    format: '',
    truncated: false,
  };
}

// 格式化文件大小
function formatFileSize(bytes: number): string {
  if (!bytes || bytes <= 0) return '0 B';
  if (bytes < 1024) return bytes + ' B';
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
  return (bytes / 1024 / 1024).toFixed(2) + ' MB';
}

// 试听音色
async function previewVoice(voiceId: string) {
  // 如果正在试听当前音色，停止试听
  if (previewingVoice.value === voiceId) {
    stopPreview();
    return;
  }

  // 停止之前的试听
  stopPreview();

  try {
    previewingVoice.value = voiceId;
    uni.showLoading({ title: '生成试听音频...' });

    // 调用API生成预览音频
    const res = await post<{ previewText: string; voiceId: string; audioUrl: string }>('/tts/preview', {
      voiceId,
      voiceParams: voiceParams.value,
    });

    uni.hideLoading();

    if (res.audioUrl) {
      // #ifdef H5
      previewAudio = new Audio(res.audioUrl);
      previewAudio.play();
      previewAudio.onended = () => {
        previewingVoice.value = null;
        previewAudio = null;
      };
      // #endif

      // #ifndef H5
      // 非H5环境直接停止
      uni.showToast({ title: '试听已播放', icon: 'success' });
      setTimeout(() => {
        previewingVoice.value = null;
      }, 2000);
      // #endif
    }
  } catch (error: any) {
    uni.hideLoading();
    uni.showToast({ title: '试听生成失败', icon: 'none' });
    previewingVoice.value = null;
  }
}

// 停止试听
function stopPreview() {
  if (previewAudio) {
    previewAudio.pause();
    previewAudio = null;
  }
  previewingVoice.value = null;
}

// 生成音频
async function handleGenerate() {
  if (!canGenerate.value) return;

  // 检查额度（无限额度 -1 跳过检查）
  const quota = userStore.memberStatus?.quota;
  const quotaExhausted = quota && quota.dailyRemaining !== -1 && quota.dailyRemaining <= 0;
  if (quotaExhausted) {
    showQuotaModal.value = true;
    return;
  }

  // 如果没有选择专辑，使用后端自动创建的默认书籍
  const bookId = selectedAlbum.value?.id;

  generating.value = true;
  try {
    const result = await audioStore.generateAudio(
      text.value,
      selectedVoice.value,
      voiceParams.value,
      { bookId }
    );

    // 清空文本，方便下次输入
    text.value = '';

    // 和书籍创建一样，跳转到详情页等待音频生成
    uni.showToast({ title: '任务已提交', icon: 'success' });
    setTimeout(() => {
      uni.navigateTo({
        url: `/pages/book-generator/detail?id=${result.bookId}`
      });
    }, 800);
  } catch (error: any) {
    console.error('生成失败:', error);

    if (error.message?.includes('额度') || error.message?.includes('quota')) {
      showQuotaModal.value = true;
    } else {
      uni.showToast({
        title: error.message || '提交失败，请重试',
        icon: 'none'
      });
    }
  } finally {
    generating.value = false;
  }
}

// 新手引导 - 下一步
function nextGuideStep() {
  if (guideStep.value < guideSteps.length) {
    guideStep.value++;
  }
}

// 新手引导 - 关闭
function closeGuide() {
  showGuide.value = false;
  uni.setStorageSync('hasSeenCreateGuide', true);
}

// 跳转到会员页
function goToMember() {
  showQuotaModal.value = false;
  uni.navigateTo({ url: '/pages/member/index' });
}
</script>

<style scoped>
.page {
  min-height: 100vh;
  background: #f5f5f5;
}

.nav-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 88rpx;
  background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
  z-index: 100;
  padding-top: 44rpx;
}

.nav-content {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 32rpx;
  height: 88rpx;
}

.page-title {
  font-size: 34rpx;
  font-weight: 600;
  color: #ffffff;
}

.main-content {
  padding: 132rpx 32rpx 220rpx;
}

.card {
  background: #ffffff;
  border-radius: 24rpx;
  padding: 32rpx;
  margin-bottom: 24rpx;
  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24rpx;
}

.card-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #1f2937;
}

/* 文档上传卡片 */
.doc-upload-card {
  border-left: 6rpx solid #4F46E5;
}

.doc-upload-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40rpx 20rpx;
  border: 2rpx dashed #d1d5db;
  border-radius: 16rpx;
  background: #f9fafb;
  transition: all 0.2s;
}

.doc-upload-area:active {
  background: #eef2ff;
  border-color: #4F46E5;
}

.doc-upload-icon {
  font-size: 64rpx;
  margin-bottom: 12rpx;
}

.doc-upload-text {
  font-size: 28rpx;
  font-weight: 500;
  color: #4F46E5;
  margin-bottom: 8rpx;
}

.doc-upload-hint {
  font-size: 22rpx;
  color: #9ca3af;
}

.upload-status {
  font-size: 24rpx;
  color: #6b7280;
}

.upload-status.uploading {
  color: #f59e0b;
  animation: pulse 1.5s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

/* 文档信息栏 */
.doc-info-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20rpx;
  background: #f0fdf4;
  border-radius: 16rpx;
  border: 2rpx solid #86efac;
}

.doc-info-left {
  display: flex;
  align-items: center;
  gap: 16rpx;
  flex: 1;
  min-width: 0;
}

.doc-format-badge {
  flex-shrink: 0;
  font-size: 22rpx;
  font-weight: 700;
  color: #ffffff;
  background: linear-gradient(135deg, #4F46E5, #7C3AED);
  padding: 6rpx 14rpx;
  border-radius: 8rpx;
}

.doc-info-text {
  display: flex;
  flex-direction: column;
  gap: 4rpx;
  min-width: 0;
}

.doc-filename {
  font-size: 26rpx;
  font-weight: 600;
  color: #1f2937;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.doc-meta {
  font-size: 22rpx;
  color: #6b7280;
}

.doc-truncated-hint {
  font-size: 20rpx;
  color: #f59e0b;
}

.doc-remove-btn {
  flex-shrink: 0;
  width: 48rpx;
  height: 48rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32rpx;
  color: #ef4444;
  background: #fef2f2;
  border-radius: 50%;
}

.doc-remove-btn:active {
  background: #fca5a5;
  color: #ffffff;
}

/* 上传中提示 */
.doc-uploading-bar {
  padding: 24rpx;
  text-align: center;
  background: #fefce8;
  border-radius: 12rpx;
  font-size: 26rpx;
  color: #a16207;
  margin-top: 16rpx;
}

.word-count {
  font-size: 24rpx;
  color: #6b7280;
}

.word-count.warning {
  color: #f59e0b;
}

.word-count.error {
  color: #ef4444;
  font-weight: 600;
}

.text-input {
  width: 100%;
  height: 300rpx;
  font-size: 28rpx;
  color: #1f2937;
  line-height: 1.6;
  overflow-y: auto;
}

.input-actions {
  display: flex;
  justify-content: flex-end;
  gap: 16rpx;
  margin-top: 16rpx;
}

.input-hint {
  margin-top: 12rpx;
  text-align: right;
}

.input-hint text {
  font-size: 22rpx;
  color: #9ca3af;
}

.action-btn {
  font-size: 24rpx;
  color: #6b7280;
  background: #f3f4f6;
  padding: 12rpx 24rpx;
  border-radius: 12rpx;
  border: none;
  transition: all 0.2s;
}

.action-btn:active {
  opacity: 0.7;
  transform: scale(0.98);
}

.action-btn::after {
  border: none;
}

.voice-list {
  white-space: nowrap;
  margin-top: 24rpx;
}

/* 音色网格布局 - 2列 */
.voice-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16rpx;
  margin-top: 24rpx;
}

.voice-item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 24rpx 16rpx;
  border-radius: 16rpx;
  background: #f9fafb;
  border: 2rpx solid transparent;
  transition: all 0.3s;
}

.voice-item.active {
  background: linear-gradient(135deg, #4f46e5 0%, #6366f1 100%);
  border-color: #4f46e5;
}

.voice-item.active .voice-name {
  color: #ffffff;
}

.voice-item:active {
  transform: scale(0.95);
}

.voice-icon {
  font-size: 48rpx;
  margin-bottom: 12rpx;
}

.voice-name {
  font-size: 26rpx;
  font-weight: 500;
  color: #1f2937;
  margin-bottom: 4rpx;
}

.voice-preview-btn {
  position: absolute;
  top: 8rpx;
  right: 8rpx;
  width: 40rpx;
  height: 40rpx;
  background: rgba(79, 70, 229, 0.9);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20rpx;
  color: #ffffff;
}

.voice-item.active .voice-preview-btn {
  background: rgba(255, 255, 255, 0.9);
  color: #4f46e5;
}

.voice-desc {
  font-size: 20rpx;
  color: #6b7280;
}

.param-item {
  margin-top: 24rpx;
}

.param-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12rpx;
}

.param-label {
  font-size: 26rpx;
  color: #6b7280;
}

.param-value {
  font-size: 28rpx;
  font-weight: 600;
  color: #4F46E5;
  background: #EEF2FF;
  padding: 4rpx 16rpx;
  border-radius: 8rpx;
}

.param-range {
  display: flex;
  justify-content: space-between;
  margin-top: 8rpx;
}

.param-range text {
  font-size: 22rpx;
  color: #9ca3af;
}

/* 专辑选择 */
.album-card {
  background: #ffffff;
  border-radius: 24rpx;
  padding: 32rpx;
  margin-bottom: 24rpx;
  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
}

.card-header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20rpx;
}

.album-add-btn {
  font-size: 28rpx;
  color: #4f46e5;
  font-weight: 500;
}

.album-selector {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #f9fafb;
  border-radius: 16rpx;
  padding: 24rpx;
}

.album-name {
  font-size: 28rpx;
  color: #1f2937;
  font-weight: 500;
}

.album-placeholder {
  font-size: 28rpx;
  color: #9ca3af;
}

.album-arrow {
  font-size: 40rpx;
  color: #9ca3af;
}

/* 专辑面板 */
.album-panel {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 1000;
  display: flex;
  align-items: flex-end;
}

.album-content {
  width: 100%;
  max-height: 80vh;
  background: #ffffff;
  border-radius: 32rpx 32rpx 0 0;
  padding: 32rpx;
  display: flex;
  flex-direction: column;
}

.album-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24rpx;
}

.album-title {
  font-size: 34rpx;
  font-weight: 600;
  color: #1f2937;
}

.album-close {
  font-size: 40rpx;
  color: #9ca3af;
  padding: 8rpx;
}

.album-list {
  flex: 1;
  max-height: 50vh;
}

.album-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 24rpx;
  border-radius: 16rpx;
  background: #f9fafb;
  margin-bottom: 16rpx;
}

.album-item.active {
  background: #eef2ff;
  border: 2px solid #4f46e5;
}

.album-item-content {
  flex: 1;
}

.album-item-title {
  display: block;
  font-size: 28rpx;
  font-weight: 600;
  color: #1f2937;
  margin-bottom: 8rpx;
}

.album-item-desc {
  display: block;
  font-size: 24rpx;
  color: #6b7280;
}

.album-check {
  font-size: 32rpx;
  color: #4f46e5;
  margin-left: 16rpx;
}

.album-empty {
  text-align: center;
  padding: 60rpx 0;
  color: #9ca3af;
  font-size: 28rpx;
}

.album-create-btn,
.album-submit-btn {
  width: 100%;
  height: 100rpx;
  background: linear-gradient(135deg, #4f46e5 0%, #818cf8 100%);
  border-radius: 24rpx;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32rpx;
  font-weight: 600;
  color: #ffffff;
  margin-top: 24rpx;
}

.album-create-btn::after,
.album-submit-btn::after {
  border: none;
}

/* 专辑表单 */
.album-form {
  margin: 24rpx 0;
}

.form-item {
  margin-bottom: 24rpx;
}

.form-label {
  display: block;
  font-size: 28rpx;
  color: #1f2937;
  font-weight: 500;
  margin-bottom: 12rpx;
}

.form-input {
  width: 100%;
  height: 88rpx;
  background: #f9fafb;
  border-radius: 16rpx;
  padding: 0 24rpx;
  font-size: 28rpx;
  color: #1f2937;
}

.form-textarea {
  width: 100%;
  min-height: 160rpx;
  background: #f9fafb;
  border-radius: 16rpx;
  padding: 24rpx;
  font-size: 28rpx;
  color: #1f2937;
  line-height: 1.6;
}

.generate-btn {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 120rpx;
  padding: 16rpx 32rpx;
  padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
  background: linear-gradient(135deg, #4f46e5 0%, #818cf8 100%);
  border-radius: 0;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 -4rpx 24rpx rgba(79, 70, 229, 0.3);
  transition: opacity 0.3s ease, transform 0.3s ease;
  opacity: 1;
  z-index: 1001;
}

.generate-btn::after {
  border: none;
}

.generate-btn.disabled {
  opacity: 0.5;
  background: #9ca3af;
  box-shadow: none;
}

.generate-btn.pressed {
  transform: scale(0.98);
}

/* 视频生成入口卡片 */
.video-entry-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 16rpx;
  padding: 30rpx;
  margin-top: 20rpx;
}

.video-entry-content {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.video-entry-icon {
  font-size: 60rpx;
}

.video-entry-text {
  display: flex;
  flex-direction: column;
  gap: 6rpx;
}

.video-entry-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #ffffff;
}

.video-entry-desc {
  font-size: 24rpx;
  color: rgba(255, 255, 255, 0.8);
}

.video-entry-arrow {
  font-size: 40rpx;
  color: #ffffff;
}

.btn-text {
  font-size: 34rpx;
  font-weight: 600;
  color: #ffffff;
  letter-spacing: 2rpx;
}

/* 音频生成入口卡片 */
.audio-entry-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
  border-radius: 16rpx;
  padding: 30rpx;
  margin-top: 20rpx;
}

.audio-entry-content {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.audio-entry-icon {
  font-size: 60rpx;
}

.audio-entry-text {
  display: flex;
  flex-direction: column;
  gap: 6rpx;
}

.audio-entry-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #ffffff;
}

.audio-entry-desc {
  font-size: 24rpx;
  color: rgba(255, 255, 255, 0.8);
}

.audio-entry-arrow {
  font-size: 40rpx;
  color: #ffffff;
}

.ai-btn {
  display: flex;
  align-items: center;
  gap: 8rpx;
}

/* 新手引导 */
.guide-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.8);
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.guide-content {
  width: 600rpx;
  background: #ffffff;
  border-radius: 32rpx;
  padding: 48rpx 40rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.guide-header {
  margin-bottom: 24rpx;
}

.guide-step {
  font-size: 24rpx;
  color: #9ca3af;
}

.guide-body {
  text-align: center;
  margin-bottom: 32rpx;
}

.guide-title {
  font-size: 36rpx;
  font-weight: 600;
  color: #1f2937;
  display: block;
  margin-bottom: 16rpx;
}

.guide-desc {
  font-size: 28rpx;
  color: #6b7280;
  display: block;
  line-height: 1.6;
}

.guide-dots {
  display: flex;
  gap: 12rpx;
  margin-bottom: 32rpx;
}

.guide-dot {
  width: 12rpx;
  height: 12rpx;
  border-radius: 50%;
  background: #e5e7eb;
}

.guide-dot.active {
  background: #4f46e5;
  width: 32rpx;
  border-radius: 6rpx;
}

.guide-actions {
  display: flex;
  gap: 20rpx;
  width: 100%;
}

.guide-btn {
  flex: 1;
  height: 88rpx;
  border-radius: 44rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30rpx;
  border: none;
}

.guide-btn::after {
  border: none;
}

.guide-btn.skip {
  background: #f3f4f6;
  color: #6b7280;
}

.guide-btn.next,
.guide-btn.finish {
  background: linear-gradient(135deg, #4f46e5 0%, #818cf8 100%);
  color: #ffffff;
}

/* 额度用尽弹窗 */
.quota-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.quota-content {
  width: 600rpx;
  background: #ffffff;
  border-radius: 32rpx;
  padding: 60rpx 40rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.quota-icon {
  font-size: 100rpx;
  margin-bottom: 24rpx;
}

.quota-title {
  font-size: 36rpx;
  font-weight: 600;
  color: #1f2937;
  margin-bottom: 12rpx;
}

.quota-desc {
  font-size: 28rpx;
  color: #6b7280;
  margin-bottom: 40rpx;
}

.quota-actions {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 20rpx;
}

.quota-btn {
  width: 100%;
  height: 88rpx;
  border-radius: 44rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30rpx;
  border: none;
}

.quota-btn::after {
  border: none;
}

.quota-btn.primary {
  background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
  color: #ffffff;
}

.quota-btn.secondary {
  background: #f3f4f6;
  color: #6b7280;
}
</style>
