<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { Delete, ShoppingCart } from '@element-plus/icons-vue'
import { createMohongOrder, startMohongPayment } from '@/features/mohong/api/mohong'
import { useMohongCart } from '@/features/mohong/composables/useMohongCart'
import type { PaymentPayWay } from '@/features/orders/api/orders'
import { useSessionStore } from '@/stores/session'
import { formatCent } from '@/shared/utils/money'
import { readError } from '@/shared/utils/error'

const props = withDefaults(
  defineProps<{
    mobile?: boolean
    selectPayWay: () => Promise<PaymentPayWay | null>
    startCashier: (
      payment: Awaited<ReturnType<typeof startMohongPayment>>,
      onPaid: () => void | Promise<void>
    ) => Promise<void>
  }>(),
  { mobile: false }
)

const router = useRouter()
const session = useSessionStore()
const {
  lines,
  drawerOpen,
  totalCount,
  totalAmountCent,
  isEmpty,
  closeCart,
  setQuantity,
  removeLine,
  clearCart,
  checkoutItems,
} = useMohongCart()
const checkingOut = ref(false)

async function ensureAuthReady() {
  const loginPath = props.mobile ? '/m/login' : '/login'
  const realnamePath = props.mobile ? '/m/realname' : '/realname'
  if (!session.isLoggedIn) {
    router.push({ path: loginPath, query: { redirect: router.currentRoute.value.fullPath } })
    return false
  }
  try {
    await session.loadMe()
  } catch {
    // ignore
  }
  if (session.realnameStatus !== 'verified') {
    router.push({ path: realnamePath, query: { redirect: router.currentRoute.value.fullPath } })
    return false
  }
  return true
}

async function handleCheckout() {
  if (isEmpty.value || checkingOut.value) return
  if (!(await ensureAuthReady())) return
  const payWay = await props.selectPayWay()
  if (!payWay) return

  checkingOut.value = true
  try {
    const order = await createMohongOrder(checkoutItems())
    clearCart()
    closeCart()
    const payment = await startMohongPayment(order.id, payWay)
    const orderPath = props.mobile ? `/m/mohong/orders/${order.id}` : `/mohong/orders/${order.id}`
    if (payment.paid || payment.status === 'paid') {
      ElMessage.success('支付成功')
      await router.push(orderPath)
      return
    }
    await props.startCashier(payment, async () => {
      await router.push(orderPath)
    })
  } catch (error) {
    ElMessage.error(readError(error, '结账失败'))
  } finally {
    checkingOut.value = false
  }
}
</script>

<template>
  <el-drawer
    v-if="!mobile"
    v-model="drawerOpen"
    title="购物车"
    size="420px"
    append-to-body
  >
    <div v-if="isEmpty" class="empty">
      <el-icon :size="36"><ShoppingCart /></el-icon>
      <p>还没有选购商品</p>
      <el-button type="primary" color="#ff6a00" @click="closeCart">去选购</el-button>
    </div>
    <template v-else>
      <div class="cart-list">
        <div v-for="line in lines" :key="line.product_id" class="cart-line">
          <div class="cover">
            <img v-if="line.cover_url" :src="line.cover_url" :alt="line.title" />
            <span v-else>{{ line.title.slice(0, 1) }}</span>
          </div>
          <div class="info">
            <strong>{{ line.title }}</strong>
            <p>¥{{ line.price || formatCent(line.price_cent) }} / {{ line.unit }}</p>
            <div class="line-actions">
              <el-input-number
                :model-value="line.quantity"
                :min="1"
                :max="line.stock > 0 ? line.stock : 99"
                size="small"
                @update:model-value="(v: number | undefined) => setQuantity(line.product_id, Number(v || 1))"
              />
              <el-button text type="danger" :icon="Delete" @click="removeLine(line.product_id)" />
            </div>
          </div>
          <div class="line-amount">¥{{ formatCent(line.price_cent * line.quantity) }}</div>
        </div>
      </div>
      <div class="cart-footer">
        <div>
          共 {{ totalCount }} 件
          <strong>¥{{ formatCent(totalAmountCent) }}</strong>
        </div>
        <el-button type="primary" color="#ff6a00" :loading="checkingOut" @click="handleCheckout">
          一起结账
        </el-button>
      </div>
    </template>
  </el-drawer>

  <van-popup
    v-else
    v-model:show="drawerOpen"
    position="bottom"
    round
    :style="{ maxHeight: '78vh' }"
  >
    <div class="m-cart">
      <header class="m-head">
        <h3>购物车</h3>
        <button type="button" @click="closeCart">关闭</button>
      </header>
      <div v-if="isEmpty" class="empty">
        <p>还没有选购商品</p>
      </div>
      <div v-else class="m-list">
        <div v-for="line in lines" :key="line.product_id" class="m-line">
          <div class="cover">
            <img v-if="line.cover_url" :src="line.cover_url" :alt="line.title" />
            <span v-else>{{ line.title.slice(0, 1) }}</span>
          </div>
          <div class="info">
            <strong>{{ line.title }}</strong>
            <p>¥{{ line.price || formatCent(line.price_cent) }}</p>
            <div class="line-actions">
              <van-stepper
                :model-value="line.quantity"
                :min="1"
                :max="line.stock > 0 ? line.stock : 99"
                @change="(v: number) => setQuantity(line.product_id, Number(v || 1))"
              />
              <button type="button" class="rm" @click="removeLine(line.product_id)">删除</button>
            </div>
          </div>
        </div>
      </div>
      <footer v-if="!isEmpty" class="m-footer">
        <div>
          共{{ totalCount }}件
          <strong>¥{{ formatCent(totalAmountCent) }}</strong>
        </div>
        <van-button
          type="primary"
          color="#ff6a00"
          round
          :loading="checkingOut"
          @click="handleCheckout"
        >
          一起结账
        </van-button>
      </footer>
    </div>
  </van-popup>
</template>

<style scoped>
.empty {
  display: grid;
  gap: 12px;
  place-items: center;
  padding: 48px 16px;
  color: #94a3b8;
}
.cart-list {
  display: grid;
  gap: 12px;
  padding-bottom: 80px;
}
.cart-line {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: start;
}
.cover {
  width: 64px;
  height: 64px;
  border-radius: 10px;
  overflow: hidden;
  background: #f1f5f9;
  display: grid;
  place-items: center;
}
.cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.info strong {
  display: block;
  font-size: 14px;
  color: #0f172a;
}
.info p {
  margin: 4px 0 8px;
  color: #94a3b8;
  font-size: 12px;
}
.line-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}
.line-amount {
  color: #ff6a00;
  font-weight: 700;
  font-size: 14px;
  white-space: nowrap;
}
.cart-footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-top: 1px solid #eef1f5;
  background: #fff;
}
.cart-footer strong {
  margin-left: 8px;
  color: #ff6a00;
  font-size: 18px;
}
.m-cart {
  display: flex;
  flex-direction: column;
  max-height: 78vh;
}
.m-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid #eef1f5;
}
.m-head h3 {
  margin: 0;
  font-size: 16px;
}
.m-head button {
  border: 0;
  background: none;
  color: #64748b;
}
.m-list {
  overflow-y: auto;
  padding: 12px 16px;
  flex: 1;
}
.m-line {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid #f1f5f9;
}
.rm {
  border: 0;
  background: none;
  color: #ef4444;
  font-size: 12px;
}
.m-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid #eef1f5;
}
.m-footer strong {
  margin-left: 6px;
  color: #ff6a00;
  font-size: 18px;
}
</style>
