<script setup>
import { ref } from "vue";
import { useRouter } from "vue-router";
import axios from "axios";
import {
  GRS_API_KEY,
  ESSAY_API_URL,
  ESSAY_PROMPT,
  IMAGE_MAX_SIZE_MB,
  IMAGE_ALLOWED_TYPES_ESSAY,
} from "@/config/index.js";
import demoZuowen from "@/assets/demo/zuowen.jpg";

const API_KEY = GRS_API_KEY;
const API_URL = ESSAY_API_URL;
const PROMPT = ESSAY_PROMPT;

const router = useRouter();

// state: idle | processing | done | error
const status = ref("idle");
const originalImage = ref(null); // data URL for preview
const originalBase64 = ref(""); // pure base64 string
const resultImage = ref(""); // corrected image URL
const errorMsg = ref("");
const isDragOver = ref(false);
const fileInputRef = ref(null);
const lightboxSrc = ref("");
const lightboxVisible = ref(false);

const goBack = () => router.back();

const readFileAsBase64 = (file) =>
  new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const dataUrl = e.target.result;
      resolve({ dataUrl, base64: dataUrl.split(",")[1] });
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });

const handleFile = async (file) => {
  if (!file) return;
  const allowed = IMAGE_ALLOWED_TYPES_ESSAY;
  if (!allowed.includes(file.type)) {
    errorMsg.value = "仅支持 JPG / PNG 格式的图片";
    return;
  }
  if (file.size > IMAGE_MAX_SIZE_MB * 1024 * 1024) {
    errorMsg.value = `图片大小不能超过 ${IMAGE_MAX_SIZE_MB}MB`;
    return;
  }
  errorMsg.value = "";
  resultImage.value = "";
  status.value = "idle";
  const { dataUrl, base64 } = await readFileAsBase64(file);
  originalImage.value = dataUrl;
  originalBase64.value = base64;
};

const onFileChange = (e) => handleFile(e.target.files[0]);

const onDrop = (e) => {
  isDragOver.value = false;
  handleFile(e.dataTransfer.files[0]);
};

const resetUpload = () => {
  originalImage.value = null;
  originalBase64.value = "";
  resultImage.value = "";
  errorMsg.value = "";
  status.value = "idle";
  if (fileInputRef.value) fileInputRef.value.value = "";
};

const loadDemoImage = async () => {
  const response = await fetch(demoZuowen);
  const blob = await response.blob();
  const file = new File([blob], "zuowen.jpg", { type: "image/jpeg" });
  await handleFile(file);
};

const startCorrection = async () => {
  if (!originalBase64.value || status.value === "processing") return;
  status.value = "processing";
  errorMsg.value = "";
  resultImage.value = "";

  const res = await axios
    .post(
      API_URL,
      {
        model: "nano-banana-pro",
        prompt: PROMPT,
        aspectRatio: "auto",
        imageSize: "1K",
        urls: [originalBase64.value],
        webHook: "",
        shutProgress: true,
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${API_KEY}`,
        },
      }
    )
    .catch((err) => {
      console.error(err);
      errorMsg.value =
        err?.response?.data?.message || err.message || "请求失败，请稍后重试";
      status.value = "error";
      return null;
    });

  if (!res) return;

  // 接口返回 SSE 格式文本，形如 "data: {...}\n\n"，需去掉 "data: " 前缀再解析
  let data;
  try {
    const raw =
      typeof res.data === "string" ? res.data : JSON.stringify(res.data);
    const jsonStr = raw.replace(/^data:\s*/m, "").trim();
    data = JSON.parse(jsonStr);
  } catch {
    data = res.data;
  }

  // 根据实际返回格式解析：{ results: [{ url, content }], progress, status }
  if (data?.status && data.status !== "succeeded") {
    errorMsg.value = `批改失败：${
      data.failure_reason || data.error || data.status
    }`;
    status.value = "error";
    return;
  }

  const imgUrl =
    (Array.isArray(data?.results) && data.results[0]?.url) || data?.url || null;

  if (imgUrl) {
    resultImage.value = imgUrl;
    status.value = "done";
  } else {
    console.error("未能解析到图片地址", data);
    errorMsg.value = "批改完成，但未能获取结果图片，请检查 API 返回格式";
    status.value = "error";
  }
};

const openLightbox = (src) => {
  lightboxSrc.value = src;
  lightboxVisible.value = true;
};
const closeLightbox = () => {
  lightboxVisible.value = false;
};
</script>

<template>
  <div class="page-container">
    <!-- Nav Bar -->
    <div class="nav-bar">
      <button class="back-btn" @click="goBack">
        <svg
          width="20"
          height="20"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2.2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <polyline points="15 18 9 12 15 6" />
        </svg>
        <span>返回</span>
      </button>
      <h1 class="nav-title">AI 作文原图批改</h1>
      <div style="width: 72px"></div>
    </div>

    <div class="content">
      <!-- Error Banner -->
      <div v-if="errorMsg" class="error-banner">
        <span>{{ errorMsg }}</span>
        <button class="error-close" @click="errorMsg = ''">✕</button>
      </div>

      <!-- Upload Zone -->
      <div
        v-if="!originalImage"
        class="upload-zone"
        :class="{ 'drag-over': isDragOver }"
        @click="fileInputRef.click()"
        @dragover.prevent="isDragOver = true"
        @dragleave.prevent="isDragOver = false"
        @drop.prevent="onDrop"
      >
        <input
          ref="fileInputRef"
          type="file"
          accept="image/jpeg,image/jpg,image/png"
          style="display: none"
          @change="onFileChange"
        />
        <div class="upload-icon">
          <svg
            width="48"
            height="48"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="1.5"
            stroke-linecap="round"
            stroke-linejoin="round"
          >
            <rect x="3" y="3" width="18" height="18" rx="3" />
            <circle cx="8.5" cy="8.5" r="1.5" />
            <polyline points="21 15 16 10 5 21" />
          </svg>
        </div>
        <p class="upload-title">点击或拖拽上传作文图片</p>
        <p class="upload-hint">支持 JPG、PNG 格式，最大 10MB</p>
        <button class="demo-btn" @click.stop="loadDemoImage">示例作文</button>
      </div>

      <!-- Preview + Action -->
      <div v-else class="preview-section">
        <div class="preview-card">
          <div class="preview-header">
            <span class="preview-label">原始图片</span>
            <button
              class="reupload-btn"
              @click="resetUpload"
              :disabled="status === 'processing'"
            >
              重新上传
            </button>
          </div>
          <img
            :src="originalImage"
            class="preview-img"
            @click="openLightbox(originalImage)"
          />
        </div>

        <button
          class="correct-btn"
          :disabled="status === 'processing'"
          @click="startCorrection"
        >
          <span v-if="status === 'processing'" class="btn-spinner"></span>
          <svg
            v-else
            width="20"
            height="20"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          >
            <path d="M12 20h9" />
            <path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" />
          </svg>
          <span>{{ status === "processing" ? "批改中..." : "开始批改" }}</span>
        </button>
      </div>

      <!-- Result -->
      <div v-if="status === 'done' && resultImage" class="result-section">
        <div class="compare-grid">
          <div class="compare-card">
            <div class="compare-label">原图</div>
            <img
              :src="originalImage"
              class="compare-img"
              @click="openLightbox(originalImage)"
            />
          </div>
          <div class="compare-card result-card">
            <div class="compare-label result-label">批改结果</div>
            <img
              :src="resultImage"
              class="compare-img"
              @click="openLightbox(resultImage)"
            />
          </div>
        </div>
        <p class="click-hint">点击图片可放大查看</p>
      </div>
    </div>

    <!-- Lightbox -->
    <div v-if="lightboxVisible" class="lightbox" @click="closeLightbox">
      <img :src="lightboxSrc" class="lightbox-img" @click.stop />
      <button class="lightbox-close" @click="closeLightbox">✕</button>
    </div>
  </div>
</template>

<style scoped>
.page-container {
  min-height: 100vh;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  font-family: "PingFang SC", -apple-system, sans-serif;
}

/* Nav */
.nav-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.5rem;
  background: rgba(255, 255, 255, 0.03);
  border-bottom: 1px solid var(--card-border);
  backdrop-filter: blur(12px);
  position: sticky;
  top: 0;
  z-index: 10;
}
.back-btn {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  background: none;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 0.95rem;
  padding: 0.4rem 0.75rem;
  border-radius: 8px;
  transition: all 0.2s;
}
.back-btn:hover {
  background: rgba(255, 255, 255, 0.07);
  color: var(--text-primary);
}
.nav-title {
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
  background: linear-gradient(135deg, #ec4899, #db2777);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* Content */
.content {
  flex: 1;
  max-width: 860px;
  width: 100%;
  margin: 0 auto;
  padding: 2rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* Error */
.error-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(239, 68, 68, 0.12);
  border: 1px solid rgba(239, 68, 68, 0.3);
  border-radius: 12px;
  padding: 0.875rem 1.25rem;
  color: #fca5a5;
  font-size: 0.95rem;
  animation: fadeIn 0.2s ease;
}
.error-close {
  background: none;
  border: none;
  color: #fca5a5;
  cursor: pointer;
  font-size: 1rem;
  padding: 0 0.25rem;
  opacity: 0.7;
  transition: opacity 0.2s;
}
.error-close:hover {
  opacity: 1;
}

/* Upload Zone */
.upload-zone {
  border: 2px dashed rgba(236, 72, 153, 0.3);
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.02);
  padding: 4rem 2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  cursor: pointer;
  transition: all 0.25s;
  text-align: center;
}
.upload-zone:hover,
.upload-zone.drag-over {
  border-color: #ec4899;
  background: rgba(236, 72, 153, 0.06);
  transform: translateY(-2px);
  box-shadow: 0 8px 32px rgba(236, 72, 153, 0.12);
}
.upload-icon {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: rgba(236, 72, 153, 0.1);
  border: 1px solid rgba(236, 72, 153, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ec4899;
  transition: all 0.25s;
}
.upload-zone:hover .upload-icon,
.upload-zone.drag-over .upload-icon {
  background: rgba(236, 72, 153, 0.18);
  transform: scale(1.08);
}
.upload-title {
  font-size: 1.1rem;
  font-weight: 500;
  color: var(--text-primary);
  margin: 0;
}
.upload-hint {
  font-size: 0.875rem;
  color: var(--text-secondary);
  margin: 0;
}
.demo-btn {
  margin-top: 0.75rem;
  background: rgba(236, 72, 153, 0.1);
  border: 1px solid rgba(236, 72, 153, 0.3);
  color: #ec4899;
  padding: 0.5rem 1.25rem;
  border-radius: 20px;
  font-size: 0.875rem;
  cursor: pointer;
  transition: all 0.2s;
}
.demo-btn:hover {
  background: rgba(236, 72, 153, 0.2);
  transform: translateY(-1px);
}

/* Preview */
.preview-section {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  align-items: center;
}
.preview-card {
  width: 100%;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 16px;
  overflow: hidden;
}
.preview-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--card-border);
}
.preview-label {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--text-secondary);
}
.reupload-btn {
  background: rgba(236, 72, 153, 0.1);
  border: 1px solid rgba(236, 72, 153, 0.25);
  color: #ec4899;
  border-radius: 8px;
  padding: 0.35rem 0.875rem;
  font-size: 0.85rem;
  cursor: pointer;
  transition: all 0.2s;
}
.reupload-btn:hover:not(:disabled) {
  background: rgba(236, 72, 153, 0.2);
}
.reupload-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.preview-img {
  width: 100%;
  max-height: 400px;
  object-fit: contain;
  display: block;
  cursor: zoom-in;
  background: rgba(0, 0, 0, 0.2);
}

/* Correct Button */
.correct-btn {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: linear-gradient(135deg, #ec4899, #db2777);
  border: none;
  color: white;
  font-size: 1rem;
  font-weight: 600;
  padding: 0.875rem 2.5rem;
  border-radius: 50px;
  cursor: pointer;
  transition: all 0.25s;
  box-shadow: 0 4px 20px rgba(236, 72, 153, 0.35);
}
.correct-btn:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 8px 28px rgba(236, 72, 153, 0.5);
}
.correct-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}
.btn-spinner {
  width: 18px;
  height: 18px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: white;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Result */
.result-section {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  animation: fadeIn 0.4s ease;
}
.compare-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
}
.compare-card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 16px;
  overflow: hidden;
  transition: transform 0.2s, box-shadow 0.2s;
}
.compare-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}
.result-card {
  border-color: rgba(236, 72, 153, 0.3);
  box-shadow: 0 0 20px rgba(236, 72, 153, 0.08);
}
.compare-label {
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--card-border);
  text-align: center;
}
.result-label {
  color: #ec4899;
}
.compare-img {
  width: 100%;
  object-fit: contain;
  display: block;
  cursor: zoom-in;
  background: rgba(0, 0, 0, 0.2);
  max-height: 500px;
}
.click-hint {
  text-align: center;
  font-size: 0.8rem;
  color: var(--text-secondary);
  margin: 0;
  opacity: 0.6;
}

/* Lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  animation: fadeIn 0.2s ease;
  cursor: zoom-out;
}
.lightbox-img {
  max-width: 92vw;
  max-height: 90vh;
  object-fit: contain;
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
  cursor: default;
}
.lightbox-close {
  position: absolute;
  top: 1.25rem;
  right: 1.5rem;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: white;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  font-size: 1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s;
}
.lightbox-close:hover {
  background: rgba(255, 255, 255, 0.2);
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (max-width: 600px) {
  .compare-grid {
    grid-template-columns: 1fr;
  }
  .content {
    padding: 1.25rem 1rem;
  }
  .upload-zone {
    padding: 3rem 1.5rem;
  }
}
</style>
