<script setup lang="ts">
/**
 * 购物车页
 *
 * 全选 / 单选、修改数量、删除、清空，底部汇总结算
 */
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ArrowRight, Delete, Minus, Plus, ShoppingCart } from '@element-plus/icons-vue'
import AppHeader from '@/components/layout/AppHeader.vue'
import AppFooter from '@/components/layout/AppFooter.vue'
import EmptyState from '@/components/common/EmptyState.vue'
import {
  getCartApi,
  updateCartQuantityApi,
  updateCartSelectedApi,
  updateAllCartSelectedApi,
  deleteCartItemApi,
  batchDeleteCartApi,
  clearCartApi
} from '@/api/cart'
import type { CartItem } from '@/types/cart'

const router = useRouter()

const items = ref<CartItem[]>([])
const loading = ref(true)
const updatingSkuId = ref<number | null>(null)

const allSelected = computed(() => {
  return items.value.length > 0 && items.value.every(item => item.selected === 1)
})

const someSelected = computed(() => {
  return items.value.some(item => item.selected === 1) && !allSelected.value
})

const selectedItems = computed(() => items.value.filter(item => item.selected === 1))

const selectedCount = computed(() => {
  return selectedItems.value.reduce((sum, item) => sum + item.quantity, 0)
})

const selectedAmount = computed(() => {
  return selectedItems.value.reduce((sum, item) => sum + Number(item.subtotal || 0), 0)
})

const totalCount = computed(() => {
  return items.value.reduce((sum, item) => sum + item.quantity, 0)
})

const canCheckout = computed(() => {
  return (
    selectedItems.value.length > 0 &&
    selectedItems.value.every(item => item.productStatus === 1)
  )
})

async function loadCart() {
  loading.value = true
  try {
    const data = await getCartApi()
    items.value = data?.items || []
  } catch {
    items.value = []
  } finally {
    loading.value = false
  }
}

function formatPrice(value: number | string | null | undefined) {
  return Number(value || 0).toFixed(2)
}

async function toggleAll(checked: boolean | number | string) {
  const selected: 0 | 1 = checked === true || checked === 1 ? 1 : 0
  items.value = items.value.map(item => {
    if (item.productStatus !== 1) return item
    return { ...item, selected }
  })
  try {
    await updateAllCartSelectedApi(selected)
  } catch {
    loadCart()
  }
}

async function toggleItem(item: CartItem, checked: boolean | number | string) {
  if (item.productStatus !== 1) return
  const selected: 0 | 1 = checked === true || checked === 1 ? 1 : 0
  const index = items.value.findIndex(row => row.skuId === item.skuId)
  if (index !== -1) {
    items.value[index] = { ...items.value[index], selected }
  }
  try {
    await updateCartSelectedApi(item.skuId, selected)
  } catch {
    loadCart()
  }
}

async function changeQuantity(item: CartItem, delta: number) {
  if (item.productStatus !== 1 || updatingSkuId.value === item.skuId) return

  const next = item.quantity + delta
  if (next < 1) return

  const max = Math.min(item.stock || 99, 99)
  if (next > max) {
    ElMessage.warning(next > 99 ? '单件商品最多购买 99 件' : '库存不足')
    return
  }

  updatingSkuId.value = item.skuId
  try {
    await updateCartQuantityApi({ skuId: item.skuId, quantity: next })
    item.quantity = next
    item.subtotal = Number((Number(item.price) * next).toFixed(2))
  } catch {
    /* 拦截器已提示 */
  } finally {
    updatingSkuId.value = null
  }
}

async function deleteItem(item: CartItem) {
  try {
    await ElMessageBox.confirm(
      `确定删除「${item.productName}」吗？`,
      '删除商品',
      {
        confirmButtonText: '删除',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
  } catch {
    return
  }

  try {
    await deleteCartItemApi(item.skuId)
    ElMessage.success('已删除')
    await loadCart()
  } catch {
    /* 拦截器已提示 */
  }
}

async function removeSelected() {
  if (!selectedItems.value.length) {
    ElMessage.warning('请先勾选要删除的商品')
    return
  }

  try {
    await ElMessageBox.confirm(
      `确定删除选中的 ${selectedItems.value.length} 件商品吗？`,
      '批量删除',
      {
        confirmButtonText: '删除',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
  } catch {
    return
  }

  try {
    await batchDeleteCartApi(selectedItems.value.map(item => item.skuId))
    ElMessage.success('已删除选中商品')
    await loadCart()
  } catch {
    /* 拦截器已提示 */
  }
}

async function clearCart() {
  if (!items.value.length) return

  try {
    await ElMessageBox.confirm(
      '确定清空购物车吗？',
      '清空购物车',
      {
        confirmButtonText: '清空',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
  } catch {
    return
  }

  try {
    await clearCartApi()
    ElMessage.success('购物车已清空')
    await loadCart()
  } catch {
    /* 拦截器已提示 */
  }
}

function goCheckout() {
  if (!selectedItems.value.length) {
    ElMessage.warning('请先选择商品')
    return
  }
  if (selectedItems.value.some(item => item.productStatus !== 1)) {
    ElMessage.warning('已下架商品不能结算，请先取消选择')
    return
  }
  router.push('/checkout')
}

onMounted(loadCart)
</script>

<template>
  <div class="cart-page">
    <AppHeader />

    <main class="cart-main">
      <div class="container">
        <div class="page-head">
          <h1 class="page-title">
            <span class="title-badge">
              <el-icon :size="18"><ShoppingCart /></el-icon>
            </span>
            购物车
          </h1>
          <span v-if="items.length" class="count-badge">共 {{ totalCount }} 件</span>
        </div>

        <el-skeleton v-if="loading" :rows="5" animated class="cart-skeleton" />

        <template v-else-if="items.length === 0">
          <EmptyState description="购物车还是空的，去挑点喜欢的零食吧" />
          <div class="empty-actions">
            <button type="button" class="go-shopping-btn" @click="router.push('/products')">
              去逛逛
            </button>
          </div>
        </template>

        <template v-else>
          <div class="cart-toolbar">
            <el-checkbox
              :model-value="allSelected"
              :indeterminate="someSelected"
              @change="toggleAll"
            >
              全选
            </el-checkbox>

            <div class="toolbar-actions">
              <button type="button" class="text-btn danger" @click="removeSelected">
                删除选中
              </button>
              <span class="toolbar-divider" />
              <button type="button" class="text-btn" @click="clearCart">
                清空购物车
              </button>
            </div>
          </div>

          <div class="cart-list">
            <div
              v-for="item in items"
              :key="item.skuId"
              class="cart-item"
              :class="{ 'is-off': item.productStatus !== 1 }"
            >
              <el-checkbox
                :model-value="item.selected === 1"
                :disabled="item.productStatus !== 1"
                @change="(v: boolean | number | string) => toggleItem(item, v)"
              />

              <div class="item-image" @click="router.push(`/product/${item.productId}`)">
                <el-image
                  :src="item.productImage || item.skuImage"
                  fit="cover"
                  class="item-img"
                  lazy
                >
                  <template #error>
                    <div class="image-placeholder">🍪</div>
                  </template>
                </el-image>
              </div>

              <div class="item-info">
                <p class="item-name" @click="router.push(`/product/${item.productId}`)">
                  {{ item.productName }}
                </p>
                <p class="item-sku">{{ item.skuName }}</p>
                <span v-if="item.productStatus !== 1" class="off-tag">已下架</span>
                <span v-else-if="item.stock <= 10" class="stock-tag">仅剩 {{ item.stock }} 件</span>
              </div>

              <button
                type="button"
                class="item-delete"
                aria-label="删除商品"
                @click="deleteItem(item)"
              >
                <el-icon :size="18"><Delete /></el-icon>
              </button>

              <div class="item-bottom">
                <span class="item-price">单价 ¥{{ formatPrice(item.price) }}</span>

                <div class="item-qty">
                  <button
                    type="button"
                    class="qty-btn"
                    :disabled="item.productStatus !== 1 || updatingSkuId === item.skuId || item.quantity <= 1"
                    @click="changeQuantity(item, -1)"
                  >
                    <el-icon :size="14"><Minus /></el-icon>
                  </button>
                  <span class="qty-num">{{ item.quantity }}</span>
                  <button
                    type="button"
                    class="qty-btn"
                    :disabled="item.productStatus !== 1 || updatingSkuId === item.skuId"
                    @click="changeQuantity(item, 1)"
                  >
                    <el-icon :size="14"><Plus /></el-icon>
                  </button>
                </div>

                <span class="item-subtotal">¥{{ formatPrice(item.subtotal) }}</span>
              </div>
            </div>
          </div>

          <div class="cart-footer-bar">
            <div class="footer-left">
              <span class="summary-label">已选 {{ selectedCount }} 件</span>
              <span class="summary-amount">
                合计：
                <b>¥{{ formatPrice(selectedAmount) }}</b>
              </span>
            </div>

            <div class="footer-actions">
              <button type="button" class="remove-selected-btn" @click="removeSelected">
                删除选中
              </button>
              <button
                type="button"
                class="checkout-btn"
                :class="{ disabled: !canCheckout }"
                @click="goCheckout"
              >
                去结算
                <el-icon :size="16"><ArrowRight /></el-icon>
              </button>
            </div>
          </div>
        </template>
      </div>
    </main>

    <AppFooter />
  </div>
</template>

<style lang="scss" scoped>
.cart-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: $bg-page;
}

.cart-main {
  flex: 1;
  padding: 28px 0 48px;
}

.container {
  max-width: $container-max;
  margin: 0 auto;
  padding: 0 24px;
}

// ==================== 页头 ====================
.page-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 24px;
}

.page-title {
  margin: 0;
  font-family: 'Fredoka', 'PingFang SC', sans-serif;
  font-size: $font-size-xxl;
  font-weight: 700;
  color: $color-text-primary;
  display: flex;
  align-items: center;
  gap: 10px;

  .title-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 12px;
    background: $color-primary-light;
    color: $color-primary;
  }
}

.count-badge {
  padding: 5px 12px;
  border: 2px solid $color-border;
  border-radius: $radius-full;
  background: $bg-surface;
  color: $color-text-secondary;
  font-size: $font-size-sm;
  font-weight: 600;
}

// ==================== 加载与空状态 ====================
.cart-skeleton {
  padding: 20px;
  border: 2px solid $color-border;
  border-radius: $radius-lg;
  background: $bg-surface;
  box-shadow: $clay-shadow-sm;
}

.empty-actions {
  display: flex;
  justify-content: center;
  margin-top: -12px;
}

.go-shopping-btn {
  min-height: 44px;
  padding: 0 28px;
  border: 2px solid $color-border-dark;
  border-radius: $radius-full;
  background: linear-gradient(135deg, $color-primary, $color-cta);
  color: #fff;
  font-size: $font-size-md;
  font-weight: 600;
  box-shadow: 0 4px 0 0 $color-primary-dark;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s, filter 0.2s;

  &:hover {
    filter: brightness(1.04);
    transform: translateY(-1px);
  }

  &:active {
    box-shadow: 0 1px 0 0 $color-primary-dark;
    transform: translateY(3px);
  }
}

// ==================== 工具栏 ====================
.cart-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 20px;
  margin-bottom: 16px;
  background: $bg-surface;
  border: 2px solid $color-border;
  border-radius: $radius-lg;
  box-shadow: $clay-shadow-sm;

  :deep(.el-checkbox__label) {
    font-size: $font-size-md;
    font-weight: 600;
    color: $color-text-primary;
  }
}

.toolbar-actions {
  display: flex;
  align-items: center;
  gap: 14px;
}

.toolbar-divider {
  width: 1px;
  height: 18px;
  background: $color-border;
}

.text-btn {
  padding: 0;
  border: none;
  background: transparent;
  color: $color-text-secondary;
  font-size: $font-size-sm;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.2s;

  &:hover {
    color: $color-primary;
  }

  &.danger:hover {
    color: $color-danger;
  }
}

// ==================== 购物车列表 ====================
.cart-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.cart-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  padding: 18px;
  background: $bg-surface;
  border: 2px solid $color-border;
  border-radius: $radius-lg;
  box-shadow: $clay-shadow-sm;
  transition: opacity 0.2s, box-shadow 0.2s;

  &:hover {
    box-shadow: $clay-shadow-md;
  }

  &.is-off {
    opacity: 0.72;
    background: $bg-hover;
  }

  :deep(.el-checkbox) {
    flex-shrink: 0;
  }
}

.item-image {
  width: 96px;
  height: 96px;
  flex-shrink: 0;
  border: 2px solid $color-border;
  border-radius: $radius-md;
  overflow: hidden;
  background: $bg-page;
  cursor: pointer;

  .item-img {
    width: 100%;
    height: 100%;
  }

  .image-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 36px;
  }
}

.item-info {
  flex: 1;
  min-width: 180px;
}

.item-name {
  margin: 0 0 6px;
  font-size: $font-size-lg;
  font-weight: 600;
  color: $color-text-primary;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  cursor: pointer;
  transition: color 0.2s;

  &:hover {
    color: $color-primary;
  }
}

.item-sku {
  margin: 0;
  font-size: $font-size-sm;
  color: $color-text-secondary;
}

.off-tag,
.stock-tag {
  display: inline-block;
  margin-top: 8px;
  padding: 2px 10px;
  border-radius: $radius-full;
  font-size: $font-size-xs;
  font-weight: 700;
  line-height: 1.6;
}

.off-tag {
  background: $bg-hover;
  color: $color-text-secondary;
}

.stock-tag {
  background: #FEF3C7;
  color: $color-warning;
}

.item-delete {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border: 2px solid $color-border;
  border-radius: $radius-full;
  background: $bg-surface;
  color: $color-text-placeholder;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s, background-color 0.2s;

  &:hover {
    color: $color-danger;
    border-color: $color-danger;
    background: #FEF2F2;
  }
}

.item-bottom {
  flex: 0 0 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 28px;
  padding-left: 48px;
}

.item-price {
  font-size: $font-size-sm;
  color: $color-text-secondary;
}

.item-qty {
  display: flex;
  align-items: center;
  gap: 10px;
}

.qty-btn {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid $color-border;
  border-radius: $radius-full;
  background: $bg-page;
  color: $color-text-regular;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s, background-color 0.2s, opacity 0.2s;

  &:hover:not(:disabled) {
    color: $color-primary;
    border-color: $color-primary;
    background: $color-primary-light;
  }

  &:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }
}

.qty-num {
  min-width: 36px;
  text-align: center;
  font-size: $font-size-lg;
  font-weight: 700;
  color: $color-text-primary;
  font-family: 'Fredoka', sans-serif;
}

.item-subtotal {
  min-width: 90px;
  text-align: right;
  font-family: 'Fredoka', sans-serif;
  font-size: $font-size-lg;
  font-weight: 700;
  color: $color-primary;
}

// ==================== 底部结算栏 ====================
.cart-footer-bar {
  position: sticky;
  bottom: 16px;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 16px 20px;
  margin-top: 24px;
  background: $bg-surface;
  border: 2px solid $color-border;
  border-radius: $radius-lg;
  box-shadow: $clay-shadow-lg;
}

.footer-left {
  display: flex;
  align-items: baseline;
  gap: 18px;
  flex-wrap: wrap;
}

.summary-label {
  font-size: $font-size-sm;
  color: $color-text-secondary;
}

.summary-amount {
  font-size: $font-size-md;
  color: $color-text-primary;

  b {
    font-family: 'Fredoka', sans-serif;
    font-size: $font-size-xl;
    color: $color-primary;
  }
}

.footer-actions {
  display: flex;
  align-items: center;
  gap: 14px;
}

.remove-selected-btn {
  min-height: 40px;
  padding: 0 18px;
  border: 2px solid $color-border;
  border-radius: $radius-full;
  background: $bg-page;
  color: $color-text-regular;
  font-size: $font-size-sm;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s;

  &:hover {
    color: $color-danger;
    border-color: $color-danger;
  }
}

.checkout-btn {
  min-height: 44px;
  padding: 0 26px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 2px solid $color-border-dark;
  border-radius: $radius-full;
  background: linear-gradient(135deg, $color-primary, $color-cta);
  color: #fff;
  font-size: $font-size-md;
  font-weight: 600;
  box-shadow: 0 4px 0 0 $color-primary-dark;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s, filter 0.2s, opacity 0.2s;

  &:hover:not(.disabled) {
    filter: brightness(1.04);
    transform: translateY(-1px);
  }

  &:active:not(.disabled) {
    box-shadow: 0 1px 0 0 $color-primary-dark;
    transform: translateY(3px);
  }

  &.disabled {
    opacity: 0.55;
    cursor: not-allowed;
  }
}

// ==================== 响应式 ====================
@media (max-width: 640px) {
  .container {
    padding: 0 16px;
  }

  .page-title {
    font-size: $font-size-xl;
  }

  .cart-toolbar {
    padding: 12px 14px;
  }

  .cart-item {
    gap: 12px;
    padding: 14px;
  }

  .item-image {
    width: 72px;
    height: 72px;
  }

  .item-info {
    min-width: 0;
  }

  .item-name {
    font-size: $font-size-md;
  }

  .item-bottom {
    justify-content: space-between;
    gap: 12px;
    padding-left: 0;
  }

  .item-price {
    display: none;
  }

  .cart-footer-bar {
    padding: 14px;
  }

  .summary-label {
    display: none;
  }

  .footer-actions {
    width: 100%;
    justify-content: flex-end;
  }
}
</style>
