<template>
  <view class="page">
    <NavBar title="订单管理" :showBack="true" />

    <!-- 搜索栏 -->
    <view class="search-bar">
      <view class="search-input-wrap">
        <view class="search-icon"></view>
        <input
          class="search-input"
          v-model="searchKeyword"
          placeholder="搜索订单编号或手机号"
          confirm-type="search"
          @confirm="handleSearch"
        />
        <view class="search-clear" v-if="searchKeyword" @click="clearSearch"></view>
      </view>
    </view>

    <!-- 时间筛选栏 -->
    <view class="time-filter-bar">
      <view class="date-presets-row">
        <view
          v-for="d in datePresets"
          :key="d.days"
          class="preset-chip"
          :class="{ active: datePresetDays === d.days }"
          @click="setDatePreset(d.days)"
        >
          <text>{{ d.label }}</text>
        </view>
        <view class="preset-chip custom" :class="{ active: datePresetDays < 0 }" @click="showDatePicker = true">
          <text>{{ datePresetDays < 0 ? dateRangeShortText : '自定义' }}</text>
        </view>
      </view>
      <text class="result-count">共 {{ total }} 条</text>
    </view>

    <!-- Tab 栏 -->
    <view class="tab-bar">
      <view
        v-for="tab in tabs"
        :key="tab.key"
        class="tab-item"
        :class="{ active: currentTab === tab.key }"
        @click="changeTab(tab.key)"
      >
        <text class="tab-label">{{ tab.label }}</text>
        <view class="tab-line" v-if="currentTab === tab.key"></view>
      </view>
    </view>

    <!-- 订单列表 -->
    <scroll-view
      class="order-scroll"
      scroll-y
      @scrolltolower="loadMore"
      refresher-enabled
      :refresher-triggered="isRefreshing"
      @refresherrefresh="onRefresh"
    >
      <!-- 骨架屏 -->
      <view class="skeleton-list" v-if="isFirstLoad">
        <view class="skeleton-card" v-for="i in 3" :key="i">
          <view class="sk-row sk-header">
            <view class="sk-box w-48"></view>
            <view class="sk-box w-16"></view>
          </view>
          <view class="sk-row sk-body">
            <view class="sk-col" style="flex:1;">
              <view class="sk-box w-24" style="height: 34rpx; margin-bottom: 8rpx;"></view>
              <view class="sk-box w-32"></view>
            </view>
            <view class="sk-col" style="align-items:flex-end;">
              <view class="sk-box w-28"></view>
              <view class="sk-box w-20" style="margin-top: 4rpx;"></view>
            </view>
          </view>
          <view class="sk-row">
            <view class="sk-box w-32"></view>
          </view>
        </view>
      </view>

      <!-- 错误状态 -->
      <view class="error-state" v-if="errorMsg && !isFirstLoad">
        <view class="error-icon"></view>
        <text class="error-text">{{ errorMsg }}</text>
        <view class="retry-btn" @click="onRefresh"><text>点击重试</text></view>
      </view>

      <!-- 订单列表 -->
      <view class="order-list" v-if="!isFirstLoad && !errorMsg">
        <view
          class="order-card"
          v-for="order in orderList"
          :key="order.id"
          @click="goDetail(order.id)"
        >
          <view class="card-header">
            <text class="order-no">{{ order.orderNo }}</text>
            <text class="order-status" :class="getStatusClass(order.status)">
              {{ order.statusLabel || getStatusText(order.status) }}
            </text>
          </view>

          <view class="card-body">
            <view class="body-left" v-if="order.deviceName || order.shopName">
              <text class="body-device" v-if="order.deviceName">{{ order.deviceName }}</text>
              <text class="body-shop" v-if="order.shopName">{{ order.shopName }}</text>
            </view>
            <view class="body-right">
              <text class="order-amount">¥{{ formatAmount(order) }}</text>
              <text class="discount-tag" v-if="order.discountAmount > 0">优惠 ¥{{ order.discountAmount }}</text>
            </view>
          </view>

          <view class="card-footer">
            <view class="footer-info">
              <text class="footer-time">{{ formatDateTime(order.createTime) }}</text>
              <text class="footer-sep" v-if="order.userName || order.phone">·</text>
              <text class="footer-user" v-if="order.userName || order.phone">{{ order.userName || '' }}{{ order.userName && order.phone ? ' ' : '' }}{{ order.phone || '' }}</text>
            </view>
            <view class="view-btn" @click.stop="goDetail(order.id)">
              <text>详情</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 加载更多 -->
      <view class="loading-more" v-if="isLoadingMore && !isFirstLoad">
        <view class="loading-spinner"></view>
        <text>加载中</text>
      </view>
      <view class="no-more" v-if="!hasMore && orderList.length > 0 && !isFirstLoad">
        <text>没有更多了</text>
      </view>

      <!-- 空状态 -->
      <view class="empty-state" v-if="!isFirstLoad && !errorMsg && orderList.length === 0">
        <view class="empty-icon-box">
          <view class="empty-doc-icon"></view>
        </view>
        <text class="empty-title">暂无订单</text>
        <text class="empty-desc">当前筛选条件下没有订单数据</text>
      </view>
    </scroll-view>

    <!-- 日期选择弹窗 -->
    <view class="date-modal" v-if="showDatePicker" @click="showDatePicker = false">
      <view class="modal-content" @click.stop>
        <view class="modal-header">
          <text class="modal-title">自定义时间范围</text>
          <view class="modal-close" @click="showDatePicker = false"></view>
        </view>
        <view class="modal-body">
          <view class="date-row">
            <text class="date-label">开始日期</text>
            <picker mode="date" :value="startDate" :end="endDate" @change="onStartDateChange">
              <view class="picker-value">{{ startDate }}</view>
            </picker>
          </view>
          <view class="date-row">
            <text class="date-label">结束日期</text>
            <picker mode="date" :value="endDate" :end="formatDateStr(today)" @change="onEndDateChange">
              <view class="picker-value">{{ endDate }}</view>
            </picker>
          </view>
        </view>
        <view class="modal-footer">
          <button class="btn-cancel" @click="showDatePicker = false">取消</button>
          <button class="btn-confirm" @click="confirmDateRange">确定</button>
        </view>
      </view>
    </view>

    <CustomTabBar />
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import NavBar from '@/components/NavBar.vue';
import CustomTabBar from '@/components/CustomTabBar.vue';
import { getOrderList } from '@/api/order';
import { OrderStatusText } from '@/utils/constants';

interface OrderItem {
  id: string;
  orderNo: string;
  status: number;
  statusLabel?: string;
  paidAmount?: number;
  totalAmount?: number;
  discountAmount?: number;
  createTime: string;
  deviceId?: string;
  deviceName?: string;
  shopName?: string;
  storeName?: string;
  userName?: string;
  phone?: string;
  payType?: string;
}

const tabs = [
  { key: 'sales', label: '销售订单', params: { status: 1 } },
  { key: 'refund', label: '退款订单', params: { payStatus: 'REFUND' } },
  { key: 'abnormal', label: '异常订单', params: { statusList: [2, 3] } },
  { key: 'unpaid', label: '未支付', params: { status: 0 } }
];

const datePresets = [
  { label: '今天', days: 0 },
  { label: '近7天', days: 7 },
  { label: '近30天', days: 30 }
];

const currentTab = ref('sales');
const orderList = ref<OrderItem[]>([]);
const isFirstLoad = ref(true);
const isLoadingMore = ref(false);
const isRefreshing = ref(false);
const hasMore = ref(true);
const page = ref(1);
const total = ref(0);
const errorMsg = ref('');
const searchKeyword = ref('');

const today = new Date();
const formatDateStr = (d: Date) => {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;
};
const getDateBefore = (days: number) => new Date(today.getTime() - days * 86400000);

const startDate = ref(formatDateStr(getDateBefore(29)));
const endDate = ref(formatDateStr(today));
const showDatePicker = ref(false);
const datePresetDays = ref(30);

const dateRangeShortText = computed(() => `${startDate.value}~${endDate.value}`);

const getStatusText = (status: number): string => OrderStatusText[status] || '未知';

const getStatusClass = (status: number): string => {
  if (status === 1) return 'completed';
  if (status === 0) return 'pending';
  if (status === 2) return 'cancelled';
  return 'closed';
};

const formatAmount = (order: OrderItem): string => {
  const amount = order.paidAmount ?? order.totalAmount ?? 0;
  return Number(amount).toFixed(2);
};

const formatDateTime = (datetime: string): string => {
  if (!datetime) return '';
  return datetime.length > 16 ? datetime.slice(0, 16) : datetime;
};

const loadOrders = async () => {
  errorMsg.value = '';

  try {
    const tab = tabs.find(t => t.key === currentTab.value);
    const params: Record<string, unknown> = {
      page: page.value,
      pageSize: 10,
      startDate: startDate.value,
      endDate: endDate.value,
      ...tab?.params
    };

    const kw = searchKeyword.value.trim();
    if (kw) {
      if (/^1\d{10}$/.test(kw)) {
        params.phone = kw;
      } else {
        params.orderNo = kw;
      }
    }

    const res = await getOrderList(params);
    if (!res) {
      if (page.value === 1) orderList.value = [];
      return;
    }

    if (page.value === 1) {
      orderList.value = res.list || [];
    } else {
      orderList.value = [...orderList.value, ...(res.list || [])];
    }

    total.value = res.total || 0;
    hasMore.value = orderList.value.length < total.value;
  } catch (e: any) {
    if (page.value === 1) {
      errorMsg.value = e?.message || '加载失败，请检查网络后重试';
      orderList.value = [];
    }
  } finally {
    isFirstLoad.value = false;
    isLoadingMore.value = false;
    isRefreshing.value = false;
  }
};

const loadMore = () => {
  if (isLoadingMore.value || !hasMore.value || isFirstLoad.value) return;
  isLoadingMore.value = true;
  page.value++;
  loadOrders();
};

const onRefresh = () => {
  isRefreshing.value = true;
  page.value = 1;
  hasMore.value = true;
  loadOrders();
};

const changeTab = (key: string) => {
  if (currentTab.value === key) return;
  currentTab.value = key;
  page.value = 1;
  hasMore.value = true;
  errorMsg.value = '';
  isFirstLoad.value = true;
  loadOrders();
};

const goDetail = (orderId: string) => {
  uni.navigateTo({ url: `/pages/orders/detail?id=${orderId}` });
};

const handleSearch = () => {
  page.value = 1;
  hasMore.value = true;
  isFirstLoad.value = true;
  loadOrders();
};

const clearSearch = () => {
  searchKeyword.value = '';
  handleSearch();
};

const setDatePreset = (days: number) => {
  datePresetDays.value = days;
  endDate.value = formatDateStr(today);
  startDate.value = formatDateStr(getDateBefore(days));
  page.value = 1;
  hasMore.value = true;
  isFirstLoad.value = true;
  loadOrders();
};

const onStartDateChange = (e: { detail: { value: string } }) => {
  startDate.value = e.detail.value;
  datePresetDays.value = -1;
};

const onEndDateChange = (e: { detail: { value: string } }) => {
  endDate.value = e.detail.value;
  datePresetDays.value = -1;
};

const confirmDateRange = () => {
  showDatePicker.value = false;
  page.value = 1;
  hasMore.value = true;
  isFirstLoad.value = true;
  loadOrders();
};

onMounted(() => {
  isFirstLoad.value = true;
  loadOrders();
});
</script>

<style lang="scss" scoped>
$font-stack: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', system-ui, sans-serif;

.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
  background: $bg-color-page;
  font-family: $font-stack;
  padding-bottom: env(safe-area-inset-bottom);
}

// ====== Search ======
.search-bar {
  padding: 20rpx $spacing-3;
  background: $bg-color-card;
}

.search-input-wrap {
  display: flex;
  align-items: center;
  height: 64rpx;
  padding: 0 $spacing-3;
  background: $bg-color-page;
  border-radius: $radius-full;
}

.search-icon {
  width: 32rpx;
  height: 32rpx;
  margin-right: $spacing-2;
  flex-shrink: 0;
  position: relative;

  &::before {
    content: '';
    position: absolute;
    top: 2rpx;
    left: 2rpx;
    width: 18rpx;
    height: 18rpx;
    border: 2.5rpx solid $text-color-placeholder;
    border-radius: 50%;
  }

  &::after {
    content: '';
    position: absolute;
    bottom: 2rpx;
    right: 2rpx;
    width: 2.5rpx;
    height: 10rpx;
    background: $text-color-placeholder;
    border-radius: 1rpx;
    transform: rotate(-45deg);
    transform-origin: top center;
  }
}

.search-input {
  flex: 1;
  height: 64rpx;
  font-size: $font-size-base;
  color: $text-color-primary;
}

.search-clear {
  width: 32rpx;
  height: 32rpx;
  flex-shrink: 0;
  position: relative;

  &::before, &::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 16rpx;
    height: 2rpx;
    background: $text-color-placeholder;
    border-radius: 1rpx;
  }

  &::before { transform: translate(-50%, -50%) rotate(45deg); }
  &::after  { transform: translate(-50%, -50%) rotate(-45deg); }
}

// ====== Time filter ======
.time-filter-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16rpx $spacing-3;
  background: $bg-color-card;
  border-bottom: 1rpx solid $border-color-light;
}

.date-presets-row {
  display: flex;
  gap: 12rpx;
}

.preset-chip {
  display: inline-flex;
  align-items: center;
  padding: 8rpx 24rpx;
  border-radius: $radius-full;
  background: $bg-color-page;
  border: 1rpx solid transparent;

  text {
    font-size: 22rpx;
    color: $text-color-secondary;
    line-height: 1;
  }

  &.active {
    background: $primary-color-bg;
    border-color: $primary-color;

    text { color: $primary-color-dark; font-weight: 500; }
  }

  &.custom {
    max-width: 240rpx;

    text {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}

.result-count {
  font-size: 22rpx;
  color: $text-color-muted;
  flex-shrink: 0;
}

// ====== Tab bar ======
.tab-bar {
  display: flex;
  background: $bg-color-card;
  border-bottom: 1rpx solid $border-color-light;
}

.tab-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20rpx 0 16rpx;
  position: relative;

  .tab-label {
    font-size: 26rpx;
    color: $text-color-secondary;
  }

  &.active .tab-label {
    color: $primary-color;
    font-weight: 600;
  }

  .tab-line {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 40rpx;
    height: 4rpx;
    background: $primary-color;
    border-radius: 2rpx;
  }
}

// ====== Scroll ======
.order-scroll {
  flex: 1;
  height: 0;
}

// ====== Skeleton ======
.skeleton-list { padding: $spacing-2 $spacing-3; }

.skeleton-card {
  padding: $spacing-3;
  margin-bottom: $spacing-2;
  background: $bg-color-card;
  border-radius: $radius-md;

  .sk-row {
    display: flex;
    align-items: center;
    margin-bottom: $spacing-2;
  }

  .sk-header { justify-content: space-between; }
  .sk-body { gap: $spacing-2; }
  .sk-col { flex: 1; display: flex; flex-direction: column; gap: $spacing-1; }

  .sk-box {
    height: 28rpx;
    background: $bg-color-page;
    border-radius: $radius-xs;
  }

  .w-16 { width: 16%; }
  .w-20 { width: 20%; }
  .w-24 { width: 24%; }
  .w-28 { width: 28%; }
  .w-32 { width: 32%; }
  .w-48 { width: 48%; }
}

// ====== Error state ======
.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 160rpx $spacing-4;

  .error-icon {
    width: 80rpx;
    height: 80rpx;
    border-radius: 50%;
    background: $error-color-bg;
    margin-bottom: $spacing-3;
    position: relative;

    &::before {
      content: '!';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      font-size: 40rpx;
      font-weight: 700;
      color: $error-color;
      line-height: 1;
    }
  }

  .error-text {
    font-size: $font-size-base;
    color: $text-color-secondary;
    margin-bottom: $spacing-4;
    text-align: center;
  }

  .retry-btn {
    padding: $spacing-2 $spacing-6;
    background: $primary-color;
    border-radius: $radius-full;

    text { font-size: $font-size-base; color: $text-color-primary; font-weight: 500; }
  }
}

// ====== Order card ======
.order-list { padding: $spacing-2 $spacing-3; }

.order-card {
  padding: $spacing-3;
  margin-bottom: $spacing-2;
  background: $bg-color-card;
  border-radius: $radius-md;
  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);

  &:active { opacity: 0.7; }
}

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

  .order-no {
    font-size: 26rpx;
    color: $text-color-tertiary;
    letter-spacing: 0.02em;
    line-height: 1;
  }

  .order-status {
    font-size: 24rpx;
    font-weight: 500;
    line-height: 1;

    &.completed { color: $success-color; }
    &.pending   { color: $warning-color; }
    &.cancelled { color: $text-color-muted; }
    &.closed    { color: $text-color-tertiary; }
  }
}

.card-body {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 16rpx;

  .body-left {
    .body-device {
      font-size: 24rpx;
      color: $text-color-secondary;
      line-height: 1.4;
    }

    .body-shop {
      font-size: 22rpx;
      color: $text-color-muted;
      line-height: 1.4;
      margin-top: 4rpx;
    }
  }

  .body-right {
    text-align: right;

    .order-amount {
      font-size: 34rpx;
      font-weight: 700;
      color: $text-color-primary;
      line-height: 1.2;
    }

    .discount-tag {
      display: inline-block;
      margin-top: 8rpx;
      padding: 2rpx 10rpx;
      font-size: 20rpx;
      color: $error-color;
      background: $error-color-bg;
      border-radius: $radius-xs;
      line-height: 1.4;
    }
  }
}

.card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;

  .footer-info {
    display: flex;
    align-items: center;
    min-width: 0;

    .footer-time {
      font-size: 24rpx;
      color: $text-color-muted;
      line-height: 1;
    }

    .footer-sep {
      margin: 0 8rpx;
      font-size: 24rpx;
      color: $text-color-placeholder;
      line-height: 1;
    }

    .footer-user {
      font-size: 24rpx;
      color: $text-color-muted;
      line-height: 1;
    }
  }

  .view-btn {
    display: flex;
    align-items: center;
    padding: 8rpx $spacing-4;
    border-radius: $radius-sm;
    background: $bg-color-page;

    text { font-size: 24rpx; color: $text-color-secondary; font-weight: 500; line-height: 1; }
  }
}

// ====== Loading / No more / Empty ======
.loading-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: $spacing-1;
  padding: $spacing-4;
  color: $text-color-muted;
  font-size: $font-size-sm;

  .loading-spinner {
    width: 32rpx;
    height: 32rpx;
    border: 3rpx solid $border-color;
    border-top-color: $primary-color;
    border-radius: 50%;
    animation: spin 1s linear infinite;
  }
}

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

.no-more {
  padding: $spacing-4;
  text-align: center;
  font-size: $font-size-sm;
  color: $text-color-placeholder;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 160rpx $spacing-4;

  .empty-icon-box {
    width: 120rpx;
    height: 120rpx;
    border-radius: $radius-xl;
    background: $bg-color-secondary;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: $spacing-3;
  }

  .empty-doc-icon {
    width: 44rpx;
    height: 52rpx;
    position: relative;

    &::before {
      content: '';
      position: absolute;
      inset: 0;
      border: 2.5rpx solid $text-color-placeholder;
      border-radius: 4rpx;
    }

    &::after {
      content: '';
      position: absolute;
      top: 16rpx;
      left: 10rpx;
      right: 10rpx;
      height: 2.5rpx;
      background: $text-color-placeholder;
      border-radius: 1rpx;
      box-shadow: 0 10rpx 0 $text-color-placeholder, 0 20rpx 0 $text-color-placeholder;
    }
  }

  .empty-title {
    font-size: $font-size-base;
    font-weight: 500;
    color: $text-color-secondary;
    margin-bottom: $spacing-1;
  }

  .empty-desc {
    font-size: $font-size-sm;
    color: $text-color-muted;
  }
}

// ====== Date modal ======
.date-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 $spacing-6;
  background: rgba(0, 0, 0, 0.45);
}

.modal-content {
  width: 100%;
  background: $bg-color-card;
  border-radius: $radius-xl;
  overflow: hidden;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: $spacing-3;
  border-bottom: 1rpx solid $border-color-light;

  .modal-title {
    font-size: $font-size-md;
    font-weight: 600;
    color: $text-color-primary;
  }

  .modal-close {
    width: 44rpx;
    height: 44rpx;
    position: relative;

    &::before, &::after {
      content: '';
      position: absolute;
      top: 50%;
      left: 50%;
      width: 20rpx;
      height: 2rpx;
      background: $text-color-muted;
      border-radius: 1rpx;
    }

    &::before { transform: translate(-50%, -50%) rotate(45deg); }
    &::after  { transform: translate(-50%, -50%) rotate(-45deg); }
  }
}

.modal-body {
  padding: $spacing-3;
}

.date-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: $spacing-2 0;
  border-bottom: 1rpx solid $border-color-light;

  &:last-of-type { border-bottom: none; }

  .date-label {
    font-size: $font-size-base;
    color: $text-color-secondary;
  }

  .picker-value {
    font-size: $font-size-base;
    color: $text-color-primary;
    padding: $spacing-1 $spacing-2;
    background: $bg-color-page;
    border-radius: $radius-sm;
  }
}

.modal-footer {
  display: flex;
  gap: $spacing-2;
  padding: 0 $spacing-3 $spacing-3;

  button {
    flex: 1;
    height: 80rpx;
    line-height: 80rpx;
    padding: 0;
    border: none;
    border-radius: $radius-base;
    font-size: $font-size-base;
    font-weight: 500;

    &::after { border: none; }
  }

  .btn-cancel {
    background: $bg-color-page;
    color: $text-color-secondary;
  }

  .btn-confirm {
    background: $primary-color;
    color: $text-color-primary;
  }
}
</style>
