<template>
  <view class="agreement-page">
    <scroll-view class="agreement-scroll" scroll-y>
      <view class="screen list-screen">
        <view v-if="loading" class="state-text">加载中...</view>
        <view v-else-if="errorMessage" class="state-text" @click="loadAgreements">{{ errorMessage }}</view>
        <view v-else class="list-content">
          <view v-if="!agreements.length" class="state-text">暂无协议</view>
          <view v-else class="agreement-table">
            <view
              v-for="item in agreements"
              :key="item.id"
              class="agreement-row"
              hover-class="row-hover"
              @click="openPreview(item)"
            >
              <!-- <view class="version-cell">{{ item.version }}</view> -->
              <view class="agreement-cell">
                <view class="agreement-info">
                  <text class="agreement-name">{{ item.title }}</text>
                  <text v-if="item.date" class="agreement-date">{{ item.date }} 更新</text>
                </view>
                <text class="view-button">查看</text>
              </view>
            </view>
          </view>
          <view v-if="showPagination" class="pagination-bar">
            <button
              class="page-button"
              :class="{ 'page-button-disabled': !canPrevPage || loading }"
              :disabled="!canPrevPage || loading"
              @click="changePage(currentPage - 1)"
            >
              上一页
            </button>
            <text class="page-info">{{ currentPage }} / {{ totalPagesText }}</text>
            <button
              class="page-button"
              :class="{ 'page-button-disabled': !canNextPage || loading }"
              :disabled="!canNextPage || loading"
              @click="changePage(currentPage + 1)"
            >
              下一页
            </button>
          </view>
        </view>
      </view>
    </scroll-view>
  </view>
</template>

<script>
import { getContractList } from '@/api/contract.js';
import { refreshCurrentWebviewToken } from '@/utils/token.js';

export default {
  data() {
    return {
      agreements: [],
      loading: false,
      errorMessage: '',
      currentPage: 1,
      pageSize: 10,
      total: null,
      hasNextPage: false
    };
  },
  computed: {
    totalPages() {
      if (this.total === null) return this.currentPage;
      return Math.max(1, Math.ceil(this.total / this.pageSize));
    },
    totalPagesText() {
      if (this.total !== null) return String(this.totalPages);
      return this.hasNextPage ? this.currentPage + '+' : String(this.currentPage);
    },
    canPrevPage() {
      return this.currentPage > 1;
    },
    canNextPage() {
      if (this.total !== null) return this.currentPage < this.totalPages;
      return this.hasNextPage;
    },
    showPagination() {
      return this.currentPage > 1 || this.canNextPage || (this.total !== null && this.total > this.pageSize);
    }
  },
  onLoad(options = {}) {
    refreshCurrentWebviewToken(options.token ? '?token=' + encodeURIComponent(options.token) : '');
    uni.setNavigationBarTitle({
      title: '旧版协议'
    });
    this.loadAgreements(1);
  },
  methods: {
    async loadAgreements(page = this.currentPage) {
      if (this.loading) return;
      const nextPage = Math.max(1, Number(page) || 1);
      this.loading = true;
      this.errorMessage = '';
      try {
        const response = await getContractList({
          page: nextPage,
          limit: this.pageSize
        });
        const list = this.normalizeList(response);
        const pagination = this.resolvePagination(response, list.length, nextPage);
        this.currentPage = nextPage;
        this.agreements = list;
        this.total = pagination.total;
        this.hasNextPage = pagination.hasNextPage;
      } catch (error) {
        this.errorMessage = this.getErrorMessage(error, '协议加载失败，点击重试');
      } finally {
        this.loading = false;
      }
    },
    normalizeList(response) {
      const payload = this.unwrapPayload(response);
      const list = this.pickList(payload);

      return list
        .map(item => this.normalizeAgreementItem(item))
        .filter(item => item.id !== '');
    },
    unwrapPayload(response) {
      if (response && typeof response === 'object' && response.data !== undefined) {
        return response.data;
      }
      return response;
    },
    pickList(payload) {
      if (Array.isArray(payload)) return payload;
      if (!payload || typeof payload !== 'object') return [];

      const candidates = [
        payload.list,
        payload.data,
        payload.data && payload.data.list,
        payload.data && payload.data.rows,
        payload.data && payload.data.records,
        payload.rows,
        payload.records,
        payload.result,
        payload.result && payload.result.list
      ];

      for (let index = 0; index < candidates.length; index += 1) {
        if (Array.isArray(candidates[index])) {
          return candidates[index];
        }
      }

      return [];
    },
    resolvePagination(response, listLength, page) {
      const sources = this.collectPaginationSources(response);
      const total = this.pickNumber(sources, [
        'total',
        'count',
        'total_count',
        'totalCount',
        'total_num',
        'totalNum'
      ]);
      const responsePageSize =
        this.pickNumber(sources, ['limit', 'pageSize', 'page_size', 'per_page', 'perPage']) || this.pageSize;
      const explicitHasNext = this.pickValue(sources, ['has_more', 'hasMore', 'has_next', 'hasNext']);

      let hasNextPage = false;
      if (total !== null) {
        hasNextPage = page < Math.max(1, Math.ceil(total / responsePageSize));
      } else if (explicitHasNext !== undefined) {
        hasNextPage = explicitHasNext === true || explicitHasNext === 1 || explicitHasNext === '1';
      } else {
        hasNextPage = listLength >= responsePageSize;
      }

      return {
        total,
        hasNextPage
      };
    },
    collectPaginationSources(response) {
      const sources = [];
      const stack = [response];
      const seen = [];

      while (stack.length && sources.length < 12) {
        const item = stack.shift();
        if (!item || typeof item !== 'object' || seen.indexOf(item) !== -1) continue;
        seen.push(item);
        sources.push(item);

        ['data', 'result', 'page', 'pagination', 'meta'].forEach(key => {
          if (item[key] && typeof item[key] === 'object') {
            stack.push(item[key]);
          }
        });
      }

      return sources;
    },
    pickNumber(sources, keys) {
      const value = this.pickValue(sources, keys);
      if (value === undefined || value === null || value === '') return null;
      const numberValue = Number(value);
      return Number.isFinite(numberValue) ? numberValue : null;
    },
    pickValue(sources, keys) {
      for (let sourceIndex = 0; sourceIndex < sources.length; sourceIndex += 1) {
        const source = sources[sourceIndex];
        for (let keyIndex = 0; keyIndex < keys.length; keyIndex += 1) {
          const key = keys[keyIndex];
          if (Object.prototype.hasOwnProperty.call(source, key)) {
            return source[key];
          }
        }
      }
      return undefined;
    },
    normalizeAgreementItem(item) {
      item = item || {};
      const id = this.toText(item.id || item.contract_id || item.agreement_id);
      const title = this.toText(
        item.title ||
          item.name ||
          item.contract_name ||
          item.agreement_name ||
          item.content_name || '未命名'
      );
      const version = this.toText(
        item.version ||
          item.version_name ||
          item.contract_version ||
          item.edition ||
          item.v ||
          (id ? 'id' + id : '')
      );
      const date = this.formatDate(
        item.date ||
          item.release_time ||
          item.publish_time ||
          item.create_time ||
          item.add_time ||
          item.updated_at ||
          item.update_time
      );

      return {
        id,
        title,
        version,
        date
      };
    },
    formatDate(value) {
      if (value === undefined || value === null || value === '') return '';
      if (typeof value === 'number') {
        const timestamp = value > 100000000000 ? value : value * 1000;
        const date = new Date(timestamp);
        if (!Number.isNaN(date.getTime())) {
          return this.padDate(date);
        }
      }
      const text = this.toText(value);
      if (/^\d+$/.test(text)) {
        return this.formatDate(Number(text));
      }
      return text.split(' ')[0].replace(/-/g, '年').replace(/^(\d{4})年(\d{2})年(\d{2})$/, '$1年$2月$3日');
    },
    padDate(date) {
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const day = String(date.getDate()).padStart(2, '0');
      return date.getFullYear() + '年' + month + '月' + day + '日';
    },
    toText(value) {
      if (value === undefined || value === null) return '';
      return String(value).trim();
    },
    getErrorMessage(error, defaultMessage) {
      if (error && error.msg) return error.msg;
      if (error && error.message) return error.message;
      if (typeof error === 'string') return error;
      return defaultMessage;
    },
    changePage(page) {
      if (page < 1 || this.loading) return;
      if (page > this.currentPage && !this.canNextPage) return;
      this.loadAgreements(page);
    },
    openPreview(item) {
      if (!item.id) {
        uni.showToast({
          title: '协议ID为空',
          icon: 'none'
        });
        return;
      }
      uni.navigateTo({
        url: `/pages/agreement/preview/index?id=${encodeURIComponent(item.id)}`
      });
    }
  }
};
</script>

<style scoped>
page {
  height: 100%;
  overflow: hidden;
  background: #ffffff;
}

.agreement-page {
  width: 100%;
  height: 100%;
  min-height: 0;
  display: flex;
  overflow: hidden;
  background: #ffffff;
  color: #111111;
}

.agreement-scroll {
  flex: 1;
  width: 100%;
  height: 100%;
}

.screen {
  background: #ffffff;
}

.list-screen {
  display: flex;
  box-sizing: border-box;
  min-height: 100%;
  flex-direction: column;
  overflow: visible;
  padding: 16px 16px calc(14px + env(safe-area-inset-bottom));
}

.list-content {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  flex-direction: column;
  overflow: visible;
}

.agreement-table {
  display: flex;
  flex: 0 0 auto;
  min-height: 0;
  flex-direction: column;
  overflow: visible;
  width: 100%;
  border: 1px solid #c9c9c9;
  border-bottom: none;
  background: #fff0e2;
}

.state-text {
  padding: 28px 0;
  color: #666666;
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
}

.agreement-row {
  display: flex;
  flex: 0 0 auto;
  min-height: 54px;
  border-bottom: 1px solid #c9c9c9;
}

.row-hover {
  opacity: 0.78;
}

.version-cell {
  display: flex;
  flex: 0 0 56px;
  align-items: center;
  justify-content: center;
  border-right: 1px solid #c9c9c9;
  color: #111111;
  font-size: 14px;
  line-height: 1.45;
}

.agreement-cell {
  display: flex;
  flex: 1;
  min-width: 0;
  align-items: center;
  justify-content: space-between;
  padding: 0;
  background: #fff0e2;
  color: #171717;
}

.agreement-info {
  display: flex;
  min-width: 0;
  flex: 1;
  flex-direction: column;
  justify-content: center;
  padding: 7px 10px;
}

.agreement-name,
.agreement-date {
  display: block;
  overflow: hidden;
  font-size: 28rpx;
  line-height: 1.5;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agreement-date {
	font-size: 24rpx;
	color: gray;
	margin-top: 14rpx;
}

.view-button {
  display: flex;
  flex: 0 0 48px;
  align-self: stretch;
  align-items: center;
  justify-content: center;
  border-left: 1px solid #c9c9c9;
  color: #1677ff;
  font-size: 14px;
  line-height: 1.45;
  text-decoration: underline;
}

.pagination-bar {
  display: flex;
  flex: 0 0 44px;
  align-items: center;
  justify-content: center;
  padding: 14px 0 2px;
}

.page-button {
  width: 74px;
  height: 32px;
  margin: 0;
  padding: 0;
  border: 1px solid #ec0208;
  border-radius: 16px;
  background: #ffffff;
  color: #ec0208;
  font-size: 13px;
  line-height: 30px;
}

.page-button::after {
  border: 0;
}

.page-button-disabled {
  border-color: #d8d8d8;
  color: #a6a6a6;
  background: #f7f7f7;
}

.page-info {
  min-width: 68px;
  height: 32px;
  margin: 0 10px;
  padding: 0 8px;
  border-radius: 16px;
  background: #f5f7fa;
  color: #333333;
  font-size: 13px;
  line-height: 32px;
  text-align: center;
}

</style>
