<template>
  <div class="app-container upload-page">
    <div class="page-header">
      <h2><i class="el-icon-upload2"></i> 资料上传</h2>
      <p class="page-desc">请先处理页面上方标记为“可上传”的资料；暂未开放的资料会提示需要先上传哪些内容。</p>
    </div>

    <el-card class="overview-card hero-card">
      <div class="overview-top">
        <div>
          <div class="overview-title">选择文件后即可上传</div>
          <div class="overview-desc">
            支持 CSV、XLS、XLSX 文件。页面已把可以直接上传的资料排在前面，暂不可上传的资料会在列表中给出原因。
          </div>
        </div>
        <div class="hero-summary">
          <div class="summary-item">
            <span>{{ readyUploadCount }}</span>
            <label>可上传</label>
          </div>
          <div class="summary-item">
            <span>{{ completedTableCount }}</span>
            <label>已完成</label>
          </div>
          <div class="summary-item">
            <span>{{ waitingUploadCount }}</span>
            <label>待准备</label>
          </div>
        </div>
      </div>
      <div class="overview-progress">
        <span>完成进度</span>
        <el-progress :percentage="progressPercent" :stroke-width="10" />
      </div>
    </el-card>

    <el-row :gutter="20" class="content-row">
      <el-col :xs="24" :lg="10">
        <el-card class="order-card">
          <template slot="header">
            <div class="card-header">
              <span>优先上传</span>
              <el-tag size="mini" type="success">{{ readyUploadCount }} 项可处理</el-tag>
            </div>
          </template>

          <div class="order-list">
            <div
              v-for="table in displayTables"
              :key="table.key"
              class="order-item"
              :class="{
                active: activeTableKey === table.key,
                uploaded: table.uploaded,
                locked: !canUpload(table) && !table.uploaded
              }"
              @click="selectTable(table.key)"
            >
              <div class="order-index">
                <i :class="getItemIcon(table)"></i>
              </div>
              <div class="order-main">
                <div class="order-title-row">
                  <div>
                    <div class="order-title">{{ getUploadName(table) }}</div>
                    <div class="order-table">{{ getUploadHint(table) }}</div>
                  </div>
                  <el-tag :type="getStatusType(table)" size="mini">
                    {{ getStatusText(table) }}
                  </el-tag>
                </div>
                <div class="order-footer">
                  <span>预览 {{ table.recordCount }} 条</span>
                  <span v-if="table.fileName">已选文件：{{ table.fileName }}</span>
                  <span v-else-if="!table.uploaded && !canUpload(table)">{{ getBlockedReason(table) }}</span>
                  <span v-else>待选择上传文件</span>
                </div>
              </div>
            </div>
          </div>
        </el-card>
      </el-col>

      <el-col :xs="24" :lg="14">
        <el-card class="detail-card">
          <template slot="header">
            <div class="card-header">
              <span>{{ getUploadName(selectedTable) }}</span>
              <el-tag size="mini" :type="getStatusType(selectedTable)">{{ getStatusText(selectedTable) }}</el-tag>
            </div>
          </template>

          <div class="detail-actions">
            <el-button
              type="primary"
              size="small"
              :disabled="selectedTable.uploaded || selectedTable.uploading || !isBackendSupported(selectedTable)"
              @click="triggerFileSelect(selectedTable)"
            >
              <i class="el-icon-folder-opened"></i> 选择文件
            </el-button>
            <el-button
              type="success"
              size="small"
              :disabled="selectedTable.uploaded || selectedTable.uploading || selectedTable.previewLoading || !canUpload(selectedTable) || hasMissingFields(selectedTable)"
              :loading="selectedTable.uploading"
              @click="submitTable(selectedTable)"
            >
              <i class="el-icon-upload"></i> 开始上传
            </el-button>
            <el-button
              size="small"
              :disabled="!selectedTable.fileName && !selectedTable.uploaded"
              @click="resetFromTable(selectedTable)"
            >
              <i class="el-icon-delete"></i> 重新选择
            </el-button>
          </div>

          <el-alert
            v-if="!canUpload(selectedTable) && !selectedTable.uploaded"
            :closable="false"
            type="warning"
            show-icon
            :title="getBlockedReason(selectedTable)"
            class="detail-alert"
          />

          <el-alert
            v-else
            :closable="false"
            type="info"
            show-icon
            class="detail-alert"
            :title="selectedTable.uploaded ? '这项资料已上传完成。' : '这项资料现在可以上传，请选择 CSV、XLS 或 XLSX 文件。'"
          />

          <div class="upload-dropzone" :class="{ disabled: selectedTable.uploaded || !isBackendSupported(selectedTable) }" @click="triggerFileSelect(selectedTable)">
            <i class="el-icon-upload"></i>
            <div>
              <strong>{{ selectedTable.fileName || '点击选择上传文件' }}</strong>
              <p>{{ selectedTable.fileName ? selectedTable.fileSize : (isBackendSupported(selectedTable) ? '支持 CSV、XLS、XLSX，选择后再点击开始上传' : '这项资料暂未接入上传') }}</p>
            </div>
          </div>

          <div class="selected-file" v-if="selectedTable.fileName">
            <i class="el-icon-document"></i>
            <span>{{ selectedTable.fileName }}</span>
            <span class="file-size">{{ selectedTable.fileSize }}</span>
          </div>

          <el-alert
            v-if="selectedTable.previewLoading"
            :closable="false"
            type="info"
            show-icon
            title="正在读取文件内容，请稍候"
            class="detail-alert"
          />

          <el-alert
            v-else-if="hasMissingFields(selectedTable)"
            :closable="false"
            type="error"
            show-icon
            class="detail-alert"
          >
            <div slot="title">文件缺少必要内容，暂不能上传</div>
            <div class="missing-fields">
              <el-tag
                v-for="field in selectedTable.missingFields"
                :key="field.name"
                size="mini"
                type="danger"
                effect="plain"
              >
                {{ field.label || field.name }}
              </el-tag>
            </div>
          </el-alert>

          <el-alert
            v-else-if="selectedTable.previewError"
            :closable="false"
            type="warning"
            show-icon
            :title="selectedTable.previewError"
            class="detail-alert"
          />

          <div class="section-title section-with-gap">
            <span>内容预览</span>
            <el-tag size="mini" :type="selectedTable.fileName ? 'success' : 'info'">{{ getPreviewCountText(selectedTable) }}</el-tag>
          </div>
          <el-table
            v-loading="selectedTable.previewLoading"
            :data="selectedTable.sampleRows"
            stripe
            size="small"
            class="data-table"
            :empty-text="selectedTable.fileName ? '文件中没有可预览的数据' : '选择文件后展示真实数据'"
          >
            <el-table-column
              v-for="column in selectedTable.previewColumns"
              :key="column.prop"
              :prop="column.prop"
              :label="column.label"
              :min-width="column.minWidth || 120"
              show-overflow-tooltip
            />
          </el-table>
        </el-card>
      </el-col>
    </el-row>

    <el-card class="snapshot-card">
      <template slot="header">
        <div class="card-header">
          <span>全部资料预览</span>
          <el-tag size="mini" type="info">可切换查看 {{ uploadTables.length }} 项</el-tag>
        </div>
      </template>

      <el-tabs v-model="activePreviewTab" @tab-click="handlePreviewTabChange">
        <el-tab-pane
          v-for="table in orderedTables"
          :key="table.key"
          :name="table.key"
        >
          <span slot="label">{{ getUploadName(table) }}</span>
          <div class="snapshot-meta">
            <el-tag size="mini" :type="getStatusType(table)">{{ getStatusText(table) }}</el-tag>
            <el-tag size="mini" effect="plain" :type="table.fileName ? 'success' : 'info'">{{ getPreviewCountText(table) }}</el-tag>
            <span class="snapshot-desc">{{ getUploadHint(table) }}</span>
          </div>
          <el-table
            v-loading="table.previewLoading"
            :data="table.sampleRows"
            stripe
            size="mini"
            :empty-text="table.fileName ? '文件中没有可预览的数据' : '选择文件后展示真实数据'"
          >
            <el-table-column
              v-for="column in table.previewColumns"
              :key="column.prop"
              :prop="column.prop"
              :label="column.label"
              :min-width="column.minWidth || 120"
              show-overflow-tooltip
            />
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <div class="hidden-inputs">
      <input
        v-for="table in orderedTables"
        :key="table.key"
        :ref="'fileInput-' + table.key"
        type="file"
        accept=".xlsx,.xls,.csv"
        @change="handleFileChange(table, $event)"
      >
    </div>
  </div>
</template>

<script>
import { previewPreparedData, uploadPreparedData } from '@/api/uploadData'

const UPLOAD_TABLES = [
  {
    key: 'warehouse',
    order: 1,
    name: '仓库表',
    tableName: 'warehouse',
    description: '仓库主数据，无外键依赖。',
    dependencies: [],
    recordCount: 12,
    fields: [
      { name: 'warehouse_code', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY', description: '仓库编码（主键）' },
      { name: 'warehouse_name', type: 'VARCHAR(100)', constraint: 'NOT NULL', description: '仓库名称' },
      { name: 'warehouse_type', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '仓库类型（普通仓 / 冷链仓 / 电商仓等）' },
      { name: 'warehouse_address', type: 'VARCHAR(200)', constraint: 'NOT NULL', description: '仓库地址' }
    ],
    previewColumns: [
      { prop: 'warehouse_code', label: '仓库编码', minWidth: 120 },
      { prop: 'warehouse_name', label: '仓库名称', minWidth: 160 },
      { prop: 'warehouse_type', label: '仓库类型', minWidth: 120 },
      { prop: 'warehouse_address', label: '仓库地址', minWidth: 220 }
    ],
    sampleRows: [
      { warehouse_code: 'WH-SH-01', warehouse_name: '上海中心仓', warehouse_type: '电商仓', warehouse_address: '上海市嘉定区叶城路 88 号' },
      { warehouse_code: 'WH-HZ-02', warehouse_name: '华中周转仓', warehouse_type: '普通仓', warehouse_address: '武汉市东西湖区高桥五路 26 号' },
      { warehouse_code: 'WH-GZ-03', warehouse_name: '广州冷链仓', warehouse_type: '冷链仓', warehouse_address: '广州市黄埔区开源大道 16 号' }
    ]
  },
  {
    key: 'supplier',
    order: 2,
    name: '供应商表',
    tableName: 'supplier',
    description: '供应商主数据，无外键依赖。',
    dependencies: [],
    recordCount: 18,
    fields: [
      { name: 'supplier_id', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY', description: '供应商编号（主键）' },
      { name: 'supplier_name', type: 'VARCHAR(100)', constraint: 'NOT NULL', description: '供应商名称' }
    ],
    previewColumns: [
      { prop: 'supplier_id', label: '供应商编号', minWidth: 140 },
      { prop: 'supplier_name', label: '供应商名称', minWidth: 220 }
    ],
    sampleRows: [
      { supplier_id: 'SUP-001', supplier_name: '华东包装材料有限公司' },
      { supplier_id: 'SUP-007', supplier_name: '宁波晨光辅料工厂' },
      { supplier_id: 'SUP-015', supplier_name: '青岛智造电子配件厂' }
    ]
  },
  {
    key: 'semi_finished_product',
    order: 3,
    name: '半成品表',
    tableName: 'semi_finished_product',
    description: '半成品基础档案，无外键依赖。',
    dependencies: [],
    recordCount: 26,
    fields: [
      { name: 'sku', type: 'VARCHAR(64)', constraint: 'PRIMARY KEY', description: '半成品 SKU（主键）' },
      { name: 'semi_name', type: 'VARCHAR(100)', constraint: 'NOT NULL', description: '半成品名称' },
      { name: 'price', type: 'DECIMAL(10,2)', constraint: 'NOT NULL', description: '半成品单价' }
    ],
    previewColumns: [
      { prop: 'sku', label: '半成品 SKU', minWidth: 160 },
      { prop: 'semi_name', label: '半成品名称', minWidth: 220 },
      { prop: 'price', label: '单价', minWidth: 100 }
    ],
    sampleRows: [
      { sku: 'SEMI-AX1001', semi_name: '主控板组件 A', price: '38.50' },
      { sku: 'SEMI-BX2040', semi_name: '电源模块 B', price: '21.00' },
      { sku: 'SEMI-CX3012', semi_name: '外壳组件 C', price: '12.80' }
    ]
  },
  {
    key: 'product',
    order: 4,
    name: '产品表',
    tableName: 'product',
    description: '成品主数据，无外键依赖。',
    dependencies: [],
    recordCount: 48,
    fields: [
      { name: 'sku', type: 'VARCHAR(64)', constraint: 'PRIMARY KEY', description: '产品 SKU（主键）' },
      { name: 'spu', type: 'VARCHAR(64)', constraint: 'NOT NULL', description: '标准产品单元 SPU' },
      { name: 'product_code', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '产品代码' },
      { name: 'product_name', type: 'VARCHAR(128)', constraint: 'NOT NULL', description: '产品名称' }
    ],
    previewColumns: [
      { prop: 'sku', label: 'SKU', minWidth: 160 },
      { prop: 'spu', label: 'SPU', minWidth: 120 },
      { prop: 'product_code', label: '产品代码', minWidth: 140 },
      { prop: 'product_name', label: '产品名称', minWidth: 220 }
    ],
    sampleRows: [
      { sku: 'SKU-P1001-BLK', spu: 'SPU-P1001', product_code: 'PD-1001', product_name: '智能水杯 黑色款' },
      { sku: 'SKU-P1001-WHT', spu: 'SPU-P1001', product_code: 'PD-1002', product_name: '智能水杯 白色款' },
      { sku: 'SKU-P2100-GRY', spu: 'SPU-P2100', product_code: 'PD-2100', product_name: '便携保温壶 灰色款' }
    ]
  },
  {
    key: 'product_structure',
    order: 5,
    name: '产品结构表',
    tableName: 'product_structure',
    description: '产品层级结构，自关联表，需先插入顶层节点。',
    dependencies: [],
    recordCount: 31,
    fields: [
      { name: 'level_no', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY', description: '当前层级编号（如 1、1-1、1-1-1）' },
      { name: 'parent_id', type: 'VARCHAR(32)', constraint: 'FOREIGN KEY', description: '父类 ID（关联本表）' },
      { name: 'parent_name', type: 'VARCHAR(100)', constraint: 'NOT NULL', description: '父类分类名称' },
      { name: 'category_id', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '分类 ID' }
    ],
    previewColumns: [
      { prop: 'level_no', label: '层级编号', minWidth: 120 },
      { prop: 'parent_id', label: '父级 ID', minWidth: 120 },
      { prop: 'parent_name', label: '父级名称', minWidth: 140 },
      { prop: 'category_id', label: '分类 ID', minWidth: 120 },
      { prop: 'category_name', label: '分类名称', minWidth: 160 }
    ],
    sampleRows: [
      { level_no: '1', parent_id: '-', parent_name: '根节点', category_id: 'CAT-ROOT', category_name: '产品目录' },
      { level_no: '1-1', parent_id: '1', parent_name: '产品目录', category_id: 'CAT-SMART', category_name: '智能杯具' },
      { level_no: '1-1-1', parent_id: '1-1', parent_name: '智能杯具', category_id: 'CAT-TRAVEL', category_name: '便携系列' }
    ]
  },
  {
    key: 'store',
    order: 6,
    name: '店铺表',
    tableName: 'store',
    description: '店铺主数据，无外键依赖。',
    dependencies: [],
    recordCount: 9,
    fields: [
      { name: 'store_code', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY', description: '店铺编码（主键）' },
      { name: 'store_name', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '店铺名称' },
      { name: 'dept_name', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '事业部名称' },
      { name: 'channel_name', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '渠道名称' }
    ],
    previewColumns: [
      { prop: 'store_code', label: '店铺编码', minWidth: 120 },
      { prop: 'store_name', label: '店铺名称', minWidth: 180 },
      { prop: 'dept_name', label: '事业部', minWidth: 120 },
      { prop: 'channel_name', label: '渠道', minWidth: 120 }
    ],
    sampleRows: [
      { store_code: 'ST-TM-01', store_name: '天猫旗舰店', dept_name: '电商事业部', channel_name: '天猫' },
      { store_code: 'ST-JD-01', store_name: '京东自营店', dept_name: '电商事业部', channel_name: '京东' },
      { store_code: 'ST-DY-01', store_name: '抖音直播店', dept_name: '新零售事业部', channel_name: '抖音' }
    ]
  },
  {
    key: 'structure_rule_setting',
    order: 7,
    name: '结构规则设置表',
    tableName: 'structure_rule_setting',
    description: '结构编码规则配置，无外键依赖。',
    dependencies: [],
    recordCount: 6,
    fields: [
      { name: 'rule_id', type: 'BIGINT', constraint: 'PRIMARY KEY AUTO_INCREMENT', description: '规则 ID（主键）' },
      { name: 'rule_type', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '规则对象：warehouse_location / product_structure' },
      { name: 'parent_field', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '父编码字段（如 warehouse_code、parent_id）' },
      { name: 'parent_length', type: 'INT', constraint: 'NOT NULL', description: '父编码占用位数' },
      { name: 'current_level', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '当前层级名称（L1/L2/L3）' }
    ],
    previewColumns: [
      { prop: 'rule_type', label: '规则对象', minWidth: 180 },
      { prop: 'parent_field', label: '父字段', minWidth: 140 },
      { prop: 'parent_length', label: '父编码长度', minWidth: 110 },
      { prop: 'current_level', label: '层级', minWidth: 100 },
      { prop: 'current_length', label: '当前长度', minWidth: 100 }
    ],
    sampleRows: [
      { rule_type: 'warehouse_location', parent_field: 'warehouse_code', parent_length: 8, current_level: 'L1', current_length: 4 },
      { rule_type: 'warehouse_location', parent_field: 'warehouse_code', parent_length: 8, current_level: 'L2', current_length: 2 },
      { rule_type: 'product_structure', parent_field: 'parent_id', parent_length: 6, current_level: 'L3', current_length: 3 }
    ]
  },
  {
    key: 'location',
    order: 8,
    name: '库位表',
    tableName: 'location',
    description: '库位主数据，依赖 warehouse。',
    dependencies: ['warehouse'],
    recordCount: 64,
    fields: [
      { name: 'location_code', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY', description: '库位编码（主键）' },
      { name: 'warehouse_code', type: 'VARCHAR(32)', constraint: 'FOREIGN KEY', description: '仓库编码（关联仓库表）' },
      { name: 'location_type', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '库位类型（常温 / 冷藏 / 拣选区等）' },
      { name: 'capacity_limit', type: 'INT', constraint: 'NOT NULL', description: '库位容量限制' }
    ],
    previewColumns: [
      { prop: 'location_code', label: '库位编码', minWidth: 140 },
      { prop: 'warehouse_code', label: '仓库编码', minWidth: 120 },
      { prop: 'location_type', label: '库位类型', minWidth: 120 },
      { prop: 'capacity_limit', label: '容量上限', minWidth: 100 }
    ],
    sampleRows: [
      { location_code: 'WH-SH-01-A01', warehouse_code: 'WH-SH-01', location_type: '拣选区', capacity_limit: 1200 },
      { location_code: 'WH-SH-01-B12', warehouse_code: 'WH-SH-01', location_type: '常温区', capacity_limit: 2400 },
      { location_code: 'WH-GZ-03-C02', warehouse_code: 'WH-GZ-03', location_type: '冷藏区', capacity_limit: 800 }
    ]
  },
  {
    key: 'bom_list',
    order: 9,
    name: 'BOM 清单表',
    tableName: 'bom_list',
    description: '成品与半成品映射关系，依赖 product 和 semi_finished_product。',
    dependencies: ['product', 'semi_finished_product'],
    recordCount: 86,
    fields: [
      { name: 'id', type: 'BIGINT', constraint: 'PRIMARY KEY', description: '主键 ID（自增）' },
      { name: 'finished_sku', type: 'VARCHAR(64)', constraint: 'FOREIGN KEY', description: '成品 SKU（关联产品表）' },
      { name: 'semi_sku', type: 'VARCHAR(64)', constraint: 'FOREIGN KEY', description: '半成品 SKU（关联半成品表）' },
      { name: 'quantity', type: 'INT', constraint: 'NOT NULL', description: '1 个成品所需该半成品的数量' }
    ],
    previewColumns: [
      { prop: 'finished_sku', label: '成品 SKU', minWidth: 160 },
      { prop: 'semi_sku', label: '半成品 SKU', minWidth: 160 },
      { prop: 'quantity', label: '用量', minWidth: 100 },
      { prop: 'remark', label: '说明', minWidth: 180 }
    ],
    sampleRows: [
      { finished_sku: 'SKU-P1001-BLK', semi_sku: 'SEMI-AX1001', quantity: 1, remark: '主控板组件' },
      { finished_sku: 'SKU-P1001-BLK', semi_sku: 'SEMI-BX2040', quantity: 1, remark: '电源模块' },
      { finished_sku: 'SKU-P2100-GRY', semi_sku: 'SEMI-CX3012', quantity: 2, remark: '外壳组件' }
    ]
  },
  {
    key: 'purchase_receipt',
    order: 10,
    name: '采购入库单表',
    tableName: 'purchase_receipt',
    description: '采购入库业务数据，依赖 product 和 supplier。',
    dependencies: ['product', 'supplier'],
    recordCount: 124,
    fields: [
      { name: 'receipt_id', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY', description: '单据编号（主键）' },
      { name: 'product_code', type: 'VARCHAR(32)', constraint: 'FOREIGN KEY', description: '产品代码（关联产品表）' },
      { name: 'supplier_id', type: 'VARCHAR(32)', constraint: 'FOREIGN KEY', description: '供应商编号（关联供应商表）' },
      { name: 'quantity', type: 'INT', constraint: 'NOT NULL', description: '采购入库数量' }
    ],
    previewColumns: [
      { prop: 'receipt_id', label: '入库单号', minWidth: 140 },
      { prop: 'product_code', label: '产品代码', minWidth: 120 },
      { prop: 'supplier_id', label: '供应商编号', minWidth: 120 },
      { prop: 'quantity', label: '入库数量', minWidth: 100 },
      { prop: 'receipt_date', label: '入库日期', minWidth: 120 }
    ],
    sampleRows: [
      { receipt_id: 'PR-20260401-001', product_code: 'PD-1001', supplier_id: 'SUP-001', quantity: 500, receipt_date: '2026-04-01' },
      { receipt_id: 'PR-20260403-008', product_code: 'PD-2100', supplier_id: 'SUP-007', quantity: 320, receipt_date: '2026-04-03' },
      { receipt_id: 'PR-20260408-016', product_code: 'PD-1002', supplier_id: 'SUP-015', quantity: 260, receipt_date: '2026-04-08' }
    ]
  },
  {
    key: 'order_main',
    order: 11,
    name: '订单表',
    tableName: 'order_main',
    description: '订单业务数据，依赖 product。',
    dependencies: ['product'],
    recordCount: 388,
    fields: [
      { name: 'order_id', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY', description: '订单编号（主键）' },
      { name: 'order_date', type: 'DATETIME', constraint: 'NOT NULL', description: '下单时间' },
      { name: 'product_code', type: 'VARCHAR(32)', constraint: 'FOREIGN KEY', description: '产品代码（关联产品表）' },
      { name: 'quantity', type: 'INT', constraint: 'NOT NULL', description: '数量' }
    ],
    previewColumns: [
      { prop: 'order_id', label: '订单编号', minWidth: 160 },
      { prop: 'order_date', label: '下单时间', minWidth: 160 },
      { prop: 'product_code', label: '产品代码', minWidth: 120 },
      { prop: 'quantity', label: '数量', minWidth: 90 },
      { prop: 'store_code', label: '店铺编码', minWidth: 120 }
    ],
    sampleRows: [
      { order_id: 'SO-20260410-0001', order_date: '2026-04-10 09:15:00', product_code: 'PD-1001', quantity: 2, store_code: 'ST-TM-01' },
      { order_id: 'SO-20260410-0008', order_date: '2026-04-10 10:48:00', product_code: 'PD-1002', quantity: 1, store_code: 'ST-JD-01' },
      { order_id: 'SO-20260410-0013', order_date: '2026-04-10 11:26:00', product_code: 'PD-2100', quantity: 3, store_code: 'ST-DY-01' }
    ]
  },
  {
    key: 'assembly_record',
    order: 12,
    name: '组装记录表',
    tableName: 'assembly_record',
    description: '组装业务记录，依赖 product。',
    dependencies: ['product'],
    recordCount: 53,
    fields: [
      { name: 'id', type: 'BIGINT', constraint: 'PRIMARY KEY', description: '主键 ID（自增）' },
      { name: 'product_code', type: 'VARCHAR(50)', constraint: 'FOREIGN KEY', description: '产品代码（关联产品表）' },
      { name: 'assembly_date', type: 'DATE', constraint: 'NOT NULL', description: '组装日期' },
      { name: 'quantity', type: 'INT', constraint: 'NOT NULL', description: '组装数量' }
    ],
    previewColumns: [
      { prop: 'id', label: '记录 ID', minWidth: 100 },
      { prop: 'product_code', label: '产品代码', minWidth: 120 },
      { prop: 'assembly_date', label: '组装日期', minWidth: 120 },
      { prop: 'quantity', label: '组装数量', minWidth: 100 },
      { prop: 'operator', label: '操作人', minWidth: 120 }
    ],
    sampleRows: [
      { id: 9001, product_code: 'PD-1001', assembly_date: '2026-04-09', quantity: 180, operator: '张磊' },
      { id: 9008, product_code: 'PD-1002', assembly_date: '2026-04-10', quantity: 120, operator: '陈辰' },
      { id: 9015, product_code: 'PD-2100', assembly_date: '2026-04-11', quantity: 96, operator: '王瑶' }
    ]
  },
  {
    key: 'outbound_order',
    order: 13,
    name: '出库单表',
    tableName: 'outbound_order',
    description: '出库业务数据，依赖 location 和 product。',
    dependencies: ['location', 'product'],
    recordCount: 117,
    fields: [
      { name: 'order_no', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY', description: '出库单据编号（主键）' },
      { name: 'location_code', type: 'VARCHAR(32)', constraint: 'FOREIGN KEY', description: '库位编码（关联库位表）' },
      { name: 'sku', type: 'VARCHAR(64)', constraint: 'FOREIGN KEY', description: '产品 SKU（关联产品表）' },
      { name: 'outbound_date', type: 'DATE', constraint: 'NOT NULL', description: '出库日期' }
    ],
    previewColumns: [
      { prop: 'order_no', label: '出库单号', minWidth: 150 },
      { prop: 'location_code', label: '库位编码', minWidth: 140 },
      { prop: 'sku', label: 'SKU', minWidth: 160 },
      { prop: 'outbound_date', label: '出库日期', minWidth: 120 },
      { prop: 'quantity', label: '数量', minWidth: 90 }
    ],
    sampleRows: [
      { order_no: 'OB-20260412-001', location_code: 'WH-SH-01-A01', sku: 'SKU-P1001-BLK', outbound_date: '2026-04-12', quantity: 42 },
      { order_no: 'OB-20260412-003', location_code: 'WH-SH-01-B12', sku: 'SKU-P1001-WHT', outbound_date: '2026-04-12', quantity: 31 },
      { order_no: 'OB-20260413-009', location_code: 'WH-GZ-03-C02', sku: 'SKU-P2100-GRY', outbound_date: '2026-04-13', quantity: 18 }
    ]
  },
  {
    key: 'inventory_detail',
    order: 14,
    name: '库存明细表',
    tableName: 'inventory_detail',
    description: '库存明细数据，依赖 location 和 product。',
    dependencies: ['location', 'product'],
    recordCount: 142,
    fields: [
      { name: 'location_code', type: 'VARCHAR(32)', constraint: 'PRIMARY KEY, FOREIGN KEY', description: '库位编码（关联库位表）' },
      { name: 'sku', type: 'VARCHAR(64)', constraint: 'PRIMARY KEY, FOREIGN KEY', description: '产品 SKU（关联产品表）' },
      { name: 'stock_quantity', type: 'INT', constraint: 'NOT NULL DEFAULT 0', description: '可用库存数量' },
      { name: 'lock_quantity', type: 'INT', constraint: 'NOT NULL DEFAULT 0', description: '锁定库存数量' }
    ],
    previewColumns: [
      { prop: 'location_code', label: '库位编码', minWidth: 140 },
      { prop: 'sku', label: 'SKU', minWidth: 160 },
      { prop: 'stock_quantity', label: '可用库存', minWidth: 100 },
      { prop: 'lock_quantity', label: '锁定库存', minWidth: 100 }
    ],
    sampleRows: [
      { location_code: 'WH-SH-01-A01', sku: 'SKU-P1001-BLK', stock_quantity: 860, lock_quantity: 28 },
      { location_code: 'WH-SH-01-B12', sku: 'SKU-P1001-WHT', stock_quantity: 640, lock_quantity: 16 },
      { location_code: 'WH-GZ-03-C02', sku: 'SKU-P2100-GRY', stock_quantity: 218, lock_quantity: 12 }
    ]
  },
  {
    key: 'metrics',
    order: 15,
    name: '指标表',
    tableName: 'metrics',
    description: '业务指标聚合结果，SQL 与设计文档未定义外键约束，可单独上传。',
    dependencies: [],
    recordCount: 48,
    fields: [
      { name: 'metrics_id', type: 'BIGINT', constraint: 'PRIMARY KEY AUTO_INCREMENT', description: '指标 ID（主键自增）' },
      { name: 'metrics_type', type: 'VARCHAR(32)', constraint: 'NOT NULL', description: '指标类型：inventory / supplier / store / order' },
      { name: 'biz_code', type: 'VARCHAR(64)', constraint: 'NOT NULL', description: '业务编码：仓库编码 / 供应商 ID / 店铺编码 / 订单编号' },
      { name: 'stat_start_date', type: 'DATE', constraint: 'NOT NULL', description: '统计开始日期' },
      { name: 'stat_end_date', type: 'DATE', constraint: 'NOT NULL', description: '统计结束日期' }
    ],
    previewColumns: [
      { prop: 'metrics_type', label: '指标类型', minWidth: 120 },
      { prop: 'biz_code', label: '业务编码', minWidth: 160 },
      { prop: 'stat_start_date', label: '开始日期', minWidth: 120 },
      { prop: 'stat_end_date', label: '结束日期', minWidth: 120 },
      { prop: 'metric_value', label: '指标值', minWidth: 120 }
    ],
    sampleRows: [
      { metrics_type: 'inventory', biz_code: 'WH-SH-01', stat_start_date: '2026-04-01', stat_end_date: '2026-04-15', metric_value: '92.4' },
      { metrics_type: 'supplier', biz_code: 'SUP-001', stat_start_date: '2026-04-01', stat_end_date: '2026-04-15', metric_value: '98.1' },
      { metrics_type: 'store', biz_code: 'ST-TM-01', stat_start_date: '2026-04-01', stat_end_date: '2026-04-15', metric_value: '87.6' }
    ]
  }
]

const UPLOAD_NAMES = {
  warehouse: '仓库资料',
  supplier: '供应商资料',
  semi_finished_product: '半成品资料',
  product: '产品资料',
  product_structure: '产品分类资料',
  store: '店铺资料',
  structure_rule_setting: '编码规则资料',
  location: '库位资料',
  bom_list: '组合清单资料',
  purchase_receipt: '采购入库资料',
  order_main: '订单资料',
  assembly_record: '组装记录资料',
  outbound_order: '出库资料',
  inventory_detail: '库存资料',
  metrics: '经营指标资料'
}

const BACKEND_UPLOAD_KEYS = [
  'supplier',
  'semi_finished_product',
  'product',
  'bom_list',
  'purchase_receipt',
  'order_main',
  'assembly_record',
  'store'
]

function createUploadTables() {
  return JSON.parse(JSON.stringify(UPLOAD_TABLES)).map(item => ({
    ...item,
    defaultPreviewColumns: item.previewColumns,
    defaultSampleRows: item.sampleRows,
    recordCount: 0,
    sampleRows: [],
    uploaded: false,
    fileName: '',
    fileSize: '',
    rawFile: null,
    uploading: false,
    previewLoading: false,
    previewError: '',
    missingFields: [],
    updatedAt: ''
  }))
}

export default {
  name: 'UploadIndex',
  data() {
    return {
      uploadTables: createUploadTables(),
      activeTableKey: 'supplier',
      activePreviewTab: 'supplier'
    }
  },
  computed: {
    orderedTables() {
      return this.uploadTables.slice().sort((a, b) => a.order - b.order)
    },
    selectedTable() {
      return this.uploadTables.find(item => item.key === this.activeTableKey) || this.uploadTables[0]
    },
    completedTableCount() {
      return this.uploadTables.filter(item => item.uploaded).length
    },
    progressPercent() {
      return Math.round((this.completedTableCount / this.uploadTables.length) * 100)
    },
    readyUploadCount() {
      return this.uploadTables.filter(item => !item.uploaded && this.canUpload(item)).length
    },
    waitingUploadCount() {
      return this.uploadTables.filter(item => !item.uploaded && !this.canUpload(item)).length
    },
    displayTables() {
      return this.orderedTables.slice().sort((a, b) => {
        const aRank = this.getDisplayRank(a)
        const bRank = this.getDisplayRank(b)

        if (aRank !== bRank) {
          return aRank - bRank
        }

        return a.order - b.order
      })
    }
  },
  methods: {
    selectTable(key) {
      this.activeTableKey = key
      this.activePreviewTab = key
    },
    handlePreviewTabChange(tab) {
      this.activeTableKey = tab.name
    },
    getTableByKey(key) {
      return this.uploadTables.find(item => item.key === key)
    },
    getBlockedDependencies(table) {
      return table.dependencies
        .map(key => this.getTableByKey(key))
        .filter(item => item && !item.uploaded)
    },
    getDisplayRank(table) {
      if (!table.uploaded && this.canUpload(table)) {
        return 0
      }

      if (!table.uploaded && this.isBackendSupported(table)) {
        return 1
      }

      return table.uploaded ? 2 : 3
    },
    isBackendSupported(table) {
      return BACKEND_UPLOAD_KEYS.includes(table.key)
    },
    getUploadName(table) {
      return UPLOAD_NAMES[table.key] || table.name.replace(/表$/, '资料')
    },
    getUploadHint(table) {
      if (table.uploaded) {
        return table.updatedAt || '已完成'
      }

      if (!this.isBackendSupported(table)) {
        return '资料文件暂未整理完成，暂不支持上传'
      }

      if (this.canUpload(table)) {
        return '现在可以选择文件上传'
      }

      return this.getBlockedReason(table)
    },
    getItemIcon(table) {
      if (table.uploaded) {
        return 'el-icon-check'
      }

      if (!this.isBackendSupported(table)) {
        return 'el-icon-document'
      }

      if (this.canUpload(table)) {
        return 'el-icon-upload2'
      }

      return 'el-icon-lock'
    },
    getDependentKeys(table) {
      const dependentKeys = new Set([table.key])
      let changed = true

      while (changed) {
        changed = false
        this.uploadTables.forEach(item => {
          if (
            !dependentKeys.has(item.key) &&
            item.dependencies.some(dependency => dependentKeys.has(dependency))
          ) {
            dependentKeys.add(item.key)
            changed = true
          }
        })
      }

      return dependentKeys
    },
    canUpload(table) {
      return this.isBackendSupported(table) && this.getBlockedDependencies(table).length === 0
    },
    getBlockedReason(table) {
      if (!this.isBackendSupported(table)) {
        return '这项资料暂未接入上传'
      }

      const blocked = this.getBlockedDependencies(table)

      if (!blocked.length) {
        return '现在可以上传'
      }

      return `请先上传：${blocked.map(item => this.getUploadName(item)).join('、')}`
    },
    getStatusType(table) {
      if (table.uploaded) {
        return 'success'
      }

      if (this.hasMissingFields(table)) {
        return 'danger'
      }

      return this.canUpload(table) ? 'warning' : 'info'
    },
    getStatusText(table) {
      if (table.uploaded) {
        return '已上传'
      }

      if (!this.isBackendSupported(table)) {
        return '暂未接入'
      }

      if (table.uploading) {
        return '上传中'
      }

      if (table.previewLoading) {
        return '读取中'
      }

      if (this.hasMissingFields(table)) {
        return '需调整'
      }

      if (table.fileName && this.canUpload(table)) {
        return '待提交'
      }

      return this.canUpload(table) ? '可上传' : '待准备'
    },
    triggerFileSelect(table) {
      if (table.uploaded) {
        return
      }

      if (!this.isBackendSupported(table)) {
        this.$message.warning(this.getBlockedReason(table))
        return
      }

      if (!this.canUpload(table) && !table.uploaded) {
        this.$message.warning(this.getBlockedReason(table))
        return
      }

      const inputRef = this.$refs[`fileInput-${table.key}`]
      const input = Array.isArray(inputRef) ? inputRef[0] : inputRef

      if (input) {
        input.click()
      }
    },
    async handleFileChange(table, event) {
      const file = event.target.files && event.target.files[0]
      if (!file) {
        return
      }

      const isAllowedFile = /\.(csv|xls|xlsx)$/i.test(file.name)
      if (!isAllowedFile) {
        this.$message.warning('仅支持 CSV、XLS、XLSX 格式文件')
        event.target.value = ''
        return
      }

      table.fileName = file.name
      table.fileSize = this.formatFileSize(file.size)
      table.rawFile = file
      table.updatedAt = '已选择文件，正在读取内容'
      table.previewLoading = true
      table.previewError = ''
      table.missingFields = []
      table.sampleRows = []
      table.recordCount = 0

      event.target.value = ''

      try {
        const response = await previewPreparedData(table.key, file)
        const data = response.data || {}
        table.previewColumns = data.columns && data.columns.length ? data.columns : table.defaultPreviewColumns
        table.sampleRows = data.sampleRows || []
        table.recordCount = data.totalRows || 0
        table.missingFields = data.missingFields || []
        table.updatedAt = this.hasMissingFields(table) ? '文件内容需要调整' : '已选择文件，待提交'

        if (this.hasMissingFields(table)) {
          this.$message.warning(`${this.getUploadName(table)}缺少必要内容：${this.formatMissingFields(table)}`)
        }
      } catch (error) {
        table.previewError = error && error.message ? error.message : '文件内容读取失败，请检查文件后重新选择'
        table.updatedAt = '文件内容读取失败'
        table.rawFile = null
      } finally {
        table.previewLoading = false
      }
    },
    async submitTable(table) {
      if (!this.isBackendSupported(table)) {
        this.$message.warning(this.getBlockedReason(table))
        return
      }

      if (!this.canUpload(table) && !table.uploaded) {
        this.$message.warning(this.getBlockedReason(table))
        return
      }

      if (!table.rawFile) {
        this.$message.warning(`请先为${this.getUploadName(table)}选择上传文件`)
        return
      }

      if (this.hasMissingFields(table)) {
        this.$message.warning(`文件缺少必要内容：${this.formatMissingFields(table)}`)
        return
      }

      table.uploading = true
      try {
        const response = await uploadPreparedData(table.key, table.rawFile)
        table.uploaded = true
        table.updatedAt = `${this.getCurrentTime()} 已上传`
        table.recordCount = (response.data && response.data.totalRows) || table.recordCount
        this.$message.success((response.data && response.data.message) || `${this.getUploadName(table)}上传成功`)

        const nextTable = this.displayTables.find(item => !item.uploaded && this.canUpload(item))
        if (nextTable) {
          this.selectTable(nextTable.key)
        }
      } finally {
        table.uploading = false
      }
    },
    resetFromTable(table) {
      const dependentKeys = this.getDependentKeys(table)

      this.uploadTables.forEach(item => {
        if (dependentKeys.has(item.key)) {
          item.uploaded = false
          item.fileName = ''
          item.fileSize = ''
          item.rawFile = null
          item.uploading = false
          item.previewLoading = false
          item.previewError = ''
          item.missingFields = []
          item.sampleRows = []
          item.recordCount = 0
          item.previewColumns = item.defaultPreviewColumns
          item.updatedAt = ''
        }
      })

      this.selectTable(table.key)
      this.$message.info(`已重新打开 ${this.getUploadName(table)} 的上传`)
    },
    hasMissingFields(table) {
      return table && table.missingFields && table.missingFields.length > 0
    },
    formatMissingFields(table) {
      if (!this.hasMissingFields(table)) {
        return ''
      }
      return table.missingFields.map(field => field.label || field.name).join('、')
    },
    getPreviewCountText(table) {
      if (table.previewLoading) {
        return '读取中'
      }
      return table.fileName ? `${table.recordCount || 0} 条真实数据` : '待选择文件'
    },
    formatFileSize(size) {
      if (!size) {
        return '0 B'
      }

      if (size < 1024) {
        return `${size} B`
      }

      if (size < 1024 * 1024) {
        return `${(size / 1024).toFixed(1)} KB`
      }

      return `${(size / (1024 * 1024)).toFixed(1)} MB`
    },
    getCurrentTime() {
      const now = new Date()
      const year = now.getFullYear()
      const month = `${now.getMonth() + 1}`.padStart(2, '0')
      const day = `${now.getDate()}`.padStart(2, '0')
      const hour = `${now.getHours()}`.padStart(2, '0')
      const minute = `${now.getMinutes()}`.padStart(2, '0')

      return `${year}-${month}-${day} ${hour}:${minute}`
    }
  }
}
</script>

<style scoped lang="scss">
.upload-page {
  background: #f5f7fb;
}

.page-header {
  margin-bottom: 20px;

  h2 {
    margin: 0 0 8px;
    font-size: 24px;
    font-weight: 600;
    color: #303133;

    i {
      margin-right: 8px;
      color: #409eff;
    }
  }

  .page-desc {
    margin: 0;
    color: #606266;
    line-height: 1.6;
  }
}

.content-row {
  margin-bottom: 20px;
}

.overview-card,
.order-card,
.detail-card,
.snapshot-card {
  border: none;
}

.overview-card {
  margin-bottom: 20px;
}

.hero-card {
  background: linear-gradient(135deg, #ffffff 0%, #f3f8ff 100%);
}

.overview-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  margin-bottom: 18px;
}

.overview-title {
  font-size: 20px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 8px;
}

.overview-desc {
  color: #606266;
  line-height: 1.7;
}

.hero-summary {
  display: flex;
  gap: 12px;
  flex-shrink: 0;
}

.summary-item {
  min-width: 86px;
  padding: 12px 14px;
  border: 1px solid #dcecff;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.82);
  text-align: center;

  span {
    display: block;
    font-size: 24px;
    font-weight: 700;
    line-height: 1.2;
    color: #2563eb;
  }

  label {
    display: block;
    margin-top: 4px;
    color: #606266;
    font-size: 12px;
  }
}

.overview-progress {
  display: flex;
  align-items: center;
  gap: 16px;

  span {
    flex-shrink: 0;
    color: #606266;
  }
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-weight: 600;
}

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

.order-item {
  display: flex;
  gap: 14px;
  padding: 16px;
  border: 1px solid #ebeef5;
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  transition: all 0.2s ease;

  &:hover {
    border-color: #c6e2ff;
    box-shadow: 0 8px 18px rgba(64, 158, 255, 0.08);
  }

  &.active {
    border-color: #409eff;
    background: #f5faff;
  }

  &.uploaded {
    border-color: #d9f2d0;
    background: #f6ffed;
  }

  &.locked {
    background: #fafafa;
  }
}

.order-index {
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: #ecf5ff;
  color: #409eff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  flex-shrink: 0;
}

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

.order-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}

.order-title {
  font-size: 15px;
  font-weight: 600;
  color: #303133;
}

.order-table {
  margin-top: 2px;
  color: #909399;
  font-size: 12px;
  line-height: 1.5;
}

.order-desc {
  color: #606266;
  line-height: 1.6;
  margin-bottom: 10px;
}

.order-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.order-footer {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  color: #909399;
  font-size: 12px;
}

.detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
}

.detail-alert {
  margin-bottom: 16px;
}

.missing-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.upload-dropzone {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 24px;
  border: 1px dashed #9dccff;
  border-radius: 8px;
  background: #f7fbff;
  color: #409eff;
  cursor: pointer;
  margin-bottom: 16px;
  transition: all 0.2s ease;

  &:hover {
    border-color: #409eff;
    background: #eef7ff;
  }

  &.disabled {
    cursor: not-allowed;
    color: #909399;
    background: #f7f7f7;
    border-color: #dcdfe6;
  }

  > i {
    font-size: 34px;
  }

  strong {
    display: block;
    color: #303133;
    font-size: 16px;
    margin-bottom: 6px;
  }

  p {
    margin: 0;
    color: #909399;
    line-height: 1.5;
  }
}

.selected-file {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 10px;
  background: #f4f9ff;
  color: #409eff;
  margin-bottom: 16px;

  .file-size {
    color: #909399;
  }
}

.section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  font-size: 14px;
  font-weight: 600;
  color: #303133;
}

.section-with-gap {
  margin-top: 18px;
}

.data-table {
  width: 100%;
}

.snapshot-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.snapshot-desc {
  color: #606266;
  font-size: 13px;
}

.hidden-inputs {
  display: none;
}

@media (max-width: 1200px) {
  .overview-top {
    flex-direction: column;
    align-items: flex-start;
  }

  .hero-summary {
    width: 100%;
  }

  .summary-item {
    flex: 1;
  }
}

@media (max-width: 768px) {
  .order-title-row,
  .card-header {
    flex-direction: column;
    align-items: flex-start;
  }

  .overview-progress {
    flex-direction: column;
    align-items: flex-start;
  }

  .hero-summary {
    flex-direction: column;
  }

  .upload-dropzone {
    align-items: flex-start;
    padding: 18px;
  }
}
</style>
