<template>
  <div class="create-sidebar storyboard-video-sidebar">
    <!-- 模式切换按钮 -->
    <div class="mode-switcher">
      <button 
        v-for="mode in modes" 
        :key="mode.key"
        @click="handleModeSwitch(mode.key)"
        :class="['mode-btn', { active: mode.key === 'storyboard' }]"
      >
        {{ mode.label }}
      </button>
    </div>

    <div class="sidebar-content">
      <div class="step-container">
        <div class="steps">
          <span :class="{ active: currentStep === 1 }">生成分镜图</span>
          <span class="separator">&gt;</span>
          <span :class="{ active: currentStep === 2 }">生成视频</span>
    </div>

        <!-- Step 1: Generate Storyboard -->
        <div v-if="currentStep === 1" class="step-1-content">
          
          <!-- 区块1: 自定义分镜图上传 -->
          <div class="section-card">
            <div class="section-header">
              <span class="section-title">自定义分镜图</span>
              <span class="section-subtitle">上传现成的分镜图，直接生成视频</span>
            </div>
            <div class="custom-storyboard-upload">
              <button 
                class="upload-btn-single"
                @click="triggerCustomFileInput"
                @dragover.prevent
                @drop.prevent="handleCustomDrop"
              >
                <input 
                  ref="customFileInput"
                  type="file" 
                  accept="image/png, image/jpeg, image/gif" 
                  @change="handleCustomFileSelect"
                  style="display: none"
                />
                <span v-if="!customStoryboardImages.length" class="btn-text">+ 上传分镜图</span>
                <span v-else class="btn-text">已上传</span>
              </button>
              <div v-if="customStoryboardImages.length > 0" class="preview-thumbnail">
                <img :src="customStoryboardImages[0]" alt="分镜图预览" />
                <button class="remove-btn small" @click="removeCustomImage(0)">×</button>
              </div>
            </div>
      </div>

          <!-- 分隔线 -->
          <div class="divider-line">
            <span class="divider-text">或</span>
          </div>

          <!-- 区块2: AI 生成分镜图 -->
          <div class="section-card">
            <div class="section-header">
              <span class="section-title">AI 生成分镜图</span>
              <span class="section-subtitle">输入提示词，AI 自动生成分镜图</span>
        </div>

            <!-- 参考图上传（可选） -->
            <div class="reference-upload-area">
              
              <div class="reference-grid-single">
                <div 
                  v-if="!referenceImages.length"
                  class="reference-tile upload" 
                  @click="triggerReferenceFileInput" 
                  @dragover.prevent 
                  @drop.prevent="handleReferenceDrop"
                >
                  <input 
                    ref="referenceFileInput"
                    type="file" 
                    accept="image/png, image/jpeg, image/gif" 
                    @change="handleReferenceFileSelect"
                    style="display: none"
                  />
                  <span class="plus-icon">＋</span>
                </div>
                <div 
                  v-else
                  class="reference-tile preview"
                >
                  <img :src="referenceImages[0]" :alt="参考图" />
                  <button class="remove-btn small" @click="removeReferenceImage(0)">×</button>
                </div>
              </div>
        </div>

            <!-- 提示词输入 -->
            <div class="prompt-area">
              <textarea v-model="promptText" placeholder="例如：一个咖啡的广告提示：简单描述即可，AI会自动优化成专业的12格黑白分镜图"></textarea>
        </div>

            <!-- 设置项 -->
            <div class="settings">
              <div class="setting-row">
                <span class="setting-label">模型</span>
                <div class="setting-control">
                  <div class="custom-select" @click="toggleStoryboardModelDropdown" v-click-outside="closeStoryboardModelDropdown">
                    <div class="select-display">
                      <span class="select-text">{{ storyboardModelOptions.find(opt => opt.value === storyboardModel)?.label }}</span>
                       <svg class="dropdown-arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <polyline points="6,9 12,15 18,9"></polyline>
                      </svg>
                    </div>
                    <div v-if="showStoryboardModelDropdown" class="select-dropdown">
                      <div v-for="option in storyboardModelOptions" :key="option.value" @click.stop="selectStoryboardModel(option.value)" class="select-option" :class="{ active: storyboardModel === option.value }">
                        <span class="option-text">{{ option.label }}</span>
                        <span v-if="storyboardModel === option.value" class="check-mark">✓</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div class="setting-row">
                <span class="setting-label">比例</span>
                <div class="setting-control">
                  <div class="custom-select" @click="toggleStoryboardRatioDropdown" v-click-outside="closeStoryboardRatioDropdown">
                    <div class="select-display">
                      <span class="select-text">{{ storyboardRatioOptions.find(opt => opt.value === storyboardRatio)?.label }}</span>
                      <svg class="dropdown-arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <polyline points="6,9 12,15 18,9"></polyline>
                      </svg>
                    </div>
                    <div v-if="showStoryboardRatioDropdown" class="select-dropdown">
                      <div v-for="option in storyboardRatioOptions" :key="option.value" @click.stop="selectStoryboardRatio(option.value)" class="select-option" :class="{ active: storyboardRatio === option.value }">
                        <span class="option-text">{{ option.label }}</span>
                        <span v-if="storyboardRatio === option.value" class="check-mark">✓</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div class="setting-row quality-row">
                <div class="quality-left">
                  <span class="setting-label">高清模式 (1080P)</span>
                  <label class="switch">
                    <input type="checkbox" v-model="storyboardHighQuality">
                    <span class="slider"></span>
                  </label>
                </div>
              </div>
            </div>
             <div class="action-section">
                <button class="generate-btn" @click="submitStoryboardGeneration">生成分镜图</button>
            </div>
        </div>
      </div>

        <!-- Step 2: Generate Video from Storyboard -->
        <div v-else class="step-2-content">
          <!-- 分镜图网格 -->
          <div class="storyboard-section">
            <div class="section-subtitle-small">已选分镜图（{{ storyboardImages.length }}张）</div>
            <div class="storyboard-images-grid">
              <div 
                v-for="(image, index) in storyboardImages" 
            :key="index"
                class="storyboard-image-item"
              >
                <img :src="image" :alt="`图${index + 1}`" />
                <button @click="removeStoryboardImage(index)" class="remove-btn">×</button>
                <span class="image-label">图{{ index + 1 }}</span>
            </div>
          </div>
          </div>

          <!-- 视频描述 -->
          <div class="prompt-area step2-prompt">
            <label class="prompt-label">视频描述</label>
            <textarea 
              v-model="videoPrompt" 
              placeholder="描述如何将这些分镜图生成视频，例如：&#10;- 将这些分镜图连贯衔接成一个完整的咖啡广告视频&#10;- 添加平滑的镜头转场效果&#10;- 整体风格温馨自然"
            ></textarea>
            
          </div>

          <!-- 视频设置 -->
          <div class="settings">
            <!-- 模型选择 -->
            <div class="setting-row">
              <span class="setting-label">模型</span>
              <div class="setting-control">
                <div class="custom-select" @click="toggleModelDropdown" v-click-outside="closeModelDropdown">
                  <div class="select-display">
                    <svg class="model-icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
                  <path d="M646.78 186.44a63.586 63.586 0 0 0-63.59 0L262.34 371.69a63.594 63.594 0 0 0-31.79 55.07V791.7L483.2 937.56a63.586 63.586 0 0 0 63.59 0l320.85-185.25a63.594 63.594 0 0 0 31.79-55.07V332.31L646.78 186.44z" fill="#E9F1FF"/>
                  <path d="M308.28 860.59c-4.3 0-8.62-1.11-12.5-3.35l-153.91-88.86c-22.8-13.16-36.97-37.7-36.97-64.03 0-13.81 11.19-25 25-25s25 11.19 25 25c0 8.52 4.59 16.47 11.97 20.73l109.54 63.24a623.714 623.714 0 0 1-2.96-60.67c0-128.91 39.36-252.4 113.83-357.1a619.428 619.428 0 0 1 128.04-132.71c35.86-27.49 74.43-50.86 115.14-69.78l-106.5-61.48c-7.38-4.26-16.55-4.26-23.94 0l-151.99 87.75c-11.96 6.9-27.25 2.81-34.15-9.15-6.9-11.96-2.81-27.25 9.15-34.15l151.99-87.75c22.8-13.17 51.13-13.17 73.94 0l150.36 86.81c8.41 4.85 13.24 14.14 12.41 23.81-0.84 9.67-7.2 17.98-16.31 21.32-53.72 19.67-104.08 47.36-149.68 82.32a569.319 569.319 0 0 0-117.72 122.01c-68.41 96.19-104.57 209.66-104.57 328.13 0 34.71 3.17 69.5 9.42 103.41 1.77 9.59-2.2 19.33-10.17 24.95a25.194 25.194 0 0 1-14.42 4.55zM129.9 458.1c-13.81 0-25-11.19-25-25V319.65c0-26.33 14.17-50.87 36.97-64.03l101.75-58.75c11.96-6.9 27.25-2.81 34.15 9.15 6.9 11.96 2.81 27.25-9.15 34.15l-101.75 58.75c-7.38 4.26-11.97 12.2-11.97 20.73V433.1c0 13.81-11.19 25-25 25z" fill="#2C5CCB"/>
                  <path d="M711.52 863.03c-8.64 0-17.04-4.48-21.67-12.5-6.9-11.96-2.81-27.25 9.15-34.15l158.13-91.3c7.38-4.26 11.97-12.2 11.97-20.73V575.49a624.941 624.941 0 0 1-48.78 31.27c-94.53 54.58-199.75 82.76-307.42 82.76-20.03 0-40.13-0.97-60.28-2.94a619.251 619.251 0 0 1-179.54-45.27c-41.83-17.53-81.41-39.5-118.18-65.55v128.59c0 8.52 4.59 16.47 11.97 20.73l153.91 88.86c11.96 6.9 16.05 22.19 9.15 34.15-6.9 11.96-22.19 16.05-34.15 9.15l-153.91-88.86c-22.8-13.16-36.97-37.7-36.97-64.03V524.81c0-9.73 5.65-18.58 14.47-22.67 8.83-4.1 19.23-2.7 26.66 3.58 43.9 37.08 93.15 67.19 146.37 89.49 52.69 22.08 108.22 36.09 165.06 41.62 118 11.49 234.82-13.88 337.85-73.36 29.25-16.89 57.06-36.4 82.66-58a25.01 25.01 0 0 1 26.66-3.56 24.995 24.995 0 0 1 14.46 22.67v179.77c0 26.33-14.17 50.87-36.97 64.03l-158.13 91.3a24.873 24.873 0 0 1-12.47 3.35z" fill="#2C5CCB"/>
                  <path d="M512 970.61c-12.78 0-25.57-3.29-36.97-9.87l-100.04-57.76c-11.96-6.9-16.05-22.19-9.15-34.15 6.9-11.96 22.19-16.05 34.15-9.15l100.04 57.76c7.38 4.26 16.55 4.26 23.94 0l95.6-55.2c11.96-6.9 27.25-2.81 34.15 9.15 6.9 11.96 2.81 27.25-9.15 34.15l-95.6 55.2a74.06 74.06 0 0 1-36.97 9.87zM711.5 863.02c-5.09 0-10.16-1.55-14.47-4.62a25.007 25.007 0 0 1-10.09-25.05c10.81-56.94 12.77-115.11 5.82-172.9a569.326 569.326 0 0 0-45.87-165.32c-48.93-109.06-129.7-198.4-233.57-258.37-27.63-15.95-56.71-29.65-86.43-40.7a25.002 25.002 0 0 1-16.2-21.34c-0.81-9.65 4.03-18.9 12.41-23.74l151.93-87.72c22.8-13.17 51.13-13.17 73.94 0l150.36 86.81c11.96 6.9 16.05 22.19 9.15 34.15-6.9 11.96-22.19 16.05-34.15 9.15l-150.36-86.81c-7.38-4.26-16.55-4.26-23.94 0L391.7 169.12a626.826 626.826 0 0 1 46.62 24.35c113.03 65.26 200.93 162.5 254.19 281.21a619.708 619.708 0 0 1 49.9 179.82c5.45 45.36 5.86 90.95 1.25 136.1l113.47-65.51c7.38-4.26 11.97-12.2 11.97-20.73 0-13.81 11.19-25 25-25s25 11.19 25 25c0 26.33-14.17 50.87-36.97 64.03L724 859.67a24.963 24.963 0 0 1-12.5 3.35zM894.1 457.96c-13.81 0-25-11.19-25-25V319.65c0-8.52-4.59-16.47-11.97-20.73L754.04 239.4c-11.96-6.9-16.05-22.19-9.15-34.15 6.9-11.96 22.19-16.05 34.15-9.15l103.09 59.52c22.8 13.16 36.97 37.7 36.97 64.03v113.32c0 13.8-11.2 24.99-25 24.99z" fill="#2C5CCB"/>
                  <path d="M0 513.47h1024v1H0z" fill="#2C5CCB"/>
                </svg>
                    <span class="select-text">{{ modelOptions.find(opt => opt.value === videoModel)?.label || 'Sora2.0' }}</span>
                    <svg class="dropdown-arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                      <polyline points="6,9 12,15 18,9"></polyline>
                    </svg>
                  </div>
                  <div v-if="showModelDropdown" class="select-dropdown">
                    <div 
                      v-for="option in modelOptions" 
                      :key="option.value"
                      @click.stop="selectModel(option.value)"
                      class="select-option"
                      :class="{ active: videoModel === option.value }"
                    >
                    <svg class="model-icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
                  <path d="M646.78 186.44a63.586 63.586 0 0 0-63.59 0L262.34 371.69a63.594 63.594 0 0 0-31.79 55.07V791.7L483.2 937.56a63.586 63.586 0 0 0 63.59 0l320.85-185.25a63.594 63.594 0 0 0 31.79-55.07V332.31L646.78 186.44z" fill="#E9F1FF"/>
                  <path d="M308.28 860.59c-4.3 0-8.62-1.11-12.5-3.35l-153.91-88.86c-22.8-13.16-36.97-37.7-36.97-64.03 0-13.81 11.19-25 25-25s25 11.19 25 25c0 8.52 4.59 16.47 11.97 20.73l109.54 63.24a623.714 623.714 0 0 1-2.96-60.67c0-128.91 39.36-252.4 113.83-357.1a619.428 619.428 0 0 1 128.04-132.71c35.86-27.49 74.43-50.86 115.14-69.78l-106.5-61.48c-7.38-4.26-16.55-4.26-23.94 0l-151.99 87.75c-11.96 6.9-27.25 2.81-34.15-9.15-6.9-11.96-2.81-27.25 9.15-34.15l151.99-87.75c22.8-13.17 51.13-13.17 73.94 0l150.36 86.81c8.41 4.85 13.24 14.14 12.41 23.81-0.84 9.67-7.2 17.98-16.31 21.32-53.72 19.67-104.08 47.36-149.68 82.32a569.319 569.319 0 0 0-117.72 122.01c-68.41 96.19-104.57 209.66-104.57 328.13 0 34.71 3.17 69.5 9.42 103.41 1.77 9.59-2.2 19.33-10.17 24.95a25.194 25.194 0 0 1-14.42 4.55zM129.9 458.1c-13.81 0-25-11.19-25-25V319.65c0-26.33 14.17-50.87 36.97-64.03l101.75-58.75c11.96-6.9 27.25-2.81 34.15 9.15 6.9 11.96 2.81 27.25-9.15 34.15l-101.75 58.75c-7.38 4.26-11.97 12.2-11.97 20.73V433.1c0 13.81-11.19 25-25 25z" fill="#2C5CCB"/>
                  <path d="M711.52 863.03c-8.64 0-17.04-4.48-21.67-12.5-6.9-11.96-2.81-27.25 9.15-34.15l158.13-91.3c7.38-4.26 11.97-12.2 11.97-20.73V575.49a624.941 624.941 0 0 1-48.78 31.27c-94.53 54.58-199.75 82.76-307.42 82.76-20.03 0-40.13-0.97-60.28-2.94a619.251 619.251 0 0 1-179.54-45.27c-41.83-17.53-81.41-39.5-118.18-65.55v128.59c0 8.52 4.59 16.47 11.97 20.73l153.91 88.86c11.96 6.9 16.05 22.19 9.15 34.15-6.9 11.96-22.19 16.05-34.15 9.15l-153.91-88.86c-22.8-13.16-36.97-37.7-36.97-64.03V524.81c0-9.73 5.65-18.58 14.47-22.67 8.83-4.1 19.23-2.7 26.66 3.58 43.9 37.08 93.15 67.19 146.37 89.49 52.69 22.08 108.22 36.09 165.06 41.62 118 11.49 234.82-13.88 337.85-73.36 29.25-16.89 57.06-36.4 82.66-58a25.01 25.01 0 0 1 26.66-3.56 24.995 24.995 0 0 1 14.46 22.67v179.77c0 26.33-14.17 50.87-36.97 64.03l-158.13 91.3a24.873 24.873 0 0 1-12.47 3.35z" fill="#2C5CCB"/>
                  <path d="M512 970.61c-12.78 0-25.57-3.29-36.97-9.87l-100.04-57.76c-11.96-6.9-16.05-22.19-9.15-34.15 6.9-11.96 22.19-16.05 34.15-9.15l100.04 57.76c7.38 4.26 16.55 4.26 23.94 0l95.6-55.2c11.96-6.9 27.25-2.81 34.15 9.15 6.9 11.96 2.81 27.25-9.15 34.15l-95.6 55.2a74.06 74.06 0 0 1-36.97 9.87zM711.5 863.02c-5.09 0-10.16-1.55-14.47-4.62a25.007 25.007 0 0 1-10.09-25.05c10.81-56.94 12.77-115.11 5.82-172.9a569.326 569.326 0 0 0-45.87-165.32c-48.93-109.06-129.7-198.4-233.57-258.37-27.63-15.95-56.71-29.65-86.43-40.7a25.002 25.002 0 0 1-16.2-21.34c-0.81-9.65 4.03-18.9 12.41-23.74l151.93-87.72c22.8-13.17 51.13-13.17 73.94 0l150.36 86.81c11.96 6.9 16.05 22.19 9.15 34.15-6.9 11.96-22.19 16.05-34.15 9.15l-150.36-86.81c-7.38-4.26-16.55-4.26-23.94 0L391.7 169.12a626.826 626.826 0 0 1 46.62 24.35c113.03 65.26 200.93 162.5 254.19 281.21a619.708 619.708 0 0 1 49.9 179.82c5.45 45.36 5.86 90.95 1.25 136.1l113.47-65.51c7.38-4.26 11.97-12.2 11.97-20.73 0-13.81 11.19-25 25-25s25 11.19 25 25c0 26.33-14.17 50.87-36.97 64.03L724 859.67a24.963 24.963 0 0 1-12.5 3.35zM894.1 457.96c-13.81 0-25-11.19-25-25V319.65c0-8.52-4.59-16.47-11.97-20.73L754.04 239.4c-11.96-6.9-16.05-22.19-9.15-34.15 6.9-11.96 22.19-16.05 34.15-9.15l103.09 59.52c22.8 13.16 36.97 37.7 36.97 64.03v113.32c0 13.8-11.2 24.99-25 24.99z" fill="#2C5CCB"/>
                  <path d="M0 513.47h1024v1H0z" fill="#2C5CCB"/>
                </svg>
                      <span class="option-text">{{ option.label }}</span>
                      <span v-if="videoModel === option.value" class="check-mark">✓</span>
                    </div>
                  </div>
                </div>
        </div>
      </div>

            <!-- 比例选择 -->
            <div class="setting-row">
              <span class="setting-label">比例</span>
              <div class="setting-control">
                <div class="custom-select" @click="toggleRatioDropdown" v-click-outside="closeRatioDropdown">
                  <div class="select-display">
                    <span class="select-text">{{ ratioOptions.find(opt => opt.value === videoRatio)?.label || '竖屏 (9:16)' }}</span>
                    <svg class="dropdown-arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                      <polyline points="6,9 12,15 18,9"></polyline>
                    </svg>
                  </div>
                  <div v-if="showRatioDropdown" class="select-dropdown">
                    <div 
                      v-for="option in ratioOptions" 
                      :key="option.value"
                      @click.stop="selectRatio(option.value)"
                      class="select-option"
                      :class="{ active: videoRatio === option.value }"
                    >
                      <span class="option-text">{{ option.label }}</span>
                      <span v-if="videoRatio === option.value" class="check-mark">✓</span>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <!-- 时长选择 -->
            <div class="setting-row">
              <span class="setting-label">时长</span>
              <div class="setting-control">
                <div class="custom-select" @click="toggleDurationDropdown" v-click-outside="closeDurationDropdown">
                  <div class="select-display">
                    <span class="select-text">{{ durationOptions.find(opt => opt.value === duration)?.label || '10秒' }}</span>
                    <svg class="dropdown-arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                      <polyline points="6,9 12,15 18,9"></polyline>
                    </svg>
                  </div>
                  <div v-if="showDurationDropdown" class="select-dropdown">
                    <div 
                      v-for="option in durationOptions" 
                      :key="option.value"
                      @click.stop="selectDuration(option.value)"
                      class="select-option"
                      :class="{ active: duration === option.value }"
                    >
                      <span class="option-text">{{ option.label }}</span>
                      <span v-if="duration === option.value" class="check-mark">✓</span>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <!-- 高清模式 -->
            <div class="setting-row quality-row">
              <div class="quality-left">
                <span class="setting-label">高清模式 (1080P)</span>
                <label class="switch">
                  <input type="checkbox" v-model="highQuality">
                  <span class="slider"></span>
                </label>
              </div>
            </div>
          </div>

          <!-- 生成按钮 -->
          <div class="action-section" v-if="currentStep === 2">
            <button class="generate-btn" @click="submitVideoGeneration">
              生成视频
            
        </button>
          </div>
        </div>
      </div>
    </div>
  <!-- 生成遮罩层 -->
  <div v-if="generatingMaskVisible" class="mask-overlay">
    <div class="mask-dialog">
      <div class="spinner"></div>
      <div class="mask-text">{{ generatingMaskTip }}</div>
      <div class="mask-sub">生成过程依赖云端算力，请保持页面打开</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { submitAITask, getAITaskDetail, getAIModels } from '../../api'
import { uploadFileToOss } from '../../api/files'
import { useUserStore } from '../../store/user'

// 定义props
const props = defineProps({
  remakePrompt: {
    type: String,
    default: ''
  },
  remakeImageUrl: {
    type: String,
    default: ''
  },
  remakeAspectRatio: {
    type: String,
    default: ''
  }
})

// 定义emit
const emit = defineEmits(['switch-mode', 'task-update', 'switch-to-image-mode', 'remake-done'])

// 模式数据
const modes = [
  { key: 'text', label: '文生视频' },
  { key: 'image', label: '图生视频' },
  { key: 'storyboard', label: '分镜视频' }
]

// 响应式数据
const uploadedImage = ref(null)
const fileInput = ref(null)
// 步骤一：图生视频参考图
const referenceImages = ref([])
const referenceFileInput = ref(null)
// 步骤一：自定义分镜图上传
const customStoryboardImages = ref([])
const customFileInput = ref(null)
const currentStep = ref(1) // 1: 生成分镜图；2: 生成视频
const promptText = ref('') // Step 1: 分镜图生成提示词
const videoPrompt = ref('') // Step 2: 视频生成提示词
const storyboardImages = ref([]) // 分镜图数组（步骤二）

// --- Step 1: AI Storyboard Generation State ---
const storyboardModel = ref('sora2_storyboard')
const storyboardRatio = ref('16:9')
const storyboardHighQuality = ref(false)
const showStoryboardModelDropdown = ref(false)
const showStoryboardRatioDropdown = ref(false)
const storyboardModelOptions = [
  { value: 'sora2_storyboard', label: 'Sora2.0 Storyboard' }
]

// --- Step 2: Video Generation State ---
const videoModel = ref('Sora2_img_video')
const videoRatio = ref('portrait') // portrait (9:16) or landscape (16:9)
const duration = ref(10)
const highQuality = ref(false)
const showModelDropdown = ref(false)
const showRatioDropdown = ref(false)
const showDurationDropdown = ref(false)
const availableModels = ref([]) // 从API获取的可用模型列表

// 下拉框选项
const modelOptions = [
  { value: 'Sora2_img_video', label: 'Sora2_img_video' }
]

const ratioOptions = [
  { value: 'portrait', label: '竖屏 (9:16)' },
  { value: 'landscape', label: '横屏 (16:9)' }
]

const durationOptions = [
  { value: 10, label: '10秒' },
  { value: 15, label: '15秒' }
]

// 计算匹配的模型（与图生视频逻辑一致）
const matchedModel = computed(() => {
  if (availableModels.value.length === 0) return null
  const targetAspectRatio = videoRatio.value === 'portrait' ? '9:16' : '16:9'
  const targetDuration = duration.value.toString()
  const targetSize = highQuality.value ? 'large' : 'small'
  return availableModels.value.find(m => {
    const config = m.extendedConfig
    return config.aspectRatio === targetAspectRatio && config.duration === targetDuration && config.size === targetSize
  })
})

// 计算所需积分
const requiredPoints = computed(() => {
  return matchedModel.value ? matchedModel.value.pointsCost : 0
})

// --- Hardcoded image generation models (text_to_image)
const TEXT_IMAGE_MODELS = {
  auto: { modelName: 'sc_soraimg_text_auto', points: 30, aspect: 'auto' },
  '1:1': { modelName: 'sc_soraimg_text_1x1', points: 30, aspect: '1:1' },
  '2:3': { modelName: 'sc_soraimg_text_2x3', points: 30, aspect: '2:3' },
  '3:2': { modelName: 'sc_soraimg_text_3x2', points: 30, aspect: '3:2' }
}

// --- Hardcoded image2image models
const IMG2IMG_MODELS = {
  auto: { modelName: 'sc_soraimg_img2img_auto', points: 35, aspect: 'auto' },
  '1:1': { modelName: 'sc_soraimg_img2img_1x1', points: 35, aspect: '1:1' },
  '2:3': { modelName: 'sc_soraimg_img2img_2x3', points: 35, aspect: '2:3' },
  '3:2': { modelName: 'sc_soraimg_img2img_3x2', points: 35, aspect: '3:2' }
}

// user store
const userStore = useUserStore()

// overlay mask when generating images
const generatingMaskVisible = ref(false)
const generatingMaskTip = ref('图片生成中，请勿离开，预计1-2分钟...')

// 比例候选：根据模型给出（此处模型名固定，但比例提供更全，含 9:16）
const STORYBOARD_ASPECTS = [ '1:1', '3:2', '2:3','9:16','16:9']

// 将展示比例映射到后端模型可识别的比例（16:9->3:2，9:16->2:3，其余保持不变）
const normalizeAspectForModel = (aspect) => {
  if (aspect === '16:9') return '3:2'
  if (aspect === '9:16') return '2:3'
  return aspect
}

// 计算：根据“固定模型”提供的比例列表（未来如模型不同，可在此分支）
const storyboardRatioOptions = computed(() => {
  return STORYBOARD_ASPECTS.map(a => ({ value: a, label: a }))
})

// 计算：根据比率选择返回对应文生图、图生图模型
const selectedTextImageModel = computed(() => {
  const key = normalizeAspectForModel(storyboardRatio.value)
  return TEXT_IMAGE_MODELS[key] || TEXT_IMAGE_MODELS.auto
})
const selectedImg2ImgModel = computed(() => {
  const key = normalizeAspectForModel(storyboardRatio.value)
  return IMG2IMG_MODELS[key] || IMG2IMG_MODELS.auto
})

// 提交：生成分镜图（如果上传了参考图，则用图生图；否则用文生图）
const submitStoryboardGeneration = async () => {
  // 1) 参数校验
  if (!promptText.value.trim() && referenceImages.value.length === 0 && customStoryboardImages.value.length === 0) {
    ElMessage.warning('请先填写提示词或上传分镜/参考图')
    return
  }

  // 2) 判断任务类型
  const isImg2Img = referenceImages.value.length > 0
  const modelInfo = isImg2Img ? selectedImg2ImgModel.value : selectedTextImageModel.value
  const modelAspect = normalizeAspectForModel(storyboardRatio.value)

  // 3) 积分校验（演示場景）
  if ((userStore.userInfo?.points || 0) < modelInfo.points) {
    ElMessage.warning(`积分不足，需要 ${modelInfo.points} 积分`)
    return
  }

  // 4) 确认
  try {
    await ElMessageBox.confirm(
      `将消耗 ${modelInfo.points} 积分，是否继续？`,
      '生成确认',
      { type: 'warning' }
    )
  } catch { return }

  // 5) 组装请求体
  let imageUrl = ''
  try {
    if (isImg2Img) {
      generatingMaskVisible.value = true
      generatingMaskTip.value = '正在上传参考图...'

      const base64 = referenceImages.value[0]
      const blob = await (await fetch(base64)).blob()
      const file = new File([blob], 'reference.png', { type: blob.type || 'image/png' })
      const res = await uploadFileToOss(file, userStore.userInfo?.id)
      imageUrl = res.url
    }

    generatingMaskTip.value = '任务提交中...'
    const taskData = {
      modelName: modelInfo.modelName,
      prompt: promptText.value,
      taskType: isImg2Img ? 'image_to_image' : 'text_to_image',
      imageUrl: isImg2Img ? imageUrl : undefined,
      aspectRatio: modelAspect
    }
    const submitRes = await submitAITask(taskData)
    if (submitRes.code !== 200 || !submitRes.data) {
      generatingMaskVisible.value = false
      ElMessage.error(submitRes.message || '任务提交失败')
      return
    }

    const taskNo = submitRes.data.taskNo || submitRes.data.id
    ElMessage.success('任务提交成功，已开始生成...')

    generatingMaskTip.value = '图片生成中，请勿离开，预计1-2分钟...'
    await pollImageTask(taskNo, 90)
  } catch (e) {
    console.error(e)
    ElMessage.error('处理失败，请稍后重试')
    generatingMaskVisible.value = false
  }
}

// 轮询任务状态，每 20s 查询一次
const pollImageTask = async (taskNo, maxTimes = 90) => {
  let times = 0
  return new Promise((resolve) => {
    const timer = setInterval(async () => {
      times++
      try {
        const res = await getAITaskDetail(taskNo)
        if (res.code === 200 && res.data) {
          const status = res.data.status
          if (status === 'completed') {
            clearInterval(timer)
            generatingMaskVisible.value = false
            // 将生成的分镜图塞到 step2 网格，自动进入步骤二
            const url = res.data.resultUrl
            if (url) {
              storyboardImages.value = [url]
              currentStep.value = 2
              // 保留 Step 1 的提示词到 Step 2 的视频描述中
              if (promptText.value.trim()) {
                videoPrompt.value = promptText.value
              }
            }
            ElMessage.success('分镜图生成成功')
            // 任务完成后刷新用户积分信息
            userStore.fetchUserInfo?.()
            resolve(true)
          } else if (status === 'failed') {
            clearInterval(timer)
            generatingMaskVisible.value = false
            ElMessage.error(res.data.errorMessage || '分镜图生成失败')
            // 任务失败后刷新用户积分信息
            userStore.fetchUserInfo?.()
            resolve(false)
          }
        }
      } catch (err) {
        console.error('查询任务失败', err)
      }
      if (times >= maxTimes) {
        clearInterval(timer)
        generatingMaskVisible.value = false
        ElMessage.warning('生成超时，请稍后在任务列表查看进度')
        resolve(false)
      }
    }, 20000)
  })
}

// 方法
const handleModeSwitch = (modeKey) => {
  if (modeKey !== 'storyboard') {
    emit('switch-mode', modeKey)
  }
}

// 触发文件选择
const triggerFileInput = () => {
  if (fileInput.value) {
    fileInput.value.click()
  }
}

// 处理文件选择
const handleFileSelect = (event) => {
  const file = event.target.files[0]
  if (file) {
    processFile(file)
  }
}

// 处理拖拽上传
const handleDrop = (event) => {
  const file = event.dataTransfer.files[0]
  if (file) {
    processFile(file)
  }
}

// 处理文件
const processFile = (file) => {
  // 检查文件类型
  if (!file.type.startsWith('image/')) {
    ElMessage.error('请上传图片文件')
    return
  }
  
  // 检查文件大小 (10MB)
  if (file.size > 10 * 1024 * 1024) {
    ElMessage.error('图片大小不能超过10MB')
    return
  }
  
  // 读取并预览图片
  const reader = new FileReader()
  reader.onload = (e) => {
    uploadedImage.value = e.target.result
    // 用户上传图片后，自动切换到步骤2，并填充分镜图数组
    currentStep.value = 2
    storyboardImages.value = [e.target.result]
  }
  reader.readAsDataURL(file)
}

// 删除图片
const removeImage = () => {
  uploadedImage.value = null
  if (fileInput.value) {
    fileInput.value.value = ''
  }
  // 清空后回到步骤一
  currentStep.value = 1
  storyboardImages.value = []
}

// 参考图上传入口
const triggerReferenceFileInput = () => {
  if (referenceFileInput.value) {
    referenceFileInput.value.click()
  }
}

const handleReferenceFileSelect = (event) => {
  const file = event.target.files[0]
  if (file) showUploadWarning(file, processReferenceFile)
}

const handleReferenceDrop = (event) => {
  const file = event.dataTransfer.files[0]
  if (file) showUploadWarning(file, processReferenceFile)
}

const processReferenceFile = (file) => {
  if (!file.type.startsWith('image/')) {
    ElMessage.error('请上传图片文件')
    return
  }
  if (file.size > 10 * 1024 * 1024) {
    ElMessage.error('图片大小不能超过10MB')
    return
  }
  const reader = new FileReader()
  reader.onload = (e) => {
    referenceImages.value = [e.target.result]
  }
  reader.readAsDataURL(file)
}

const removeReferenceImage = (idx) => {
  referenceImages.value = []
}

// 自定义分镜图上传
const triggerCustomFileInput = () => {
  if (customFileInput.value) {
    customFileInput.value.click()
  }
}

const handleCustomFileSelect = (event) => {
  const file = event.target.files[0]
  if (file) {
    showUploadWarning(file, processCustomFile)
  }
}

const handleCustomDrop = (event) => {
  const file = event.dataTransfer.files[0]
  if (file) {
    showUploadWarning(file, processCustomFile)
  }
}

const processCustomFile = (file) => {
  if (!file.type.startsWith('image/')) {
    ElMessage.error('请上传图片文件')
    return
  }
  if (file.size > 10 * 1024 * 1024) {
    ElMessage.error('图片大小不能超过10MB')
    return
  }
  const reader = new FileReader()
  reader.onload = (e) => {
    customStoryboardImages.value = [e.target.result]
    // 自动切换到步骤二
    if (customStoryboardImages.value.length > 0) {
      currentStep.value = 2
      storyboardImages.value = [...customStoryboardImages.value]
      // 保留 Step 1 的提示词到 Step 2 的视频描述中
      if (promptText.value.trim()) {
        videoPrompt.value = promptText.value
      }
    }
  }
  reader.readAsDataURL(file)
}

const removeCustomImage = (idx) => {
  customStoryboardImages.value = []
  if (customStoryboardImages.value.length === 0) {
    currentStep.value = 1
    storyboardImages.value = []
    } else {
    storyboardImages.value = [...customStoryboardImages.value]
  }
}

// 一键优化提示词
const optimizePrompt = () => {
  // TODO: 实现提示词优化逻辑
  ElMessage.info('提示词优化功能开发中...')
}

// 显示上传警告
const showUploadWarning = async (file, callback) => {
  try {
    await ElMessageBox.confirm(
      '根据官方规定，禁止上传包含真人肖像的图片进行生成。请确认您的图片符合规定，否则可能导致处理失败或账户受限。',
      '上传内容合规确认',
      {
        confirmButtonText: '我已阅读并确认',
        cancelButtonText: '取消上传',
        type: 'warning',
        customClass: 'custom-messagebox'
      }
    )
    callback(file)
  } catch {
    ElMessage.info('已取消上传')
  }
}

// --- Step 1 Dropdown Handlers ---
const toggleStoryboardModelDropdown = () => {
  showStoryboardModelDropdown.value = !showStoryboardModelDropdown.value
}
const closeStoryboardModelDropdown = () => {
  showStoryboardModelDropdown.value = false
}
const selectStoryboardModel = (value) => {
  storyboardModel.value = value
  showStoryboardModelDropdown.value = false
}
const toggleStoryboardRatioDropdown = () => {
  showStoryboardRatioDropdown.value = !showStoryboardRatioDropdown.value
}
const closeStoryboardRatioDropdown = () => {
  showStoryboardRatioDropdown.value = false
}
const selectStoryboardRatio = (value) => {
  storyboardRatio.value = value
  showStoryboardRatioDropdown.value = false
}


// --- Step 2 Dropdown Handlers ---
// 下拉框控制方法
const toggleModelDropdown = () => {
  showModelDropdown.value = !showModelDropdown.value
  showRatioDropdown.value = false
  showDurationDropdown.value = false
}

const closeModelDropdown = () => {
  showModelDropdown.value = false
}

const selectModel = (value) => {
  videoModel.value = value
  showModelDropdown.value = false
}

const toggleRatioDropdown = () => {
  showRatioDropdown.value = !showRatioDropdown.value
  showModelDropdown.value = false
  showDurationDropdown.value = false
}

const closeRatioDropdown = () => {
  showRatioDropdown.value = false
}

const selectRatio = (value) => {
  videoRatio.value = value
  showRatioDropdown.value = false
}

const toggleDurationDropdown = () => {
  showDurationDropdown.value = !showDurationDropdown.value
  showModelDropdown.value = false
  showRatioDropdown.value = false
}

const closeDurationDropdown = () => {
  showDurationDropdown.value = false
}

const selectDuration = (value) => {
  duration.value = value
  showDurationDropdown.value = false
}

// v-click-outside directive
const vClickOutside = {
  mounted(el, binding) {
    el.clickOutsideEvent = (event) => {
      if (!(el === event.target || el.contains(event.target))) {
        binding.value()
      }
    }
    document.addEventListener('click', el.clickOutsideEvent)
  },
  unmounted(el) {
    document.removeEventListener('click', el.clickOutsideEvent)
  }
}

// 移除某一张分镜图（步骤二网格）
const removeStoryboardImage = (index) => {
  storyboardImages.value.splice(index, 1)
  if (storyboardImages.value.length === 0) {
    currentStep.value = 1
  }
}

// 生成分镜图
const handleGenerateStoryboard = () => {
  if (customStoryboardImages.value.length > 0) {
    currentStep.value = 2
    storyboardImages.value = [...customStoryboardImages.value]
  } else if (referenceImages.value.length > 0) {
    currentStep.value = 2
    storyboardImages.value = [...referenceImages.value]
  } else {
    ElMessage.warning('请先上传分镜图或参考图')
  }
}

// Step 2: 生成视频 - 将所有分镜图上传到OSS并提交视频生成任务
const submitVideoGeneration = async () => {
  if (storyboardImages.value.length === 0) {
    ElMessage.warning('请先上传分镜图')
    return
  }

  if (!videoPrompt.value.trim()) {
    ElMessage.warning('请输入视频描述')
    return
  }

  // 检查是否匹配到模型
  if (!matchedModel.value) {
    ElMessage.warning('未找到匹配的模型，请调整参数')
    return
  }

  // 检查积分
  const pointsCost = requiredPoints.value
  if ((userStore.userInfo?.points || 0) < pointsCost) {
    ElMessage.warning(`积分不足，需要 ${pointsCost} 积分`)
    return
  }

  // 确认提交
  try {
    await ElMessageBox.confirm(
      `此操作将消耗 ${pointsCost} 积分，是否继续生成视频？`,
      '确认生成',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        customClass: 'custom-messagebox'
      }
    )
  } catch {
    ElMessage.info('已取消生成')
    return
  }

  generatingMaskVisible.value = true
  generatingMaskTip.value = '正在上传分镜图...'

  try {
    // 上传所有分镜图到OSS
    const uploadedUrls = []
    for (const imageBase64 of storyboardImages.value) {
      const blob = await (await fetch(imageBase64)).blob()
      const file = new File([blob], `storyboard_${Date.now()}.png`, { type: blob.type || 'image/png' })
      const uploadRes = await uploadFileToOss(file, userStore.userInfo?.id)
      if (uploadRes && uploadRes.url) {
        uploadedUrls.push(uploadRes.url)
      }
    }

    if (uploadedUrls.length === 0) {
      generatingMaskVisible.value = false
      ElMessage.error('分镜图上传失败')
      return
    }

    generatingMaskTip.value = '任务提交中...'
    
    // 提交图生视频任务，使用匹配的模型
    const taskData = {
      modelName: matchedModel.value.modelName,
      prompt: videoPrompt.value,
      taskType: 'image_to_video',
      imageUrl: uploadedUrls[0] // 使用第一张分镜图作为主图
    }

    const submitRes = await submitAITask(taskData)
    if (submitRes.code !== 200 || !submitRes.data) {
      generatingMaskVisible.value = false
      ElMessage.error(submitRes.message || '任务提交失败')
      return
    }

    ElMessage.success('视频生成任务已提交')

    // 切换到图生视频模式并通知父组件刷新任务列表
    emit('switch-to-image-mode')
    emit('task-update')

    generatingMaskVisible.value = false
    
    // 显示提示：任务已在右侧列表中
    setTimeout(() => {
      ElMessage.info('视频正在生成中，请在右侧任务列表查看进度')
    }, 500)

  } catch (e) {
    console.error(e)
    generatingMaskVisible.value = false
    ElMessage.error('处理失败，请稍后重试')
  }
}

// 获取可用模型列表
const fetchModels = async () => {
  try {
    const response = await getAIModels({
      taskType: 'image_to_video',
      provider: 'suchuang',
      enabledOnly: true
    })
    if (response.code === 200) {
      availableModels.value = response.data || []
    }
  } catch (error) {
    console.error('获取模型列表失败:', error)
  }
}

// 组件挂载时获取模型列表
onMounted(() => {
  fetchModels()
})

// 监听做同款数据变化 - 分镜视频的做同款应该填充到 Step 2
watch(() => props.remakePrompt, (newPrompt) => {
  if (newPrompt) {
    // 填充到 Step 2 的视频描述
    videoPrompt.value = newPrompt
    console.log('分镜视频做同款：提示词已填充到 Step 2:', newPrompt)
  }
})

watch(() => props.remakeImageUrl, (newImageUrl) => {
  if (newImageUrl) {
    // 分镜视频的参考图填充到 storyboardImages，并切换到 Step 2
    storyboardImages.value = [newImageUrl]
    currentStep.value = 2
    console.log('分镜视频做同款：参考图已填充:', newImageUrl)
    
    // 如果两个数据都有，通知父组件完成填充
    if (props.remakePrompt && props.remakeImageUrl) {
      emit('remake-done')
    }
  }
})

// 监听 aspectRatio 参数变化
watch(() => props.remakeAspectRatio, (newAspectRatio) => {
  if (newAspectRatio) {
    // 将 aspectRatio 转换为 ratio 值
    if (newAspectRatio === '9:16') {
      ratio.value = 'portrait'
    } else if (newAspectRatio === '16:9') {
      ratio.value = 'landscape'
    }
    console.log('应用做同款尺寸:', newAspectRatio, '转换为:', ratio.value)
  }
})
</script>


<style scoped>
.create-sidebar {
  width: 480px;
  height: 100vh;
  background: rgba(21, 21, 21, 1);
  border-right: 1px solid rgba(255, 255, 255, 0.08);
  padding: 0;
  box-sizing: border-box;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  /* 隐藏滚动条 */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}

.create-sidebar::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Opera */
}

/* 模式切换按钮 */
.mode-switcher {
  display: flex;
  padding: 16px 24px 0 24px;
  gap: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  margin-bottom: 24px;
}

.mode-btn {
  flex: 1;
  padding: 12px 16px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px 8px 0 0;
  color: rgba(255, 255, 255, 0.6);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
}

.mode-btn:hover {
  background: rgba(255, 255, 255, 0.05);
  color: rgba(255, 255, 255, 0.8);
}

.mode-btn.active {
  background: rgba(26, 195, 255, 0.1);
  border-color: #1AC3FF;
  color: #1AC3FF;
}

.mode-btn.active::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0;
  right: 0;
  height: 2px;
  background: #1AC3FF;
}

.sidebar-content {
  display: flex;
  flex-direction: column;
  gap: 0px;
  padding: 0 0 0px 0;
  flex: 1;
  overflow-y: auto;
  /* 隐藏滚动条 */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}

.sidebar-content::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Opera */
}

.step-container {
  padding: 0 16px;
}

.step-1-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* 区块卡片 */
.section-card {
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 8px;
  padding: 12px;
}

.section-header {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 10px;
}

.section-title {
  font-size: 14px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.95);
}

.section-subtitle {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
}

/* 分隔线 */
.divider-line {
  position: relative;
  height: 1px;
  background: rgba(255, 255, 255, 0.08);
  margin: 4px 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.divider-text {
  position: absolute;
  background: rgba(21, 21, 21, 1);
  padding: 0 12px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.4);
}

.steps {
  display: flex;
  align-items: center;
  margin-bottom: 20px;
  font-size: 14px;
}

.steps span {
  color: rgba(255, 255, 255, 0.4);
}

.steps .active {
  color: #ffffff;
  font-weight: 500;
}

.steps .separator {
  margin: 0 8px;
  color: rgba(255, 255, 255, 0.4);
}

/* 自定义分镜图上传 */
.custom-storyboard-upload {
  margin-top: 8px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.upload-btn-single {
  width: 160px;
  height: 48px;
  border-radius: 8px;
  border: 1px dashed rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.02);
  color: rgba(255, 255, 255, 0.7);
  font-size: 14px;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.upload-btn-single:hover {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(26, 195, 255, 0.4);
  color: rgba(26, 195, 255, 0.9);
}

.btn-text {
  font-weight: 500;
}

.preview-thumbnail {
  position: relative;
  width: 80px;
  height: 48px;
  border-radius: 6px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.preview-thumbnail img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.plus-icon {
  font-size: 24px;
  line-height: 1;
  color: rgba(255, 255, 255, 0.6);
}

.image-number {
  position: absolute;
  left: 6px;
  bottom: 6px;
  background: rgba(0, 0, 0, 0.6);
  color: rgba(255, 255, 255, 0.9);
  padding: 2px 6px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 500;
}

/* 参考图上传区域 */
.reference-upload-area {
  margin-bottom: 12px
}

.reference-grid-single {
  display: flex;
  gap: 8px;
}

.upload-box {
  border: 1px dashed rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  padding: 20px;
  text-align: center;
  cursor: pointer;
  background-color: rgba(255, 255, 255, 0.02);
  height: 90px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: rgba(255, 255, 255, 0.6);
  transition: all 0.3s ease;
}

.upload-box:hover {
  background-color: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.3);
}

.upload-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}

.uploaded-image-preview {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.uploaded-image-preview img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 4px;
}

.remove-btn {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: #ff4757;
  color: white;
  border: none;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
}

.remove-btn:hover {
  background-color: #ff6b81;
  transform: scale(1.1);
}

.prompt-area {
  position: relative;
  margin-bottom: 16px;
}

.prompt-area textarea {
  width: 100%;
  height: 120px;
  background-color: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
  color: #ffffff;
  padding: 12px;
  resize: none;
  box-sizing: border-box;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.6;
  transition: all 0.3s ease;
}

.prompt-area textarea:hover {
  background-color: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.1);
}

.prompt-area textarea:focus {
  outline: none;
  background-color: rgba(255, 255, 255, 0.04);
  border-color: rgba(26, 195, 255, 0.4);
  box-shadow: 0 0 0 1px rgba(26, 195, 255, 0.2);
}

.prompt-area textarea::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Opera */
}

.prompt-area textarea::placeholder {
  color: rgba(255, 255, 255, 0.4);
}




.tip-note {
  margin-top: 12px;
  padding: 8px 12px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.65);
  background: rgba(255, 193, 7, 0.08);
  border: 1px solid rgba(255, 193, 7, 0.2);
  border-radius: 6px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  line-height: 1.5;
}

.tip-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  margin-top: 2px;
  color: rgba(255, 193, 7, 0.9);
}

.settings {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.setting-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 12px;
  font-size: 14px;
  background: rgba(255, 255, 255, 0.02);
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  transition: all 0.3s ease;
}

.setting-item:hover {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.1);
}

.setting-item .label {
  color: rgba(255, 255, 255, 0.9);
  font-weight: 400;
  min-width: 80px;
  flex-shrink: 0;
}

.setting-item .control {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #ffffff;
}

.setting-item .control-hd {
  display: flex;
  align-items: center;
  gap: 12px;
  color: rgba(255, 255, 255, 0.6);
}

.hd-note {
  font-size: 12px;
}

.toggle-switch {
  width: 36px;
  height: 20px;
  background-color: #555;
  border-radius: 10px;
  position: relative;
  cursor: pointer;
}

.toggle-handle {
  position: absolute;
  width: 16px;
  height: 16px;
  background-color: #fff;
  border-radius: 50%;
  top: 2px;
  left: 2px;
  transition: transform 0.2s;
}

.action-section {
  margin-top: 16px;
  padding: 0;
}

.generate-btn {
  width: 100%;
  background: linear-gradient(135deg, #1AC3FF 0%, #0F9CFF 100%);
  color: #ffffff;
  border: none;
  padding: 14px 24px;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  box-shadow: 0 2px 8px rgba(26, 195, 255, 0.2);
}

.generate-btn:hover {
  background: linear-gradient(135deg, #33DDE5 0%, #1AC3FF 100%);
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(26, 195, 255, 0.4);
}

.generate-btn .badge {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 255, 255, 0.3);
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
}

/* 生成遮罩层 */
.mask-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.mask-dialog {
  background: rgba(32, 32, 32, 0.95);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  padding: 24px 28px;
  width: 360px;
  text-align: center;
  box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}

.mask-text {
  color: #e8e8e8;
  font-size: 15px;
  margin-top: 10px;
}

.mask-sub {
  color: rgba(255,255,255,0.6);
  font-size: 12px;
  margin-top: 6px;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(255,255,255,0.2);
  border-top-color: #1AC3FF;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin: 0 auto;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.icon-placeholder {
  width: 16px;
  height: 16px;
  /* background-color: #777; remove this to not show a gray box */
  display: inline-block;
}

.reference-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}

.reference-tile {
  position: relative;
  height: 68px;
  width: 80px;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.2s ease;
}

.reference-tile.upload {
  border: 1px dashed rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.02);
}

.reference-tile.upload:hover {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.3);
}

.reference-tile.preview {
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.reference-tile.preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.remove-btn.small {
  top: 4px;
  right: 4px;
  width: 18px;
  height: 18px;
  font-size: 14px;
}
.storyboard-images-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  padding: 0 0 8px 0;
}

.storyboard-image-item {
  position: relative;
  background: rgba(255, 255, 255, 0.02);
  border: 1px dashed rgba(255, 255, 255, 0.15);
  border-radius: 6px;
  height: 92px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.storyboard-image-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.storyboard-image-item .image-label {
  position: absolute;
  left: 6px;
  bottom: 6px;
  font-size: 12px;
  color: rgba(255,255,255,0.85);
  background: rgba(0,0,0,0.25);
  padding: 0 6px;
  border-radius: 10px;
}

/* Step 2 Specific Styles */
.step-2-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.storyboard-section {
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 8px;
  padding: 12px;
}

.section-subtitle-small {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.7);
  margin-bottom: 12px;
  font-weight: 500;
}

.prompt-area.step2-prompt {
  margin-bottom: 0;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 8px;
  padding: 12px;
}

.prompt-label {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.7);
  margin-bottom: 8px;
  display: block;
  font-weight: 500;
}

.prompt-area.step2-prompt textarea {
  height: 100px;
  margin-bottom: 8px;
}

.prompt-area.step2-prompt .optimize-btn {
  position: static;
  width: 100%;
  justify-content: center;
}

.optimize-btn .icon {
  width: 14px;
  height: 14px;
}

.setting-row {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.02);
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  transition: all 0.3s ease;
}

.setting-row:hover {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.1);
}

.setting-label {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.9);
  font-weight: 400;
  min-width: 80px;
  flex-shrink: 0;
}

.setting-control {
  flex: 1;
  display: flex;
  justify-content: flex-end;
}

.custom-select {
  position: relative;
  width: 222px;
  cursor: pointer;
  user-select: none;
}

.select-display {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 12px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
  color: #ffffff;
  font-size: 14px;
  transition: all 0.2s ease;
}

.select-display:hover {
  background-color: rgba(0, 0, 0, 0.4);
  border-color: rgba(255, 255, 255, 0.2);
}

.model-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.select-text {
  flex: 1;
}

.dropdown-arrow {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  margin-left: 4px;
}

.select-dropdown {
  position: absolute;
  bottom: calc(100% + 4px); /* Changed to show above */
  left: 0;
  width: 222px;
  background: rgba(44, 50, 61, 1);
  border-radius: 6px;
  box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.3); /* Adjusted shadow */
  z-index: 1000;
  overflow: hidden;
}

.select-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  color: #ffffff;
  font-size: 14px;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

.select-option:hover {
  background: rgba(255, 255, 255, 0.1);
}

.select-option.active {
  background: rgba(26, 195, 255, 0.15);
}

.option-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.option-text {
  flex: 1;
}

.check-mark {
  color: #1AC3FF;
  font-size: 16px;
  font-weight: 600;
  margin-left: auto;
}

.quality-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.quality-left {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.switch {
  position: relative;
  display: inline-block;
  width: 44px;
  height: 24px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.2);
  transition: 0.3s;
  border-radius: 24px;
}

.slider:before {
  position: absolute;
  content: "";
  height: 18px;
  width: 18px;
  left: 3px;
  bottom: 3px;
  background-color: white;
  transition: 0.3s;
  border-radius: 50%;
}

input:checked + .slider {
  background-color: #1AC3FF;
}

input:checked + .slider:before {
  transform: translateX(20px);
}

:deep(.custom-messagebox) {
  background-color: #2b2b2b;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

:deep(.custom-messagebox .el-message-box__title) {
  color: #ffffff;
}

:deep(.custom-messagebox .el-message-box__content) {
  color: rgba(255, 255, 255, 0.8);
}

:deep(.custom-messagebox .el-button--primary) {
  background-color: #1AC3FF;
  border-color: #1AC3FF;
}
</style>