<template>
  <div ref="wrapperRef" class="sce-wrapper">
    <!-- Monaco Editor Container - terminal panel will be moved here -->
    <div ref="containerRef" class="sce-editor-area">
      <!-- Terminal Panel (will be moved here after mount) -->
      <div
        ref="terminalPanelRef"
        class="terminal-panel"
        :class="{ collapsed: !isPanelExpanded }"
        :style="isPanelExpanded ? { height: panelHeight + 'px' } : {}"
      >
        <!-- Resize Handle -->
        <div class="resize-handle" @mousedown="startResize"></div>

        <!-- Panel Tab Header -->
        <div class="panel-tabs">
          <div
            class="tab-item"
            :class="{ active: activeTab === 'testcase' }"
            @click="
              activeTab = 'testcase';
              isPanelExpanded = true;
            "
          >
            <span class="text">Testcase</span>
          </div>
          <div
            class="tab-item"
            :class="{ active: activeTab === 'result' }"
            @click="
              activeTab = 'result';
              isPanelExpanded = true;
            "
          >
            <span class="icon">>_</span>
            <span class="text">Test Result</span>
          </div>

          <div class="panel-actions">
            <button class="icon-toggle" @click="togglePanel">
              {{ isPanelExpanded ? "⌄" : "^" }}
            </button>
          </div>
        </div>

        <!-- ... rest of content ... -->

        <!-- Testcase Content -->
        <div
          class="panel-content"
          v-if="activeTab === 'testcase' && isPanelExpanded"
        >
          <div class="case-tabs">
            <button
              v-for="(item, index) in testCases"
              :key="item.id"
              class="case-tab-btn"
              :class="{ active: activeTestCaseIndex === index }"
              @click="activeTestCaseIndex = index"
            >
              {{ item.label }}
              <span
                v-if="testCases.length > 1"
                class="case-close-btn"
                @click.stop="deleteTestCase(index)"
                >×</span
              >
            </button>
            <button class="case-tab-btn add" @click="addNewTestCase">+</button>
          </div>

          <div class="case-inputs">
            <div
              class="input-group"
              v-for="(input, idx) in activeTestCase.inputs"
              :key="idx"
            >
              <label>{{ input.name }}</label>
              <div class="input-box-wrapper">
                <textarea
                  class="input-box-edit"
                  v-model="input.value"
                  rows="1"
                ></textarea>
              </div>
            </div>
          </div>
        </div>

        <!-- Result Content -->
        <div
          class="panel-content result-view"
          v-show="activeTab === 'result' && isPanelExpanded"
          ref="resultPanel"
        >
          <!-- Loading State -->
          <div class="result-loading" v-if="isRunning">
            <div class="spinner"></div>
            <p>Running Code...</p>
          </div>

          <div class="result-empty" v-else-if="!runResult">
            <p class="empty-text">Click "Run" to see results</p>
          </div>

          <div class="result-content" v-else>
            <!-- Overall Status Header -->
            <div class="result-header">
              <div
                :class="
                  runResult.status === 'success' && allTestsPassed
                    ? 'success'
                    : 'error'
                "
              >
                {{
                  runResult.status === "success" && allTestsPassed
                    ? "Accepted"
                    : runResult.error
                      ? "Runtime Error"
                      : "Wrong Answer"
                }}
              </div>
              <div class="result-meta">
                Runtime: {{ Math.round(runResult.executionTime) }} ms
              </div>
            </div>

            <!-- Compile Error Message if any -->
            <div
              v-if="
                runResult.error &&
                (!runResult.testResults || runResult.testResults.length === 0)
              "
              class="error-box"
            >
              {{ runResult.error }}
            </div>

            <!-- Test Result Tabs -->
            <div
              v-if="runResult.testResults && runResult.testResults.length > 0"
            >
              <div class="case-tabs result-tabs">
                <button
                  v-for="(res, index) in runResult.testResults"
                  :key="res.id"
                  class="case-tab-btn"
                  :class="[
                    { active: activeResultCaseIndex === index },
                    res.status,
                  ]"
                  @click="activeResultCaseIndex = index"
                >
                  <span class="status-dot"></span>
                  Case {{ index + 1 }}
                </button>
              </div>

              <!-- Selected Case Detail -->
              <div
                class="case-detail"
                v-if="runResult.testResults[activeResultCaseIndex]"
              >
                <!-- Inputs Display -->
                <div
                  class="input-group"
                  v-for="(val, idx) in runResult.testResults[
                    activeResultCaseIndex
                  ].input"
                  :key="idx"
                >
                  <label
                    v-if="
                      testCases[activeResultCaseIndex] &&
                      testCases[activeResultCaseIndex].inputs[idx]
                    "
                  >
                    {{ testCases[activeResultCaseIndex].inputs[idx].name }}
                  </label>
                  <label v-else>Input {{ idx + 1 }}</label>
                  <div class="code-block input-block">
                    {{ JSON.stringify(val) }}
                  </div>
                </div>

                <div
                  class="input-group"
                  v-if="runResult.testResults[activeResultCaseIndex].log"
                >
                  <label>Stdout</label>
                  <div class="code-block log">
                    {{ runResult.testResults[activeResultCaseIndex].log }}
                  </div>
                </div>

                <div class="input-group">
                  <label>Output</label>
                  <div
                    class="code-block"
                    :class="{
                      error:
                        runResult.testResults[activeResultCaseIndex].status !==
                        'passed',
                    }"
                  >
                    {{
                      runResult.testResults[activeResultCaseIndex].error
                        ? runResult.testResults[activeResultCaseIndex].error
                        : JSON.stringify(
                            runResult.testResults[activeResultCaseIndex].output,
                          )
                    }}
                  </div>
                </div>

                <div class="input-group">
                  <label>Expected</label>
                  <div class="code-block success">
                    {{
                      runResult.testResults[activeResultCaseIndex].expected ===
                      undefined
                        ? "N/A"
                        : JSON.stringify(
                            runResult.testResults[activeResultCaseIndex]
                              .expected,
                          )
                    }}
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import {
  defineComponent,
  ref,
  computed,
  onMounted,
  onBeforeUnmount,
  watch,
  type PropType,
} from "vue";
import { SmartCodeEditor } from "../../core/SmartCodeEditor";
import type { SmartCodeEditorOptions, RunResult } from "../../types";

export default defineComponent({
  name: "SmartCodeEditor",
  props: {
    modelValue: {
      type: String,
      default: "",
    },
    language: {
      type: String,
      default: "javascript",
    },
    theme: {
      type: String,
      default: "vs",
    },
    config: {
      type: Object as PropType<SmartCodeEditorOptions>,
      default: undefined,
    },
    questionContent: {
      type: String,
      default: "",
    },
    questionMarkdown: {
      type: Object as () => import("../../types/question").QuestionMarkdownOptions,
      default: undefined,
    },
    showQuestionPanel: {
      type: Boolean,
      default: true,
    },
    enableRun: {
      type: Boolean,
      default: true,
    },
    enableLanguageSwitch: {
      type: Boolean,
      default: true,
    },
    readOnly: {
      type: Boolean,
      default: false,
    },
    runTimeout: {
      type: Number,
      default: 5000,
    },
    disableLocalRun: {
      type: Boolean,
      default: false,
    },
    customRunner: {
      type: Function as PropType<SmartCodeEditorOptions["customRunner"]>,
      default: undefined,
    },
    customSubmitRunner: {
      type: Function as PropType<
        (
          code: string,
          language: string,
          testCases: any,
          silent: boolean,
        ) => Promise<RunResult>
      >,
      default: undefined,
    },
    enableSubmit: {
      type: Boolean,
      default: true,
    },
    testCases: {
      type: Array as () => import("../../types").UITestCase[],
      default: () => [],
    },

    // ===== 新增：题目配置相关 Props =====

    /** 题目完整配置（可选） */
    questionConfig: {
      type: Object as () => import("../../types/question").QuestionConfig,
      default: undefined,
    },

    /** 自定义语言模板映射（可选，会覆盖 questionConfig） */
    languageTemplates: {
      type: Object as () => import("../../types/question").LanguageTemplates,
      default: undefined,
    },

    /** 支持的语言列表（可选，限制可用语言） */
    supportedLanguages: {
      type: Array as () => string[],
      default: undefined,
    },

    /** 统一题目配置对象 (推荐) */
    question: {
      type: Object as () => import("../../types/question").QuestionConfig,
      default: undefined,
    },
  },
  emits: ["update:modelValue", "run", "submit", "language-change"],
  setup(props, { emit }) {
    const wrapperRef = ref<HTMLElement>();
    const containerRef = ref<HTMLElement>();
    const terminalPanelRef = ref<HTMLElement>();
    let editorInstance: SmartCodeEditor | null = null;
    let resizeObserver: ResizeObserver | null = null;

    // Terminal panel state
    const activeTab = ref<"testcase" | "result">("testcase");
    const isPanelExpanded = ref(true);
    const activeTestCaseIndex = ref(0);
    const activeResultCaseIndex = ref(0); // 新增：结果面板选中的 Case 索引
    const runResult = ref<RunResult | null>(null);
    const isRunning = ref(false); // 新增：运行状态
    const allTestsPassed = computed(() => {
      if (!runResult.value || !runResult.value.testResults) return false;
      return (
        runResult.value.testResults.length > 0 &&
        runResult.value.testResults.every((t) => t.status === "passed")
      );
    });
    const panelHeight = ref(240);
    let isResizing = false;
    let startY = 0;
    let startHeight = 0;

    // Use prop if available, otherwise default to empty or specific logic.
    // However, since we want to support the user case of "Instructors entering questions",
    // we should validly initialize it.
    // Here we initialize from props, or empty array if not provided.
    // The parent (dev-app) is responsible for providing the initial cases.
    const testCases = ref<import("../../types").UITestCase[]>(
      props.testCases && props.testCases.length > 0
        ? JSON.parse(JSON.stringify(props.testCases)) // Deep copy to avoid mutating prop
        : props.question && props.question.testCases
          ? JSON.parse(JSON.stringify(props.question.testCases))
          : [],
    );

    const getMergedQuestionMarkdown = () => {
      const base = props.questionMarkdown || props.config?.questionMarkdown;
      if (!base) return undefined;
      const value =
        base.value ??
        (props.question as any)?.descriptionMarkdown ??
        props.question?.description ??
        "";
      return { ...base, value };
    };

    // If empty default needed for independent testing when no prop provided:
    if (testCases.value.length === 0) {
      testCases.value = [
        {
          id: 1,
          label: "Case 1",
          inputs: [],
          expected: "",
        },
      ];
    }

    // Watch prop changes to update local state if parent updates it
    watch(
      () => props.testCases,
      (newVal) => {
        if (newVal) {
          testCases.value = JSON.parse(JSON.stringify(newVal));
          activeTestCaseIndex.value = 0;
        }
      },
      { deep: true },
    );

    const activeTestCase = computed(
      () => testCases.value[activeTestCaseIndex.value],
    );

    const togglePanel = () => {
      isPanelExpanded.value = !isPanelExpanded.value;
      // Reset height when expanding if it was collapsed or too small
      if (isPanelExpanded.value && panelHeight.value < 100) {
        panelHeight.value = 240;
      }
    };

    const startResize = (e: MouseEvent) => {
      isResizing = true;
      startY = e.clientY;
      startHeight = panelHeight.value;
      if (!isPanelExpanded.value) {
        isPanelExpanded.value = true;
      }
      document.addEventListener("mousemove", doResize);
      document.addEventListener("mouseup", stopResize);
      document.body.style.cursor = "ns-resize";
      document.body.style.userSelect = "none";
    };

    const doResize = (e: MouseEvent) => {
      if (!isResizing) return;
      e.preventDefault(); // Prevent text selection while dragging

      requestAnimationFrame(() => {
        const dy = startY - e.clientY;
        const newHeight = startHeight + dy;

        // Min height 100px, max height 80% of window
        const maxHeight = window.innerHeight * 0.8;
        if (newHeight >= 100 && newHeight <= maxHeight) {
          panelHeight.value = newHeight;
          // Trigger layout update during resize for smoothness
          editorInstance?.layout();
        }
      });
    };

    const stopResize = () => {
      isResizing = false;
      document.removeEventListener("mousemove", doResize);
      document.removeEventListener("mouseup", stopResize);
      document.body.style.cursor = "";
      document.body.style.userSelect = "";
      // Ensure editor resizes after panel resize stops
      editorInstance?.layout();
    };

    const addNewTestCase = () => {
      const newId = testCases.value.length + 1;

      // Clone inputs structure from the first test case if available
      let newInputs = [
        { name: "nums =", value: "[]" },
        { name: "target =", value: "0" },
      ];

      if (testCases.value.length > 0) {
        newInputs = testCases.value[0].inputs.map((input) => ({
          name: input.name,
          value: "", // Empty value for new case
        }));
      } else if (
        props.question &&
        props.question.functionStructure &&
        props.question.functionStructure.args
      ) {
        // Fallback: derive from question config
        newInputs = props.question.functionStructure.args.map((arg) => ({
          name: `${arg.name} =`,
          value: "",
        }));
      }

      testCases.value.push({
        id: newId,
        label: `Case ${newId}`,
        inputs: newInputs,
        expected: "",
      });
      activeTestCaseIndex.value = testCases.value.length - 1;
    };

    const deleteTestCase = (index: number) => {
      if (testCases.value.length <= 1) return;

      testCases.value.splice(index, 1);

      if (activeTestCaseIndex.value >= testCases.value.length) {
        activeTestCaseIndex.value = testCases.value.length - 1;
      } else if (activeTestCaseIndex.value > index) {
        activeTestCaseIndex.value--;
      }
    };

    const parseValue = (val: string) => {
      try {
        // 简单处理：如果是数字字符串，转数字；如果是 JSON 格式，解析 JSON
        if (!isNaN(Number(val)) && val.trim() !== "") return Number(val);
        return JSON.parse(val);
      } catch (e) {
        return val; // 无法解析则作为字符串
      }
    };

    // 将 UI 用例转换为运行时用例
    const getRuntimeTestCases = () => {
      return testCases.value.map((tc) => ({
        id: tc.id,
        input: tc.inputs.map((i) => parseValue(i.value)),
        expected: parseValue(tc.expected),
      }));
    };

    // 同步测试用例到编辑器实例
    const syncTestCasesToEditor = () => {
      if (editorInstance) {
        editorInstance.setTestCases(getRuntimeTestCases());
      }
    };

    // 监听测试用例变化，同步到编辑器
    watch(
      testCases,
      () => {
        syncTestCasesToEditor();
      },
      { deep: true },
    );

    // 运行完成的回调
    const handleRunComplete = (result: RunResult) => {
      isRunning.value = false;
      runResult.value = result;
      activeTab.value = "result";
      isPanelExpanded.value = true;

      // 默认选中第一个 failed 的 case，或者第一个 case
      if (result.testResults && result.testResults.length > 0) {
        const firstFailed = result.testResults.findIndex(
          (r) => r.status !== "passed",
        );
        activeResultCaseIndex.value = firstFailed >= 0 ? firstFailed : 0;
      }

      emit("run", result);
    };

    const handleRun = async () => {
      // 切换到结果标签页并显示 loading
      activeTab.value = "result";
      isPanelExpanded.value = true;
      isRunning.value = true;
      runResult.value = null; // 清除旧结果

      // 调用编辑器运行
      // 注意：这里是一个异步调用，但我们通过回调 handleRunComplete 来处理完成状态
      // 这里 await 如果 CodeRunner 内部抛错也能捕获
      try {
        const result = await editorInstance?.run();
        // If disableLocalRun is true, the result will be a placeholder
        // The actual result will come from external handler via prop callback
        // But we still need to wait for it somehow...
        if (result && result.status !== "success") {
          // If we got an error from the internal runner disable logic, handle it
          isRunning.value = false;
        }
      } catch (e) {
        isRunning.value = false;
        console.error("Run failed:", e);
      }
    };

    onMounted(() => {
      if (!containerRef.value || !terminalPanelRef.value) return;

      const mergedQuestionMarkdown = getMergedQuestionMarkdown();

      const options: SmartCodeEditorOptions = {
        ...(props.config || {}),
        container: containerRef.value,
        language: props.language,
        theme: props.theme,
        value: props.modelValue,
        questionContent: mergedQuestionMarkdown
          ? ""
          : props.questionContent || props.question?.description,
        questionMarkdown: mergedQuestionMarkdown,
        showQuestionPanel: props.showQuestionPanel,
        enableRun: props.enableRun,
        enableSubmit: props.enableSubmit,
        enableLanguageSwitch: props.enableLanguageSwitch,
        readOnly: props.readOnly,
        runTimeout: props.runTimeout,
        disableLocalRun: props.disableLocalRun,
        customRunner: props.customRunner,

        // 新增：题目配置相关
        questionConfig: props.questionConfig || props.question,
        languageTemplates:
          props.languageTemplates || props.question?.languageTemplates,
        supportedLanguages:
          props.supportedLanguages || props.question?.supportedLanguages,

        onChange: (value: string) => {
          emit("update:modelValue", value);
        },
        onRun: handleRunComplete,
        onSubmit: async (code: string, language: string) => {
          if (props.customSubmitRunner) {
            // Show result panel
            activeTab.value = "result";
            isPanelExpanded.value = true;
            isRunning.value = true;
            runResult.value = null;

            try {
              // Call custom submit runner (wrapper should handle args)
              // We pass null for testCases because backend uses hidden cases
              const result = await props.customSubmitRunner(
                code,
                language,
                null,
                true,
              );
              handleRunComplete(result);
            } catch (e) {
              console.error("Submit failed:", e);
              isRunning.value = false;
            }
          } else {
            emit("submit", {
              code,
              language,
              testCases: getRuntimeTestCases(),
            });
          }
        },
        onLanguageChange: (language: string) => {
          emit("language-change", language);
        },
      };

      editorInstance = new SmartCodeEditor(options);

      // 初始化同步测试用例
      syncTestCasesToEditor();

      // 如果在初始化时就有 question 数据，确保代码正确加载
      if (props.question && props.question.languageTemplates) {
        const currentLang = editorInstance.getLanguage();
        const template = props.question.languageTemplates[currentLang];

        console.log("🔧 初始化时检查代码:", {
          hasQuestion: !!props.question,
          currentLang,
          hasTemplate: !!template,
          modelValue: props.modelValue?.substring(0, 50),
        });

        // 如果 modelValue 是空的或未定义，但有题目模板，使用题目模板
        if (!props.modelValue && template) {
          console.log("⚠️ 模板未正确传递，手动设置");
          editorInstance.setValue(template);
        }
      }

      // Move terminal-panel into sce-right-container (as sibling of sce-editor-panel)
      setTimeout(() => {
        const rightContainer = containerRef.value?.querySelector(
          ".sce-right-container",
        );
        if (rightContainer && terminalPanelRef.value) {
          rightContainer.appendChild(terminalPanelRef.value);
        }
      }, 0);

      // 监听容器大小变化
      if (wrapperRef.value) {
        resizeObserver = new ResizeObserver(() => {
          editorInstance?.resize();
        });
        resizeObserver.observe(wrapperRef.value);
      }
    });

    // 监听 props 变化并同步到编辑器
    watch(
      () => props.language,
      (newLang) => {
        editorInstance?.setLanguage(newLang);
        runResult.value = null;
      },
    );

    watch(
      () => props.theme,
      (newTheme) => {
        editorInstance?.setTheme(newTheme);
      },
    );

    watch(
      () => props.modelValue,
      (newValue) => {
        if (editorInstance && editorInstance.getValue() !== newValue) {
          editorInstance.setValue(newValue);
        }
      },
    );

    watch(
      () => props.questionContent,
      (newContent) => {
        if (getMergedQuestionMarkdown()) return;
        editorInstance?.setQuestionContent(newContent);
      },
    );

    watch(
      () => [props.questionMarkdown, props.config, props.question],
      () => {
        const merged = getMergedQuestionMarkdown();
        if (!merged) return;
        editorInstance?.setQuestionMarkdown(merged.value || "", merged);
      },
      { deep: true },
    );

    watch(
      () => props.question,
      (newQ) => {
        if (!newQ) return;

        // Update Question Content if prop not set
        if (
          !props.questionContent &&
          !getMergedQuestionMarkdown() &&
          newQ.description
        ) {
          editorInstance?.setQuestionContent(newQ.description);
        }

        // Update Test Cases if prop not set
        if (
          (!props.testCases || props.testCases.length === 0) &&
          newQ.testCases
        ) {
          testCases.value = JSON.parse(JSON.stringify(newQ.testCases));
          activeTestCaseIndex.value = 0;
        }

        // Update config for languages and templates
        editorInstance?.updateConfig({
          questionConfig: newQ,
          languageTemplates: newQ.languageTemplates,
          supportedLanguages: newQ.supportedLanguages,
        });

        // Update code if editor is empty or using fallback template
        if (editorInstance && newQ.defaultLanguage && newQ.languageTemplates) {
          const currentCode = editorInstance.getValue();
          const currentLang = editorInstance.getLanguage();

          // 如果代码是空的，或者当前语言与题目默认语言一致，则加载题目模板
          if (!currentCode || currentLang === newQ.defaultLanguage) {
            const template = newQ.languageTemplates[currentLang];
            if (template) {
              editorInstance.setValue(template);
            }
          }
        }
      },
      { deep: true },
    );

    watch(
      () => props.showQuestionPanel,
      (show) => {
        if (show) {
          editorInstance?.showQuestionPanel();
        } else {
          editorInstance?.hideQuestionPanel();
        }
      },
    );

    onBeforeUnmount(() => {
      resizeObserver?.disconnect();
      editorInstance?.destroy();
    });

    return {
      wrapperRef,
      containerRef,
      terminalPanelRef,
      activeTab,
      isPanelExpanded,
      activeTestCaseIndex,
      testCases,
      activeTestCase,
      runResult,
      panelHeight,
      startResize,
      togglePanel,
      addNewTestCase,
      deleteTestCase,
      activeResultCaseIndex,
      isRunning,
      allTestsPassed,
    };
  },
});
</script>

<style scoped>
.sce-wrapper {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.sce-editor-area {
  width: 100%;
  height: 100%;
}

/* Terminal Panel - will be moved into sce-right-container */
.terminal-panel {
  flex-shrink: 0;
  /* height set via inline style for resizing */
  background: var(--panel-bg, #1e1e1e);
  border-top: 1px solid var(--border-color, #333);
  display: flex;
  flex-direction: column;
  transition: height 0.3s ease;
  position: relative;
}

.terminal-panel.collapsed {
  height: 40px !important;
}

.resize-handle {
  position: absolute;
  top: -4px;
  left: 0;
  right: 0;
  height: 8px;
  cursor: ns-resize;
  z-index: 10;
  background: transparent;
}

.resize-handle:hover {
  background: rgba(255, 255, 255, 0.1);
}

.panel-tabs {
  display: flex;
  align-items: center;
  height: 40px;
  background: var(--header-bg, #252526);
  border-bottom: 1px solid var(--border-color, #333);
  padding: 0 8px;
  gap: 16px;
  flex-shrink: 0;
}

.tab-item {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  padding: 6px 12px;
  border-radius: 4px;
  font-size: 13px;
  color: var(--text-color, #cccccc);
  opacity: 0.7;
  transition: opacity 0.2s;
}

.tab-item:hover {
  opacity: 1;
}

.tab-item.active {
  opacity: 1;
  font-weight: 500;
}

.tab-item .icon {
  font-size: 14px;
}

.panel-actions {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

.icon-toggle {
  background: none;
  border: none;
  color: var(--text-color, #cccccc);
  cursor: pointer;
  font-size: 14px;
  opacity: 0.6;
  transition: opacity 0.2s;
}

.icon-toggle:hover {
  opacity: 1;
}

.panel-content {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
  font-family: -apple-system, sans-serif;
}

.case-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.case-tab-btn {
  background: transparent;
  border: none;
  color: var(--text-color, #cccccc);
  padding: 6px 10px;
  border-radius: 16px;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s;
  opacity: 0.8;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  position: relative;
}

.case-tab-btn:hover {
  background: var(--hover-bg, #3c3c3c);
  opacity: 1;
}

.case-tab-btn.active {
  background: var(--hover-bg, #3c3c3c);
  /* color: white; */
  font-weight: 500;
  opacity: 1;
}

.case-tab-btn.add {
  padding: 6px 10px;
}

.case-close-btn {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 16px;
  height: 16px;
  display: none;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  opacity: 1;
  transition: transform 0.2s;
  transform: scale(1);
  border-radius: 50%;
  background: rgba(128, 128, 128, 0.5);
  color: #fff;
}

.case-tab-btn:hover .case-close-btn {
  display: flex;
}

.case-close-btn:hover {
  opacity: 1;
  background: #f44336;
}

.case-inputs .input-group {
  margin-bottom: 16px;
}

.case-inputs label {
  display: block;
  font-size: 12px;
  color: var(--text-color, #cccccc);
  margin-bottom: 6px;
  opacity: 0.8;
  font-family: monospace;
}

.input-box-wrapper {
  background: var(--header-bg, #252526);
  border: 1px solid var(--border-color, #333);
  border-radius: 6px;
  padding: 4px;
  font-size: 0;
}

.input-box-edit {
  width: 100%;
  background: transparent;
  border: none;
  color: var(--text-color, #cccccc);
  font-family: monospace;
  font-size: 13px;
  resize: none;
  outline: none;
  padding: 4px 8px;
}

.input-box {
  background: var(--header-bg, #252526);
  border: 1px solid var(--border-color, #333);
  border-radius: 6px;
  padding: 8px 12px;
  font-family: monospace;
  font-size: 13px;
  color: var(--text-color, #cccccc);
  white-space: pre-wrap;
  word-break: break-word;
}

.result-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.result-title {
  font-size: 18px;
  font-weight: 600;
}

.result-title.success {
  color: #4caf50;
}

.result-title.error {
  color: #ef5350;
}

.result-meta {
  font-size: 13px;
  color: var(--text-color);
  opacity: 0.6;
}

.result-tabs {
  margin-bottom: 20px;
}

.case-tab-btn.passed .status-dot {
  background: #4caf50;
}

.case-tab-btn.failed .status-dot {
  background: #ef5350;
}

.case-tab-btn.error .status-dot {
  background: #ef5350;
}

.status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ccc;
  display: inline-block;
  margin-right: 4px;
}

/* Override default active style for result tabs */
.result-tabs .case-tab-btn {
  background: var(--hover-bg);
  color: var(--text-color);
}
.result-tabs .case-tab-btn.active {
  background: var(--active-bg);
}

.input-group label {
  margin-bottom: 8px;
  display: block;
  color: var(--text-color);
  opacity: 0.7;
}

.code-block {
  background: var(--header-bg);
  border: 1px solid var(--border-color);
  border-radius: 6px;
  padding: 12px;
  font-family: monospace;
  font-size: 13px;
  color: var(--text-color);
  white-space: pre-wrap;
  word-break: break-work;
  margin-bottom: 16px;
}

.code-block.success {
  /* 弱绿色背景? 根据 mock design，其实是普通的灰色背景，只是文字颜色可能不同？ */
  /* Mockup shows text is green for Expected */
  color: #4caf50;
  font-weight: 500;
}

.code-block.error {
  color: #ef5350;
}

.param-line {
  margin-bottom: 4px;
}

.param-name {
  color: var(--text-color);
  opacity: 0.6;
  margin-right: 8px;
}

.param-value {
  font-weight: 500;
}

.error-box {
  background: rgba(239, 83, 80, 0.1);
  border: 1px solid #ef5350;
  color: #ef5350;
  padding: 12px;
  border-radius: 6px;
  margin-bottom: 16px;
  white-space: pre-wrap;
}

.empty-state {
  color: var(--text-color, #cccccc);
  opacity: 0.5;
  margin-top: 20px;
  text-align: center;
}
</style>
