<template>
    <div class="keywords-container">
      <transition name="el-zoom-in-top" appear>
        <div class="page-header">
          <div class="header-left">
            <h2 class="page-title">{{ $t('crawlerKeywords.pageTitle') }}</h2>
            <p class="page-desc">
              <i class="el-icon-info"></i> {{ $t('crawlerKeywords.pageDesc') }}
            </p>
          </div>
          <div class="header-actions">
           
            <!-- <el-button 
              type="primary" 
              icon="el-icon-video-play" 
              @click="handleStartCrawl" 
              :loading="crawlLoading" 
              class="glow-button" 
              round
            >
              {{ $t('crawlerKeywords.startCrawl') }}
            </el-button> -->
          </div>
        </div>
      </transition>
  
      <div class="add-section shadow-hover">
        <el-input
          v-model="newKeyword"
          :placeholder="$t('crawlerKeywords.inputPlaceholder')"
          class="add-input-custom"
          prefix-icon="el-icon-collection-tag"
          clearable
          @keyup.enter.native="handleAdd"
        />
        <el-button 
          type="primary" 
          icon="el-icon-plus" 
          @click="handleAdd" 
          :loading="addLoading" 
          class="add-btn"
        >
          {{ $t('crawlerKeywords.addKeyword') }}
        </el-button>
      </div>
  
      <el-card shadow="never" class="table-card animated-card">
        <div class="table-toolbar">
          <el-input
            v-model="searchText"
            :placeholder="$t('crawlerKeywords.searchPlaceholder')"
            prefix-icon="el-icon-search"
            clearable
            class="search-input"
            @input="handleSearch"
          />
          <el-button style="margin-left: 20px;"
            type="primary"
            icon="el-icon-search"
            @click="handleSearchNow"
          >
            {{ $t('crawlerKeywords.searchBtn') }}
          </el-button>
        </div>
  
        <el-table 
          :data="list" 
          v-loading="loading" 
          border 
          stripe
          highlight-current-row
          header-row-class-name="custom-header" 
          style="width: 100%" 
          class="modern-table"
        >
          <el-table-column prop="keyword" :label="$t('crawlerKeywords.colKeyword')" min-width="180">
            <template slot-scope="scope">
              <transition name="fade-slide" mode="out-in">
                <span :key="'t'+scope.row.id" v-if="editingId !== scope.row.id" class="keyword-text">
                  {{ scope.row.keyword }}
                </span>
                <el-input 
                  :key="'e'+scope.row.id" 
                  v-else 
                  v-model="editForm.keyword" 
                  size="small" 
                  v-focus
                  class="edit-input"
                />
              </transition>
            </template>
          </el-table-column>
  
          <el-table-column prop="category" :label="$t('crawlerKeywords.colCategory')" width="150">
            <template slot-scope="scope">
              <transition name="fade-slide" mode="out-in">
                <div :key="editingId === scope.row.id">
                  <el-tag 
                    v-if="editingId !== scope.row.id" 
                    :type="scope.row.category ? 'success' : 'info'" 
                    size="small" 
                    effect="light"
                  >
                    {{ scope.row.category || 'Default' }}
                  </el-tag>
                  <el-input v-else v-model="editForm.category" size="small" />
                </div>
              </transition>
            </template>
          </el-table-column>
  
          <el-table-column prop="state" :label="$t('crawlerKeywords.colStatus')" width="140" align="center">
            <template slot-scope="scope">
              <div class="status-container">
                <span :class="['status-dot', 'pulse', 'status-' + scope.row.state]"></span>
                <span :class="['status-label', 'text-' + scope.row.state]">
                  {{ getStateText(scope.row.state) }}
                </span>
              </div>
            </template>
          </el-table-column>
  
          <el-table-column prop="expert_count" :label="$t('crawlerKeywords.colExpertCount')" width="120" align="center">
            <template slot-scope="scope">
              <span class="count-badge">{{ scope.row.expert_count }}</span>
            </template>
          </el-table-column>
  
          <el-table-column prop="last_crawl_time" :label="$t('crawlerKeywords.colLastCrawl')" width="180" />
  
          <el-table-column :label="$t('crawlerKeywords.colAction')" width="160" align="center" fixed="right">
            <template slot-scope="scope">
              <div class="action-wrapper">
                <template v-if="editingId === scope.row.id">
                  <el-button type="text" icon="el-icon-circle-check" class="save-btn" @click="handleSaveEdit(scope.row)">
                    {{ $t('crawlerKeywords.save') }}
                  </el-button>
                  <el-button type="text" icon="el-icon-circle-close" class="cancel-btn" @click="editingId = null">
                    {{ $t('crawlerKeywords.cancel') }}
                  </el-button>
                </template>
                <template v-else>
                  <el-tooltip :content="$t('crawlerKeywords.refresh')" placement="top">
                    <el-button 
                      type="text" 
                      icon="el-icon-refresh" 
                      :class="['refresh-icon', { 'is-spinning': scope.row._refreshing }]"
                      @click="handleRefresh(scope.row)"
                    />
                  </el-tooltip>
                  <el-tooltip :content="$t('crawlerKeywords.edit')" placement="top">
                    <el-button type="text" icon="el-icon-edit-outline" @click="handleEdit(scope.row)" />
                  </el-tooltip>
                  <el-tooltip :content="$t('crawlerKeywords.delete')" placement="top">
                    <el-button type="text" icon="el-icon-delete" class="del-btn" @click="handleDelete(scope.row)" />
                  </el-tooltip>
                </template>
              </div>
            </template>
          </el-table-column>
        </el-table>
  
        <div class="pagination-wrapper">
          <el-pagination
            background
            layout="total, sizes, prev, pager, next, jumper"
            :current-page="query.pageIndex"
            :page-size="query.pageSize"
            :page-sizes="[10, 20, 50]"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handlePageChange"
          />
        </div>
      </el-card>
    </div>
  </template>
  
  <script>
  import Common from '@/components/common/common';
  
  const API = {
    list: 'api/expert_manage/getKeywordList',
    add: 'api/expert_manage/addKeyword',
    update: 'api/expert_manage/updateKeyword',
    delete: 'api/expert_manage/deleteKeyword',
    refresh: 'api/expert_manage/refreshKeyword',
    startCrawl: 'api/expert_manage/startCrawl',
    exportData: 'api/expert_manage/exportKeywords'
  };
  
  export default {
    name: 'scholarCrawlersKeywords',
    directives: {
      focus: {
        inserted: (el) => el.querySelector('input').focus()
      }
    },
    data() {
      return {
        mediaUrl: Common.mediaUrl,
        newKeyword: '',
        searchText: '',
        loading: false,
        addLoading: false,
        exportLoading: false,
        crawlLoading: false,
        editingId: null,
        editForm: { keyword: '', category: '' },
        query: { pageIndex: 1, pageSize: 10 },
        list: [],
        total: 0,
        searchTimer: null
      };
    },
    created() {
      this.fetchList();
    },
    methods: {
      getStateText(state) {
        const map = {
          running: this.$t('crawlerKeywords.stateRunning'),
          paused: this.$t('crawlerKeywords.statePaused'),
          error: this.$t('crawlerKeywords.stateError'),
          done: this.$t('crawlerKeywords.stateDone')
        };
        return map[state] || state || '-';
      },
      async fetchList() {
        this.loading = true;
        try {
          const params = {
            keyword: this.searchText || '',
            pageIndex: this.query.pageIndex,
            pageSize: this.query.pageSize
          };
          const res = await this.$api.post(API.list, params);
          if (res && res.code === 0 && res.data) {
            this.list = (res.data.list || []).map(item => ({
              ...item,
              _refreshing: false
            }));
            this.total = res.data.total || 0;
          }
        } catch (e) {
          console.error(e);
        } finally {
          setTimeout(() => { this.loading = false; }, 300); // 增加微小延迟让加载动画更平滑
        }
      },
      handleSearch() {
        if (this.searchTimer) clearTimeout(this.searchTimer);
        this.searchTimer = setTimeout(() => {
          this.query.pageIndex = 1;
          this.fetchList();
        }, 400);
      },
      handleSearchNow() {
        if (this.searchTimer) {
          clearTimeout(this.searchTimer);
          this.searchTimer = null;
        }
        this.query.pageIndex = 1;
        this.fetchList();
      },
      async handleAdd() {
        const kw = (this.newKeyword || '').trim();
        if (!kw) {
          this.$message.warning(this.$t('crawlerKeywords.emptyKeywordWarn'));
          return;
        }
        this.addLoading = true;
        try {
          const res = await this.$api.post(API.add, { keyword: kw });
          if (res && res.code === 0) {
            this.$notify({ title: 'Success', message: this.$t('crawlerKeywords.addSuccess'), type: 'success' });
            this.newKeyword = '';
            this.query.pageIndex = 1;
            this.fetchList();
          }
        } finally {
          this.addLoading = false;
        }
      },
      handleEdit(row) {
        this.editingId = row.id;
        this.editForm = { keyword: row.keyword, category: row.category || '' };
      },
      async handleSaveEdit(row) {
        if (!(this.editForm.keyword || '').trim()) {
          this.$message.warning(this.$t('crawlerKeywords.emptyKeywordWarn'));
          return;
        }
        try {
          const res = await this.$api.post(API.update, {
            id: String(row.id),
            keyword: this.editForm.keyword.trim(),
            category: this.editForm.category || ''
          });
          if (res && res.code === 0) {
            this.$message.success(this.$t('crawlerKeywords.updateSuccess'));
            this.editingId = null;
            this.fetchList();
          }
        } catch (e) {
          this.$message.error(this.$t('crawlerKeywords.updateFail'));
        }
      },
      handleDelete(row) {
        this.$confirm(`确定要删除关键词 "${row.keyword}" 吗？`, '安全警告', {
          confirmButtonText: '确定删除',
          cancelButtonText: '取消',
          type: 'warning',
          center: true,
          roundButton: true
        }).then(async () => {
          const res = await this.$api.post(API.delete, { id: String(row.id) });
          if (res && res.code === 0) {
            this.$notify({ title: 'Deleted', type: 'success', duration: 2000 });
            this.fetchList();
          }
        }).catch(() => {});
      },
      async handleRefresh(row) {
        row._refreshing = true;
        try {
          const res = await this.$api.post(API.refresh, { id: String(row.id) });
          if (res && res.code === 0) {
            this.$message.success(this.$t('crawlerKeywords.refreshSuccess'));
            this.fetchList();
          }
        } finally {
          row._refreshing = false;
        }
      },
      async handleStartCrawl() {
        this.crawlLoading = true;
        try {
          const res = await this.$api.post(API.startCrawl, {});
          if (res && res.code === 0) {
            this.$message({ message: this.$t('crawlerKeywords.crawlStarted'), type: 'success', showClose: true });
            this.fetchList();
          }
        } finally {
          this.crawlLoading = false;
        }
      },
      async handleExport() {
        this.exportLoading = true;
        try {
          const res = await this.$api.post(API.exportData, {});
          if (res && res.code === 0 && res.data.file_url) {
            window.open(this.mediaUrl + res.data.file_url, '_blank');
          }
        } finally {
          this.exportLoading = false;
        }
      },
      handleSizeChange(size) {
        this.query.pageSize = size;
        this.fetchList();
      },
      handlePageChange(page) {
        this.query.pageIndex = page;
        this.fetchList();
      }
    }
  };
  </script>
  
  <style scoped>
  /* 容器及整体布局 */
  .keywords-container {
    padding: 10px;
   
    margin: 0 auto;
    background-color: #f8fafc;
    /* min-height: 100vh; */
  }
  
  /* 头部样式 */
  .page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 24px;
  }
  .page-title {
    margin: 0 0 6px;
    font-size: 24px;
    font-weight: 700;
    color: #1e293b;
    letter-spacing: -0.5px;
  }
  .page-desc {
    margin: 0;
    font-size: 14px;
    color: #64748b;
  }
  
  /* 新增区域：卡片化 */
  .add-section {
    display: flex;
    gap: 16px;
    margin-bottom: 24px;
    background: #ffffff;
    border-radius: 12px;
    padding: 20px;
    border: 1px solid #e2e8f0;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .shadow-hover:hover {
    box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.05);
    transform: translateY(-2px);
  }
  .add-input-custom ::v-deep .el-input__inner {
    border-radius: 8px;
    background-color: #f1f5f9;
    border-color: transparent;
  }
  .add-input-custom ::v-deep .el-input__inner:focus {
    background-color: #fff;
    border-color: #409eff;
  }
  
  /* 按钮发光 */
  .glow-button {
    box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
  }
  .glow-button:hover {
    box-shadow: 0 6px 16px rgba(64, 158, 255, 0.4);
  }
  
  /* 表格卡片 */
  .table-card {
    border-radius: 12px;
    border: 1px solid #e2e8f0;
    padding: 10px;
  }
  .table-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 18px;
  }
  .search-input ::v-deep .el-input__inner {
    border-radius: 20px;
  }
  
  /* 状态标签与脉冲 */
  .status-container {
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-right: 8px;
  }
  .pulse {
    animation: shadow-pulse 2s infinite;
  }
  @keyframes shadow-pulse {
    0% { box-shadow: 0 0 0 0px rgba(103, 194, 58, 0.4); }
    70% { box-shadow: 0 0 0 8px rgba(103, 194, 58, 0); }
    100% { box-shadow: 0 0 0 0px rgba(103, 194, 58, 0); }
  }
  
  .status-running { background: #67C23A; }
  .status-paused { background: #E6A23C; }
  .status-error { background: #F56C6C; animation-name: shadow-pulse-error; }
  .status-done { background: #94a3b8; }
  
  @keyframes shadow-pulse-error {
    0% { box-shadow: 0 0 0 0px rgba(245, 108, 108, 0.4); }
    70% { box-shadow: 0 0 0 8px rgba(245, 108, 108, 0); }
    100% { box-shadow: 0 0 0 0px rgba(245, 108, 108, 0); }
  }
  
  .text-running { color: #67C23A; font-weight: 600; }
  .text-error { color: #F56C6C; font-weight: 600; }
  
  /* 表格定制 */
  ::v-deep .custom-header th {
    /* background-color: #f8fafc !important; */
    color: #475569;
    font-weight: 600;
    /* height: 50px; */
  }
  .count-badge {
    background: #eff6ff;
    color: #2563eb;
    padding: 2px 8px;
    border-radius: 12px;
    font-weight: 700;
    font-size: 13px;
  }
  
  /* 操作按钮 */
  .action-wrapper .el-button {
    font-size: 18px;
    padding: 0 6px;
    transition: all 0.2s;
  }
  .action-wrapper .el-button:hover {
    transform: scale(1.2);
  }
  .del-btn { color: #ef4444 !important; }
  .save-btn { color: #10b981 !important; font-size: 14px !important; }
  .cancel-btn { color: #64748b !important; font-size: 14px !important; }
  
  /* 刷新旋转 */
  .is-spinning {
    animation: rotate 1s linear infinite;
    color: #409eff;
  }
  @keyframes rotate {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
  
  /* 过渡动画 */
  .fade-slide-enter-active, .fade-slide-leave-active {
    transition: all 0.25s ease;
  }
  .fade-slide-enter {
    opacity: 0;
    transform: translateY(5px);
  }
  .fade-slide-leave-to {
    opacity: 0;
    transform: translateY(-5px);
  }
  
  .pagination-wrapper {
    margin-top: 24px;
    display: flex;
    justify-content: flex-end;
  }
  ::v-deep .el-card__body{
    padding: 10px !important;
  }
  </style>