<script setup>
import { ref, computed } from "vue";
import { onLoad, onNavigationBarButtonTap, onReady } from "@dcloudio/uni-app";
import { getSpotDetail, deleteSpot } from "@/api/spot";
import { resolveImageUrl } from "@/utils/image";
import { checkLogin } from "@/utils/auth";
import { addFavorite, removeFavorite } from "@/api/favorite";
import { rateSpot } from "@/api/rating";
import { useUserStore } from "@/store/user";
import { submitCorrection } from "@/api/correction";
import CommentList from "@/components/comment-list/comment-list.vue";
import RatingStar from "@/components/rating-star/rating-star.vue";
import Skeleton from "@/components/skeleton/skeleton.vue";

const userStore = useUserStore();
const isOwner = computed(() =>
  spot.value?.creator?.id && userStore.userInfo?.id === spot.value.creator.id
);

const showCorrection = ref(false);
const showActionMenu = ref(false);
const correctionField = ref("");
const correctionValue = ref("");
const correctionReason = ref("");
const correctionSending = ref(false);

const fieldOptions = [
  { value: "title", label: "地点名称" },
  { value: "city", label: "所在城市" },
  { value: "description", label: "地点介绍" },
  { value: "transport", label: "交通方式" },
  { value: "best_time", label: "最佳拍摄时间" },
  { value: "difficulty", label: "路径难度" },
  { value: "price", label: "收费信息" },
];
const fieldIndex = ref(0);

const onFieldChange = (e) => {
  fieldIndex.value = e.detail.value;
  correctionField.value = fieldOptions[e.detail.value].value;
};

const openCorrection = () => {
  if (!checkLogin()) return;
  showActionMenu.value = false;
  correctionField.value = fieldOptions[0].value;
  fieldIndex.value = 0;
  correctionValue.value = "";
  correctionReason.value = "";
  showCorrection.value = true;
};

const closeCorrection = () => {
  showCorrection.value = false;
};

const handleSubmitCorrection = async () => {
  if (!correctionValue.value.trim()) {
    uni.showToast({ title: "请填写建议内容", icon: "none" });
    return;
  }
  correctionSending.value = true;
  try {
    await submitCorrection(spotId, {
      field_name: correctionField.value,
      suggested_value: correctionValue.value.trim(),
      reason: correctionReason.value.trim() || null,
    });
    uni.showToast({ title: "建议已提交", icon: "success" });
    closeCorrection();
  } catch (e) {
    console.error(e);
  } finally {
    correctionSending.value = false;
  }
};

const spot = ref(null);
const isFavorited = ref(false);
const loading = ref(true);
const favLoading = ref(false);
const showRating = ref(false);
const myRating = ref(0);
const ratingLoading = ref(false);

const statusMap = {
  pending: { text: "待审核", color: "#f59e0b" },
  approved: { text: "已通过", color: "#22c55e" },
  rejected: { text: "已拒绝", color: "#ef4444" },
};

const getStatusInfo = (status) =>
  statusMap[status] || { text: status, color: "#94a3b8" };

let spotId = null;

onLoad(async (query) => {
  if (!query.id) return;
  spotId = Number(query.id);
  try {
    const data = await getSpotDetail(query.id);
    spot.value = data;
    isFavorited.value = !!data.is_favorited;
  } catch (e) {
    console.error(e);
    uni.showToast({ title: "加载失败", icon: "none" });
  } finally {
    loading.value = false;
  }
});

onNavigationBarButtonTap(() => {
  toggleActionMenu();
});

const toggleFavorite = async () => {
  if (!checkLogin()) return;
  if (!spot.value || favLoading.value) return;
  favLoading.value = true;
  try {
    if (isFavorited.value) {
      await removeFavorite(spot.value.id);
      isFavorited.value = false;
      uni.showToast({ title: "已取消收藏", icon: "none" });
    } else {
      await addFavorite(spot.value.id);
      isFavorited.value = true;
      uni.showToast({ title: "已收藏", icon: "none" });
    }
  } catch (e) {
    console.error(e);
  } finally {
    favLoading.value = false;
  }
};

const previewImage = (idx) => {
  if (!spot.value?.images?.length) return;
  const urls = spot.value.images.map((img) => resolveImageUrl(img.image_url));
  uni.previewImage({ urls, current: urls[idx] || urls[0] });
};

const openNavigation = () => {
  if (!spot.value) return;
  const lat = spot.value.latitude;
  const lng = spot.value.longitude;
  if (lat == null || lng == null) {
    uni.showToast({ title: "暂无坐标信息", icon: "none" });
    return;
  }
  uni.openLocation({
    latitude: lat,
    longitude: lng,
    name: spot.value.title,
    address: spot.value.city || "",
  });
};

const shareSpot = () => {
  if (!spot.value) return;
  showActionMenu.value = false;
  // #ifdef H5
  if (navigator.clipboard) {
    const url = window.location.href;
    navigator.clipboard.writeText(`${spot.value.title} - ${url}`);
    uni.showToast({ title: "链接已复制", icon: "success" });
    return;
  }
  // #endif
  // #ifndef H5
  uni.share?.({
    title: spot.value.title,
    summary: spot.value.description || "来次元取景器看看这个取景地吧",
    type: 0,
    fail: () => {
      uni.setClipboardData({
        data: `${spot.value.title} - 次元取景器推荐取景地`,
        success: () => uni.showToast({ title: "已复制到剪贴板", icon: "success" }),
      });
    },
  });
  // #endif
};

const toggleActionMenu = () => {
  showActionMenu.value = !showActionMenu.value;
};

const closeActionMenu = () => {
  showActionMenu.value = false;
};

const goUser = (userId) => {
  if (userId) uni.navigateTo({ url: `/pages/user/index?id=${userId}` });
};

const goEdit = () => {
  if (spotId) uni.navigateTo({ url: `/pages/spot/edit?id=${spotId}` });
};

const handleDeleteSpot = () => {
  uni.showModal({
    title: "确认删除",
    content: `确定要删除「${spot.value.title}」吗？此操作不可撤销。`,
    confirmColor: "#ef4444",
    success: async (res) => {
      if (res.confirm) {
        try {
          await deleteSpot(spotId);
          uni.showToast({ title: "已删除", icon: "success" });
          setTimeout(() => uni.navigateBack(), 800);
        } catch (e) {
          console.error(e);
        }
      }
    },
  });
};

const submitRating = async (val) => {
  if (!checkLogin()) return;
  if (ratingLoading.value) return;
  myRating.value = val;
  ratingLoading.value = true;
  try {
    await rateSpot(spot.value.id, { score: val });
    uni.showToast({ title: "评分成功", icon: "none" });
    const data = await getSpotDetail(spot.value.id);
    spot.value = data;
    showRating.value = false;
  } catch (e) {
    console.error(e);
  } finally {
    ratingLoading.value = false;
  }
};
</script>

<template>
  <view class="detail-page">
    <view v-if="showActionMenu" class="menu-mask" @tap="closeActionMenu">
      <view class="action-menu" @tap.stop>
        <view class="menu-item" @tap="shareSpot">
          <uni-icons type="redo" size="16" color="#22c55e" />
          <text class="menu-text share-text">分享</text>
        </view>
        <view v-if="!isOwner" class="menu-item" @tap="openCorrection">
          <uni-icons type="compose" size="16" color="#f59e0b" />
          <text class="menu-text correct-text">校正</text>
        </view>
      </view>
    </view>

    <view v-if="loading" class="loading-state">
      <view class="sk-cover shimmer" />
      <Skeleton :rows="2" card />
      <Skeleton :rows="4" card />
      <Skeleton avatar :rows="1" card />
    </view>

    <view v-else-if="spot" class="content">
      <swiper
        v-if="spot.images && spot.images.length"
        class="image-swiper"
        indicator-dots
        autoplay
        circular
        indicator-active-color="#6366f1"
      >
        <swiper-item v-for="(img, idx) in spot.images" :key="idx" @tap="previewImage(idx)">
          <image class="swiper-image" :src="resolveImageUrl(img.image_url)" mode="aspectFill" />
        </swiper-item>
      </swiper>
      <view v-else class="image-placeholder">
        <uni-icons type="image" size="48" color="#6366f1" class="placeholder-icon" />
        <text class="placeholder-text">暂无图片</text>
      </view>

      <view class="info-section">
        <view class="title-row">
          <text class="title">{{ spot.title }}</text>
          <view
            class="status-badge"
            :style="{ background: getStatusInfo(spot.audit_status).color }"
          >
            <text class="status-text">{{
              getStatusInfo(spot.audit_status).text
            }}</text>
          </view>
        </view>
        <view class="city-row">
          <view class="city-info">
            <uni-icons type="location" size="16" color="#6366f1" class="city-icon" />
            <text class="city">{{ spot.city }}</text>
          </view>
          <view class="inline-action nav-inline" @tap="openNavigation">
            <uni-icons type="navigate-filled" size="16" color="#3b82f6" />
            <text class="inline-action-text nav-text">导航</text>
          </view>
        </view>

        <view v-if="spot.tags && spot.tags.length" class="tags-row">
          <view v-for="tag in spot.tags" :key="tag.id" class="detail-tag">
            <text class="detail-tag-text">{{ tag.name }}</text>
          </view>
        </view>

        <view class="price-row">
          <uni-icons :type="spot.is_free ? 'checkbox-filled' : 'shop'" size="16" :color="spot.is_free ? '#22c55e' : '#f59e0b'" />
          <text v-if="spot.is_free" class="price-free">免费</text>
          <text v-else class="price-paid">
            {{ spot.price_min != null && spot.price_max != null && spot.price_min !== spot.price_max
              ? `¥${spot.price_min} ~ ¥${spot.price_max}`
              : `¥${spot.price_min || spot.price_max || '-'}` }}
          </text>
        </view>

        <view class="rating-row">
          <RatingStar :value="Math.round(spot.avg_rating || 0)" :readonly="true" size="32rpx" />
          <text class="rating-num">{{ (spot.avg_rating || 0).toFixed(1) }}</text>
          <text class="rating-count">（{{ spot.rating_count || 0 }}人评分）</text>
          <view class="rate-action" @tap="showRating = !showRating">
            <text class="rate-action-text">{{ showRating ? "取消" : "我要评分" }}</text>
          </view>
        </view>

        <view v-if="showRating" class="my-rating-box">
          <text class="my-rating-label">点击星星评分：</text>
          <RatingStar :value="myRating" size="48rpx" @update:value="submitRating" />
        </view>

        <view class="action-grid">
          <template v-if="isOwner">
            <view class="action-chip edit-chip" @tap="goEdit">
              <uni-icons type="compose" size="18" color="#6366f1" />
              <text class="action-chip-text edit-text">编辑</text>
            </view>
            <view class="action-chip delete-chip" @tap="handleDeleteSpot">
              <uni-icons type="trash" size="18" color="#ef4444" />
              <text class="action-chip-text delete-text">删除</text>
            </view>
          </template>
        </view>
      </view>

      <view v-if="spot.description" class="section">
        <text class="section-label">地点介绍</text>
        <text class="section-content">{{ spot.description }}</text>
      </view>

      <view v-if="spot.transport" class="section">
        <view class="section-label"><uni-icons type="car" size="16" color="#1e293b" /> 交通方式</view>
        <text class="section-content">{{ spot.transport }}</text>
      </view>

      <view v-if="spot.best_time" class="section">
        <view class="section-label"><uni-icons type="calendar" size="16" color="#1e293b" /> 最佳拍摄时间</view>
        <text class="section-content">{{ spot.best_time }}</text>
      </view>

      <view v-if="spot.difficulty" class="section">
        <view class="section-label"><uni-icons type="flag" size="16" color="#1e293b" /> 路径难度说明</view>
        <text class="section-content">{{ spot.difficulty }}</text>
      </view>

      <view v-if="spot.creator" class="creator-section">
        <view class="creator-card" @tap="goUser(spot.creator.id)">
          <image
            v-if="spot.creator.avatar_url"
            class="creator-avatar"
            :src="resolveImageUrl(spot.creator.avatar_url)"
            mode="aspectFill"
          />
          <view v-else class="creator-avatar creator-avatar-default">
            <uni-icons type="person" size="20" color="#6366f1" />
          </view>
          <view class="creator-info">
            <text class="creator-name">{{ spot.creator.nickname || "匿名用户" }}</text>
            <view class="creator-meta">
              <text class="creator-label">投稿者</text>
              <text v-if="spot.creator.city" class="creator-city">{{ spot.creator.city }}</text>
            </view>
          </view>
          <view class="creator-arrow">
            <uni-icons type="right" size="16" color="#cbd5e1" />
          </view>
        </view>
      </view>

      <CommentList
        v-if="spotId"
        :spot-id="spotId"
        :is-favorited="isFavorited"
        @toggle-favorite="toggleFavorite"
      />

      <!-- 校正建议弹窗 -->
      <view v-if="showCorrection" class="correction-mask" @tap.self="closeCorrection">
        <view class="correction-popup">
          <text class="correction-title">提交校正建议</text>

          <view class="correction-field">
            <text class="correction-label">校正字段</text>
            <picker :value="fieldIndex" :range="fieldOptions" range-key="label" @change="onFieldChange">
              <view class="correction-picker">
                <text>{{ fieldOptions[fieldIndex].label }}</text>
                <uni-icons type="arrowdown" size="14" color="#94a3b8" />
              </view>
            </picker>
          </view>

          <view class="correction-field">
            <text class="correction-label">建议内容 *</text>
            <textarea
              v-model="correctionValue"
              class="correction-textarea"
              placeholder="请输入正确的信息"
              maxlength="500"
            />
          </view>

          <view class="correction-field">
            <text class="correction-label">理由说明</text>
            <textarea
              v-model="correctionReason"
              class="correction-textarea correction-textarea-sm"
              placeholder="简要说明校正原因（可选）"
              maxlength="200"
            />
          </view>

          <view class="correction-actions">
            <view class="correction-cancel" @tap="closeCorrection">
              <text>取消</text>
            </view>
            <view
              class="correction-submit"
              :class="{ disabled: correctionSending }"
              @tap="handleSubmitCorrection"
            >
              <text class="correction-submit-text">{{ correctionSending ? "提交中..." : "提交" }}</text>
            </view>
          </view>
        </view>
      </view>
    </view>

    <view v-else class="error-state">
      <text>加载失败，请返回重试</text>
    </view>
  </view>
</template>

<style scoped>
.detail-page {
  min-height: 100vh;
  background: #f5f6fa;
  padding-bottom: 280rpx;
}

.loading-state {
  padding-top: 0;
}
.sk-cover {
  width: 100%;
  height: 480rpx;
  background: #e2e8f0;
}
.shimmer {
  background: linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.error-state {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60vh;
  color: #94a3b8;
  font-size: 28rpx;
}

.menu-mask {
  position: fixed;
  inset: 0;
  z-index: 120;
}

.action-menu {
  position: absolute;
  top: calc(88rpx + env(safe-area-inset-top));
  right: 24rpx;
  min-width: 180rpx;
  background: #ffffff;
  border-radius: 16rpx;
  box-shadow: 0 10rpx 30rpx rgba(15, 23, 42, 0.16);
  overflow: hidden;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 10rpx;
  padding: 22rpx 24rpx;
}

.menu-item + .menu-item {
  border-top: 1rpx solid #f1f5f9;
}

.menu-text {
  font-size: 26rpx;
  color: #1e293b;
  font-weight: 500;
}

:global(uni-page-head .detail-nav-menu-btn) {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  line-height: 1;
}

:global(uni-page-head .detail-nav-menu-btn .uni-page-head-btn-text) {
  width: 0;
  opacity: 0;
  overflow: hidden;
}

:global(uni-page-head .detail-nav-menu-btn::before) {
  content: "";
  display: block;
  width: 20px;
  height: 20px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 20px 20px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='4' cy='10' r='1.8' fill='%231e293b'/%3E%3Ccircle cx='10' cy='10' r='1.8' fill='%231e293b'/%3E%3Ccircle cx='16' cy='10' r='1.8' fill='%231e293b'/%3E%3C/svg%3E");
}

.image-swiper {
  width: 100%;
  height: 480rpx;
}

.swiper-image {
  width: 100%;
  height: 100%;
}

.image-placeholder {
  width: 100%;
  height: 480rpx;
  background: linear-gradient(135deg, #e0e7ff, #c7d2fe);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.placeholder-icon {
  font-size: 96rpx;
  margin-bottom: 12rpx;
}

.placeholder-text {
  font-size: 28rpx;
  color: #6366f1;
}

.info-section {
  background: #ffffff;
  padding: 32rpx;
  margin-bottom: 16rpx;
}

.title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16rpx;
}

.title {
  font-size: 38rpx;
  font-weight: 700;
  color: #1e293b;
  flex: 1;
  margin-right: 16rpx;
}

.status-badge {
  padding: 6rpx 16rpx;
  border-radius: 8rpx;
  flex-shrink: 0;
}

.status-text {
  font-size: 22rpx;
  color: #ffffff;
  font-weight: 500;
}

.city-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16rpx;
}

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

.city-icon {
  font-size: 28rpx;
  margin-right: 8rpx;
}

.city {
  font-size: 28rpx;
  color: #64748b;
  min-width: 0;
}

.inline-action {
  display: flex;
  align-items: center;
  gap: 6rpx;
  padding: 10rpx 18rpx;
  border-radius: 999rpx;
  flex-shrink: 0;
}

.nav-inline {
  background: rgba(59, 130, 246, 0.1);
}

.inline-action-text {
  font-size: 24rpx;
  font-weight: 600;
}

.tags-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12rpx;
  margin-top: 16rpx;
}

.detail-tag {
  background: rgba(99, 102, 241, 0.1);
  padding: 6rpx 20rpx;
  border-radius: 20rpx;
}

.detail-tag-text {
  font-size: 24rpx;
  color: #6366f1;
}

.price-row {
  display: flex;
  align-items: center;
  gap: 8rpx;
  margin-top: 16rpx;
}

.price-free {
  font-size: 28rpx;
  color: #22c55e;
  font-weight: 600;
}

.price-paid {
  font-size: 28rpx;
  color: #f59e0b;
  font-weight: 600;
}

.rating-row {
  display: flex;
  align-items: center;
  margin-top: 20rpx;
}

.rating-num {
  font-size: 28rpx;
  font-weight: 700;
  color: #f59e0b;
  margin-left: 12rpx;
}

.rating-count {
  font-size: 24rpx;
  color: #94a3b8;
  margin-left: 4rpx;
}

.rate-action {
  margin-left: auto;
  padding: 8rpx 24rpx;
  background: #6366f1;
  border-radius: 24rpx;
}

.rate-action-text {
  font-size: 24rpx;
  color: #ffffff;
  font-weight: 500;
}

.my-rating-box {
  background: #f5f6fa;
  border-radius: 12rpx;
  padding: 24rpx;
  margin-top: 20rpx;
  display: flex;
  align-items: center;
}

.my-rating-label {
  font-size: 26rpx;
  color: #475569;
  margin-right: 16rpx;
}

.action-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx;
  margin-top: 24rpx;
}

.action-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8rpx;
  min-width: 160rpx;
  height: 76rpx;
  padding: 0 24rpx;
  border-radius: 999rpx;
  background: #f5f6fa;
}

.action-chip.active {
  background: rgba(99, 102, 241, 0.1);
}

.action-chip-text {
  font-size: 26rpx;
  color: #475569;
  font-weight: 500;
}

.action-chip-text.active {
  color: #6366f1;
}

.section {
  background: #ffffff;
  padding: 32rpx;
  margin-bottom: 16rpx;
}

.section-label {
  font-size: 30rpx;
  font-weight: 600;
  color: #1e293b;
  display: block;
  margin-bottom: 16rpx;
}

.section-content {
  font-size: 28rpx;
  color: #475569;
  line-height: 1.7;
  display: block;
}

.creator-section {
  padding: 0 32rpx;
  margin-bottom: 32rpx;
}

.creator-card {
  background: #ffffff;
  border-radius: 16rpx;
  padding: 24rpx;
  display: flex;
  align-items: center;
}

.creator-avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 40rpx;
  flex-shrink: 0;
  margin-right: 20rpx;
}

.creator-avatar-default {
  background: #e0e7ff;
  display: flex;
  align-items: center;
  justify-content: center;
}

.creator-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.creator-name {
  font-size: 28rpx;
  font-weight: 600;
  color: #1e293b;
  margin-bottom: 4rpx;
}

.creator-meta {
  display: flex;
  align-items: center;
  gap: 12rpx;
}

.creator-label {
  font-size: 22rpx;
  color: #94a3b8;
}

.creator-city {
  font-size: 22rpx;
  color: #6366f1;
}

.creator-arrow {
  flex-shrink: 0;
  margin-left: 8rpx;
}

.correct-text {
  color: #f59e0b;
}

.nav-chip {
  background: rgba(59, 130, 246, 0.1);
}
.nav-text {
  color: #3b82f6;
}

.share-chip {
  background: rgba(34, 197, 94, 0.1);
}
.share-text {
  color: #22c55e;
}

.correct-chip {
  background: rgba(245, 158, 11, 0.1);
}

.edit-chip {
  background: rgba(99, 102, 241, 0.1);
}

.edit-text {
  color: #6366f1;
}

.delete-chip {
  background: rgba(239, 68, 68, 0.1);
}

.delete-text {
  color: #ef4444;
}

.correction-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
}

.correction-popup {
  width: 640rpx;
  background: #ffffff;
  border-radius: 20rpx;
  padding: 40rpx;
  max-height: 80vh;
  overflow-y: auto;
}

.correction-title {
  font-size: 32rpx;
  font-weight: 700;
  color: #1e293b;
  display: block;
  text-align: center;
  margin-bottom: 32rpx;
}

.correction-field {
  margin-bottom: 24rpx;
}

.correction-label {
  font-size: 26rpx;
  color: #64748b;
  font-weight: 500;
  display: block;
  margin-bottom: 12rpx;
}

.correction-picker {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 80rpx;
  background: #f5f6fa;
  border-radius: 12rpx;
  padding: 0 24rpx;
  font-size: 28rpx;
  color: #1e293b;
}

.correction-textarea {
  width: 100%;
  height: 160rpx;
  background: #f5f6fa;
  border-radius: 12rpx;
  padding: 20rpx;
  font-size: 28rpx;
  color: #334155;
  box-sizing: border-box;
}

.correction-textarea-sm {
  height: 100rpx;
}

.correction-actions {
  display: flex;
  margin-top: 32rpx;
  gap: 20rpx;
}

.correction-cancel {
  flex: 1;
  height: 80rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f6fa;
  border-radius: 12rpx;
  font-size: 28rpx;
  color: #64748b;
}

.correction-submit {
  flex: 1;
  height: 80rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #6366f1;
  border-radius: 12rpx;
}

.correction-submit.disabled {
  opacity: 0.6;
}

.correction-submit-text {
  font-size: 28rpx;
  color: #ffffff;
  font-weight: 500;
}
</style>
