<template>
  <div class="inspection-page">
    <div class="canvas">
      <header class="topbar"><div class="topbar-center"><div class="model-title">{{ modelCenterStore.activeModelName }}</div></div></header>

      <section class="model-stage">
        <ModelPlaceholder />
      </section>

      <aside class="sidepanel inspect-panel-left" :class="{ 'is-collapsed': leftCollapsed }">
        <header class="sidepanel-header">
          <div class="sidepanel-title">智能巡检分析</div>
          <button class="iconbtn" type="button" @click="leftCollapsed = !leftCollapsed">{{ leftCollapsed ? "▸" : "▾" }}</button>
        </header>
        <div class="sidepanel-body" v-show="!leftCollapsed">
          <section class="inspect-upload-card">
            <div class="inspect-upload-head">
              <div class="inspect-upload-head-title">全景照片上传</div>
            </div>
            <button class="inspect-drop" type="button" @click="panoramaInputRef?.click()">
              <div class="inspect-drop-title">上传全景照片</div>
              <div class="inspect-drop-sub">AI 将对全景照片进行整体场景分析</div>
            </button>
            <input ref="panoramaInputRef" type="file" accept="image/*" hidden @change="onPanoramaPick" />
            <div class="inspect-file-row" v-show="panoramaFileName">
              <div class="inspect-file-name">{{ panoramaFileName }}</div>
              <button class="inspect-file-remove" type="button" @click="panoramaFileName = ''">×</button>
            </div>
          </section>

          <section class="inspect-upload-card is-media">
            <div class="inspect-upload-head">
              <div class="inspect-upload-head-title">照片/视频上传</div>
            </div>
            <button class="inspect-drop" type="button" @click="mediaInputRef?.click()">
              <div class="inspect-drop-title">点击上传照片或视频</div>
              <div class="inspect-drop-sub">支持 JPG、PNG、MP4 格式</div>
            </button>
            <input ref="mediaInputRef" type="file" accept="image/*,video/*" multiple hidden @change="onMediaPick" />
            <div class="inspect-file-list" v-show="mediaFiles.length > 0">
              <div class="inspect-file-row" v-for="f in mediaFiles" :key="f.name + f.size">
                <div class="inspect-file-name">{{ f.name }}</div>
                <button class="inspect-file-remove" type="button" @click="removeMediaFile(f)">×</button>
              </div>
            </div>
            <button class="btn btn-accent inspect-analyze-btn" type="button" :disabled="mediaFiles.length === 0" @click="analyzeMedia">开始照片/视频 AI 分析</button>
          </section>

          <section class="inspect-block">
            <div class="inspect-block-title">风险分级统计</div>
            <div class="inspect-risk-grid">
              <div class="inspect-risk-card is-high"><div class="inspect-risk-k">高风险</div><div class="inspect-risk-v">{{ riskCount.high }}</div></div>
              <div class="inspect-risk-card is-mid"><div class="inspect-risk-k">中风险</div><div class="inspect-risk-v">{{ riskCount.mid }}</div></div>
              <div class="inspect-risk-card is-low"><div class="inspect-risk-k">低风险</div><div class="inspect-risk-v">{{ riskCount.low }}</div></div>
            </div>
          </section>
        </div>
      </aside>

      <aside class="sidepanel inspect-panel-right">
        <header class="sidepanel-header">
          <div class="sidepanel-title inspect-list-title">巡检问题清单</div>
          <div class="inspect-list-badge">{{ issues.length }} 个问题</div>
        </header>
        <div class="sidepanel-body inspect-list-body">
          <template v-for="group in groupedIssues" :key="group.key">
            <div class="inspect-group-title" :class="`is-${group.key}`">{{ group.label }}</div>
            <article class="inspect-item" :class="`is-${it.severity}`" v-for="it in group.items" :key="it.id" @click="openDetail(it)">
              <div class="inspect-item-top">
                <span class="inspect-pill" :class="`is-${it.severity}`">{{ severityLabel(it.severity) }}</span>
                <span class="inspect-level">{{ it.levelText }}</span>
              </div>
              <div class="inspect-item-title">{{ it.title }}</div>
              <div class="inspect-item-desc">{{ it.desc }}</div>
              <div class="inspect-item-meta">
                <div class="inspect-item-loc">{{ it.location }}</div>
                <div class="inspect-item-status" :class="`is-${it.status}`">{{ statusLabel(it.status) }}</div>
              </div>
            </article>
          </template>
        </div>
      </aside>

      <div class="inspect-detail-overlay" v-show="detailOpen" @click.self="closeDetail">
        <section class="inspect-detail-modal">
          <header class="inspect-detail-header">
            <div class="inspect-detail-chips">
              <span class="inspect-pill" :class="`is-${activeIssue?.severity || 'high'}`">{{ severityLabel(activeIssue?.severity) }}</span>
              <span class="inspect-detail-status-chip">{{ statusLabel(activeIssue?.status) }}</span>
            </div>
            <button class="inspect-detail-close" type="button" @click="closeDetail">×</button>
          </header>
          <div class="inspect-detail-body" v-if="activeIssue">
            <div class="inspect-detail-title">{{ activeIssue.title }}</div>
            <section class="inspect-detail-card is-ai">
              <div class="inspect-detail-card-title">AI 分析结果</div>
              <div class="inspect-detail-card-text">{{ activeIssue.aiText }}</div>
            </section>
            <div class="inspect-detail-grid">
              <section class="inspect-detail-mini"><div class="inspect-detail-mini-label">关联构件</div><div class="inspect-detail-mini-value">{{ activeIssue.component }}</div></section>
              <section class="inspect-detail-mini"><div class="inspect-detail-mini-label">位置信息</div><div class="inspect-detail-mini-value">{{ activeIssue.location }}</div></section>
            </div>
            <section class="inspect-detail-task" v-show="activeIssue.owner || activeIssue.due">
              <div class="inspect-detail-task-title">整改任务信息</div>
              <div class="inspect-detail-task-grid">
                <div class="inspect-detail-task-item"><div class="inspect-detail-task-k">责任人</div><div class="inspect-detail-task-v">{{ activeIssue.owner || "--" }}</div></div>
                <div class="inspect-detail-task-item"><div class="inspect-detail-task-k">完成期限</div><div class="inspect-detail-task-v">{{ activeIssue.due || "--" }}</div></div>
                <div class="inspect-detail-task-item"><div class="inspect-detail-task-k">当前状态</div><div class="inspect-detail-task-v">{{ statusLabel(activeIssue.status) }}</div></div>
              </div>
            </section>
          </div>
          <footer class="inspect-detail-footer">
            <button class="btn inspect-detail-btn" type="button" @click="openAssign" v-show="activeIssue && activeIssue.status === 'unassigned'">指派整改任务</button>
            <button class="btn inspect-detail-btn" type="button" @click="toast('已在模型中定位（占位）')">在模型中定位</button>
            <button class="btn inspect-detail-btn" type="button" @click="toast('导出报告（占位）')">导出报告</button>
          </footer>
        </section>
      </div>

      <div class="inspect-assign-overlay" v-show="assignOpen" @click.self="assignOpen = false">
        <section class="inspect-assign-modal">
          <header class="inspect-assign-header">
            <div class="inspect-assign-title">指派整改任务</div>
            <button class="inspect-assign-close" type="button" @click="assignOpen = false">×</button>
          </header>
          <div class="inspect-assign-body" v-if="activeIssue">
            <section class="inspect-assign-summary">
              <div class="inspect-assign-summary-title">{{ activeIssue.title }}</div>
              <div class="inspect-assign-summary-meta">{{ activeIssue.component }}</div>
            </section>
            <div class="inspect-assign-field">
              <div class="inspect-assign-label">指派类型</div>
              <div class="inspect-assign-radio">
                <button class="inspect-assign-radio-btn" :class="{ 'is-on': assignType === 'person' }" type="button" @click="assignType='person'">个人</button>
                <button class="inspect-assign-radio-btn" :class="{ 'is-on': assignType === 'team' }" type="button" @click="assignType='team'">班组</button>
              </div>
            </div>
            <div class="inspect-assign-field">
              <div class="inspect-assign-label">{{ assignType === 'person' ? '选择责任人' : '选择责任班组' }}</div>
              <div class="inspect-assign-select-wrap">
                <select class="input inspect-assign-select" v-model="assignOwner">
                  <option value="">请选择</option>
                  <option v-for="p in assignCandidates" :key="p" :value="p">{{ p }}</option>
                </select>
              </div>
            </div>
            <div class="inspect-assign-field"><div class="inspect-assign-label">设置完成期限</div><input class="input inspect-assign-input" type="date" v-model="assignDue" /></div>
            <div class="inspect-assign-field"><div class="inspect-assign-label">整改要求与备注</div><textarea class="inspect-assign-textarea" v-model="assignNote" placeholder="输入整改要求与备注…"></textarea></div>
          </div>
          <footer class="inspect-assign-footer">
            <button class="btn btn-ghost inspect-assign-btn" type="button" @click="assignOpen = false">取消</button>
            <button class="btn btn-accent inspect-assign-btn" type="button" :disabled="!canAssign" @click="confirmAssign">确认指派</button>
          </footer>
        </section>
      </div>

      <div class="toast" v-show="toastOpen">{{ toastText }}</div>
    </div>
  </div>
</template>

<script setup>
import { computed, ref } from "vue";
import ModelPlaceholder from "../../components/model-placeholder/index.vue";
import { useModelCenterStore } from "../../stores/modelCenter.js";

const modelCenterStore = useModelCenterStore();

const leftCollapsed = ref(false);
const panoramaFileName = ref("");
const mediaFiles = ref([]);
const detailOpen = ref(false);
const assignOpen = ref(false);
const activeIssueId = ref("");
const assignType = ref("person");
const assignOwner = ref("");
const assignDue = ref("");
const assignNote = ref("");
const toastOpen = ref(false);
const toastText = ref("");

const panoramaInputRef = ref(null);
const mediaInputRef = ref(null);

const issues = ref([
  { id: "I-001", severity: "high", levelText: "高风险", title: "临边防护缺失", desc: "桥面边缘未设置连续防护栏杆，存在坠落风险。", component: "主桥-0#墩", location: "主桥桥面北侧", status: "unassigned", aiText: "AI识别到临边防护缺失，建议立即设置双道栏杆并加挂安全网。", owner: "", due: "" },
  { id: "I-002", severity: "mid", levelText: "中风险", title: "材料堆放不规范", desc: "钢筋堆放区未按分区标识，通道占用。", component: "引桥-承台", location: "引桥材料堆场", status: "assigned", aiText: "AI识别材料堆放不规范，建议按区域标线重新布置并清理通道。", owner: "张工", due: "2026-03-25" },
  { id: "I-003", severity: "low", levelText: "低风险", title: "警示牌破损", desc: "个别警示牌褪色破损，辨识度下降。", component: "路面-基层", location: "东侧便道入口", status: "fixing", aiText: "AI识别警示标识清晰度不足，建议统一更换为反光警示牌。", owner: "安监班组", due: "2026-03-21" },
]);

const groupedIssues = computed(() => {
  const groups = [
    { key: "high", label: "高风险问题", items: [] },
    { key: "mid", label: "中风险问题", items: [] },
    { key: "low", label: "低风险问题", items: [] },
  ];
  issues.value.forEach((it) => groups.find((g) => g.key === it.severity)?.items.push(it));
  return groups.filter((g) => g.items.length > 0);
});

const riskCount = computed(() => ({
  high: issues.value.filter((i) => i.severity === "high").length,
  mid: issues.value.filter((i) => i.severity === "mid").length,
  low: issues.value.filter((i) => i.severity === "low").length,
}));

const activeIssue = computed(() => issues.value.find((i) => i.id === activeIssueId.value) || null);
const assignCandidates = computed(() => (assignType.value === "person" ? ["张工", "李工", "王工"] : ["土建班组", "钢筋班组", "机电班组"]));
const canAssign = computed(() => !!assignOwner.value && !!assignDue.value);

function onPanoramaPick(e) {
  const file = e.target.files?.[0];
  panoramaFileName.value = file ? file.name : "";
}

function onMediaPick(e) {
  const files = Array.from(e.target.files || []);
  mediaFiles.value = files;
}

function removeMediaFile(file) {
  mediaFiles.value = mediaFiles.value.filter((f) => f !== file);
}

function analyzeMedia() {
  toast("AI 分析完成，已生成巡检问题清单");
}

function openDetail(issue) {
  activeIssueId.value = issue.id;
  detailOpen.value = true;
}

function closeDetail() {
  detailOpen.value = false;
}

function openAssign() {
  assignType.value = "person";
  assignOwner.value = "";
  assignDue.value = "";
  assignNote.value = "";
  assignOpen.value = true;
}

function confirmAssign() {
  const idx = issues.value.findIndex((i) => i.id === activeIssueId.value);
  if (idx < 0) return;
  issues.value[idx] = {
    ...issues.value[idx],
    status: "assigned",
    owner: assignOwner.value,
    due: assignDue.value,
  };
  assignOpen.value = false;
  toast("已指派整改任务");
}

let timer = null;
function toast(text) {
  toastText.value = text;
  toastOpen.value = true;
  if (timer) clearTimeout(timer);
  timer = setTimeout(() => (toastOpen.value = false), 1500);
}

function severityLabel(sev) {
  return sev === "mid" ? "中风险" : sev === "low" ? "低风险" : "高风险";
}

function statusLabel(status) {
  return status === "assigned" ? "已指派" : status === "fixing" ? "整改中" : "未指派";
}
</script>

<style scoped>
.inspection-page { min-height: 100vh; font-family: "Microsoft YaHei", "PingFang SC", sans-serif; }
.canvas { position: relative; min-height: 100vh; overflow: hidden; border-radius: 24px; border: 1px solid rgba(98,191,206,.34); background: radial-gradient(circle at 50% 30%, #bcc9d6 0%, #b2c3d2 60%, #a8b8c9 100%); box-shadow: inset 0 0 0 8px rgba(214,230,241,.55); }
.topbar { position: absolute; inset: 0 0 auto; height: 120px; z-index: 30; }
.topbar-center { position: absolute; left: 50%; transform: translateX(-50%); top: 16px; }
.model-title { font-size: 20px; letter-spacing: 1px; font-weight: 700; color: rgba(255,128,52,.95); text-shadow: 0 2px 10px rgba(0,0,0,.25); }
.model-stage { position: absolute; inset: 0; }

.sidepanel { border-radius: 18px; border: 1px solid rgba(83,214,206,.24); background: radial-gradient(260px 140px at 8% 0%, rgba(63,203,191,.16), transparent 62%) padding-box, linear-gradient(180deg, rgba(20,31,37,.92), rgba(15,23,29,.88)) padding-box; box-shadow: 0 22px 60px rgba(0,0,0,.34), 0 0 0 1px rgba(83,214,206,.12) inset; overflow: hidden; z-index: 25; position: absolute; top: 150px; bottom: 100px; }
.inspect-panel-left { left: 16px; width: 340px; }
.inspect-panel-right { right: 16px; width: 360px; }
.sidepanel-header { display: flex; align-items: center; justify-content: space-between; padding: 10px 10px 10px 12px; border-bottom: 1px solid rgba(83,214,206,.16); background: radial-gradient(360px 100px at 10% 0%, rgba(83,214,206,.24), transparent 68%), linear-gradient(180deg, rgba(28,134,122,.84), rgba(15,60,74,.62)); }
.sidepanel-title { font-size: 14px; font-weight: 900; color: rgba(207,247,242,.96); }
.iconbtn { width: 30px; height: 30px; border-radius: 10px; border: 1px solid rgba(255,255,255,.12); background: rgba(255,255,255,.42); color: rgba(11,27,58,.86); font-weight: 900; cursor: pointer; }
.sidepanel-body { height: calc(100% - 52px); overflow: auto; padding: 10px; }

.inspect-upload-card, .inspect-block { border: 1px solid rgba(255,255,255,.1); background: rgba(0,0,0,.14); border-radius: 14px; padding: 10px; margin-bottom: 10px; }
.inspect-upload-head-title, .inspect-block-title { color: rgba(238,247,251,.92); font-size: 13px; font-weight: 900; margin-bottom: 8px; }
.inspect-drop { width: 100%; border: 1px dashed rgba(83,214,206,.4); border-radius: 12px; background: rgba(0,0,0,.16); padding: 12px; color: rgba(220,238,244,.88); text-align: left; cursor: pointer; }
.inspect-drop-title { font-size: 13px; font-weight: 900; }
.inspect-drop-sub { font-size: 12px; opacity: .75; margin-top: 4px; }
.inspect-file-row { margin-top: 8px; display: flex; align-items: center; justify-content: space-between; gap: 8px; border: 1px solid rgba(255,255,255,.1); border-radius: 10px; background: rgba(255,255,255,.04); padding: 6px 8px; }
.inspect-file-name { color: rgba(222,238,244,.86); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inspect-file-remove { border: 0; background: transparent; color: rgba(255,255,255,.72); font-size: 18px; cursor: pointer; }
.inspect-file-list { display: grid; gap: 6px; margin-top: 8px; }
.inspect-analyze-btn { width: 100%; margin-top: 8px; }

.btn { appearance: none; border: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.08); color: rgba(255,255,255,.88); border-radius: 12px; padding: 8px 10px; cursor: pointer; }
.btn-ghost { background: rgba(255,255,255,.04); }
.btn-accent { border-color: rgba(83,214,206,.24); background: rgba(43,191,178,.26); }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.inspect-risk-grid { display: grid; grid-template-columns: 1fr; gap: 8px; }
.inspect-risk-card { border-radius: 12px; padding: 8px 10px; border: 1px solid rgba(255,255,255,.1); background: rgba(0,0,0,.16); display: flex; align-items: center; justify-content: space-between; }
.inspect-risk-card.is-high { border-color: rgba(217,54,62,.35); }
.inspect-risk-card.is-mid { border-color: rgba(212,136,6,.35); }
.inspect-risk-card.is-low { border-color: rgba(47,143,47,.35); }
.inspect-risk-k { color: rgba(220,236,242,.82); font-size: 12px; }
.inspect-risk-v { color: rgba(255,255,255,.92); font-weight: 900; font-size: 16px; }

.inspect-list-title { display: flex; align-items: center; gap: 8px; }
.inspect-list-badge { font-size: 12px; font-weight: 800; color: rgba(255,255,255,.9); border: 1px solid rgba(255,255,255,.14); border-radius: 999px; padding: 4px 8px; background: rgba(0,0,0,.18); }
.inspect-list-body { display: grid; gap: 8px; }
.inspect-group-title { margin: 2px 2px 0; font-size: 12px; font-weight: 900; color: rgba(230,243,247,.85); }

.inspect-item { border: 1px solid rgba(255,255,255,.1); background: rgba(0,0,0,.16); border-radius: 14px; padding: 10px; cursor: pointer; }
.inspect-item:hover { border-color: rgba(83,214,206,.26); }
.inspect-item-top { display: flex; align-items: center; justify-content: space-between; }
.inspect-pill { border-radius: 999px; padding: 3px 8px; font-size: 11px; font-weight: 900; border: 1px solid transparent; }
.inspect-pill.is-high { color: rgba(255,178,182,.95); border-color: rgba(217,54,62,.35); background: rgba(217,54,62,.18); }
.inspect-pill.is-mid { color: rgba(255,214,142,.95); border-color: rgba(212,136,6,.35); background: rgba(212,136,6,.18); }
.inspect-pill.is-low { color: rgba(176,244,176,.95); border-color: rgba(47,143,47,.35); background: rgba(47,143,47,.18); }
.inspect-level { color: rgba(214,235,241,.8); font-size: 11px; }
.inspect-item-title { margin-top: 6px; color: rgba(244,252,255,.92); font-size: 13px; font-weight: 900; }
.inspect-item-desc { margin-top: 6px; color: rgba(214,233,239,.8); font-size: 12px; line-height: 1.45; }
.inspect-item-meta { margin-top: 8px; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.inspect-item-loc { color: rgba(201,223,231,.72); font-size: 11px; }
.inspect-item-status { font-size: 11px; font-weight: 900; border-radius: 999px; padding: 3px 8px; border: 1px solid rgba(255,255,255,.1); }
.inspect-item-status.is-unassigned { color: rgba(255,214,142,.95); border-color: rgba(212,136,6,.35); background: rgba(212,136,6,.18); }
.inspect-item-status.is-assigned { color: rgba(176,244,176,.95); border-color: rgba(47,143,47,.35); background: rgba(47,143,47,.18); }
.inspect-item-status.is-fixing { color: rgba(176,218,255,.95); border-color: rgba(21,108,255,.35); background: rgba(21,108,255,.18); }

.inspect-detail-overlay, .inspect-assign-overlay { position: absolute; inset: 0; z-index: 90; display: grid; place-items: center; background: rgba(13,36,74,.08); backdrop-filter: blur(3px); }
.inspect-detail-modal, .inspect-assign-modal { width: min(720px, calc(100% - 32px)); border-radius: 18px; border: 1px solid rgba(83,214,206,.24); background: radial-gradient(260px 160px at 18% 0%, rgba(83,214,206,.14), transparent 62%) padding-box, linear-gradient(180deg, rgba(18,26,31,.94), rgba(14,20,25,.86)) padding-box; box-shadow: 0 30px 80px rgba(0,0,0,.3); }
.inspect-detail-header, .inspect-assign-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; border-bottom: 1px solid rgba(83,214,206,.2); }
.inspect-detail-close, .inspect-assign-close { border: 0; background: transparent; color: rgba(255,255,255,.8); font-size: 26px; cursor: pointer; }
.inspect-detail-body, .inspect-assign-body { padding: 14px; max-height: 58vh; overflow: auto; }
.inspect-detail-title { color: rgba(244,252,255,.92); font-size: 18px; font-weight: 900; margin-bottom: 12px; }
.inspect-detail-card, .inspect-detail-mini, .inspect-detail-task, .inspect-assign-summary { border: 1px solid rgba(255,255,255,.1); background: rgba(0,0,0,.16); border-radius: 12px; padding: 10px; }
.inspect-detail-card-title, .inspect-detail-task-title, .inspect-detail-mini-label, .inspect-assign-label, .inspect-assign-title { color: rgba(230,243,247,.84); font-size: 12px; font-weight: 900; }
.inspect-detail-card-text, .inspect-detail-mini-value, .inspect-detail-task-v { color: rgba(244,252,255,.9); font-size: 13px; margin-top: 6px; }
.inspect-detail-grid, .inspect-detail-task-grid { margin-top: 10px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.inspect-detail-task { margin-top: 10px; }
.inspect-detail-footer, .inspect-assign-footer { display: flex; justify-content: flex-end; gap: 10px; padding: 12px 14px; border-top: 1px solid rgba(83,214,206,.2); }

.inspect-assign-field { margin-top: 10px; }
.inspect-assign-radio { margin-top: 6px; display: inline-flex; gap: 8px; }
.inspect-assign-radio-btn { border: 1px solid rgba(255,255,255,.14); background: rgba(0,0,0,.14); color: rgba(255,255,255,.84); border-radius: 999px; padding: 6px 10px; cursor: pointer; }
.inspect-assign-radio-btn.is-on { border-color: rgba(83,214,206,.28); background: rgba(43,191,178,.24); }
.inspect-assign-select-wrap { margin-top: 6px; }
.input { width: 100%; border-radius: 10px; border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.08); color: rgba(255,255,255,.9); padding: 8px 10px; }
.inspect-assign-textarea { margin-top: 6px; width: 100%; min-height: 86px; border-radius: 10px; border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.08); color: rgba(255,255,255,.9); padding: 8px 10px; resize: vertical; }

.toast { position: absolute; left: 50%; top: 74px; transform: translateX(-50%); z-index: 100; border-radius: 12px; padding: 8px 12px; border: 1px solid rgba(255,255,255,.14); background: rgba(18,26,31,.92); color: rgba(238,246,250,.9); font-size: 12px; font-weight: 800; }

@media (max-width: 1300px) {
  .inspect-panel-left { width: 300px; }
  .inspect-panel-right { width: 320px; }
}
</style>
