<template>
  <div class="closure-demo">
    <div class="demo-header">
      <span class="icon">🎁</span>
      <span class="title">函数与闭包</span>
      <span class="subtitle">理解作用域链和闭包机制</span>
    </div>

    <div class="intro-text">
      想象你有个<span class="highlight">背包</span>（函数），每次出门时都会把当时看到的
      <span class="highlight">风景</span>（外部变量）装进去。
      <span class="highlight">闭包</span>就是这个背包——即使离开了那个地方，你依然能拿出当时装的风景
    </div>

    <div class="demo-tabs">
      <button
        v-for="tab in tabs"
        :key="tab.id"
        @click="activeTab = tab.id"
        class="tab-btn"
        :class="{ active: activeTab === tab.id }"
      >
        {{ tab.label }}
      </button>
    </div>

    <!-- 函数基础 -->
    <div v-if="activeTab === 'basic'" class="tab-content">
      <div class="function-showcase">
        <div class="code-panel">
          <div class="code-title">函数声明方式</div>
          <div class="code-block">
            <div class="code-line comment">// 1. 函数声明</div>
            <div class="code-line">function greet(name) {</div>
            <div class="code-line indent">return "Hello " + name</div>
            <div class="code-line">}</div>
            <div class="code-line"></div>
            <div class="code-line comment">// 2. 函数表达式</div>
            <div class="code-line">const greet = function(name) {</div>
            <div class="code-line indent">return "Hello " + name</div>
            <div class="code-line">}</div>
            <div class="code-line"></div>
            <div class="code-line comment">// 3. 箭头函数 (ES6)</div>
            <div class="code-line">const greet = (name) => {</div>
            <div class="code-line indent">return "Hello " + name</div>
            <div class="code-line">}</div>
            <div class="code-line"></div>
            <div class="code-line comment">// 简化版（单行可省略 return）</div>
            <div class="code-line">const greet = name => "Hello " + name</div>
          </div>
        </div>

        <div class="playground">
          <div class="playground-title">试试调用函数</div>
          <div class="input-group">
            <input v-model="functionName" placeholder="输入你的名字" />
            <button @click="callFunction">调用</button>
          </div>
          <div class="output">
            <span v-if="functionResult" class="result">{{ functionResult }}</span>
            <span v-else class="placeholder">点击"调用"按钮看结果...</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 闭包演示 -->
    <div v-else-if="activeTab === 'closure'" class="tab-content">
      <div class="closure-visual">
        <div class="scenario-selector">
          <button @click="closureScenario = 'counter'" :class="{ active: closureScenario === 'counter' }">
            计数器
          </button>
          <button @click="closureScenario = 'config'" :class="{ active: closureScenario === 'config' }">
            配置器
          </button>
        </div>

        <div v-if="closureScenario === 'counter'" class="counter-demo">
          <div class="code-panel small">
            <div class="code-line">function createCounter() {</div>
            <div class="code-line indent">let count = 0 <span class="comment">// 私有变量</span></div>
            <div class="code-line indent">return function() {</div>
            <div class="code-line indent indent">count++</div>
            <div class="code-line indent indent">return count</div>
            <div class="code-line indent">}</div>
            <div class="code-line">}</div>
            <div class="code-line"></div>
            <div class="code-line">const counter = createCounter()</div>
          </div>

          <div class="closure-animation">
            <div class="closure-box">
              <div class="box-title">闭包环境</div>
              <div class="closure-var">
                <span class="var-label">count = </span>
                <span class="var-value">{{ counterValue }}</span>
              </div>
            </div>

            <div class="controls-area">
              <button @click="incrementCounter" class="action-btn primary">
                调用 counter()
              </button>
            </div>

            <div class="explanation">
              <p><strong>发生了什么？</strong></p>
              <ul>
                <li><code>createCounter()</code> 执行后，局部变量 <code>count</code> 本该消失</li>
                <li>但返回的函数"记住"了这个变量（形成了闭包）</li>
                <li>每次调用 <code>counter()</code> 都在访问同一个 <code>count</code></li>
                <li>外部无法直接访问 <code>count</code>（实现了数据私有化）</li>
              </ul>
            </div>
          </div>
        </div>

        <div v-else class="config-demo">
          <div class="code-panel small">
            <div class="code-line">function makeMultiplier(times) {</div>
            <div class="code-line indent">return function(n) {</div>
            <div class="code-line indent indent">return n * times</div>
            <div class="code-line indent">}</div>
            <div class="code-line">}</div>
            <div class="code-line"></div>
            <div class="code-line">const double = makeMultiplier(2)</div>
            <div class="code-line">const triple = makeMultiplier(3)</div>
          </div>

          <div class="multiplier-playground">
            <div class="function-list">
              <div class="func-item" @click="activeMultiplier = 'double'" :class="{ active: activeMultiplier === 'double' }">
                <div class="func-name">double = makeMultiplier(2)</div>
                <div class="func-desc">闭包捕获 times = 2</div>
              </div>
              <div class="func-item" @click="activeMultiplier = 'triple'" :class="{ active: activeMultiplier === 'triple' }">
                <div class="func-name">triple = makeMultiplier(3)</div>
                <div class="func-desc">闭包捕获 times = 3</div>
              </div>
            </div>

            <div class="multiplier-input">
              <input v-model.number="multiplyNumber" type="number" placeholder="输入数字" />
              <button @click="doMultiply">计算</button>
            </div>

            <div v-if="multiplyResult" class="multiply-result">
              <span class="result-equation">{{ multiplyResult }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 作用域链 -->
    <div v-else class="tab-content">
      <div class="scope-chain-demo">
        <div class="nested-visual">
          <div class="scope-level global">
            <div class="level-title">全局作用域</div>
            <div class="level-vars">
              <span class="var-tag">globalVar = "全局"</span>
            </div>

            <div class="scope-level outer">
              <div class="level-title">外层函数作用域</div>
              <div class="level-vars">
                <span class="var-tag">outerVar = "外层"</span>
              </div>

              <div class="scope-level inner">
                <div class="level-title">内层函数作用域</div>
                <div class="level-vars">
                  <span class="var-tag">innerVar = "内层"</span>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="lookup-demo">
          <div class="lookup-title">🔍 变量查找过程（作用域链）</div>
          <div class="lookup-steps">
            <div class="lookup-step" v-for="(step, i) in lookupSteps" :key="i">
              <div class="step-num">{{ i + 1 }}</div>
              <div class="step-content">{{ step }}</div>
            </div>
          </div>

          <div class="lookup-rule">
            <strong>查找规则：</strong>
            从当前作用域开始，逐层向外查找，直到全局作用域。找不到则报错 ReferenceError。
          </div>
        </div>
      </div>
    </div>

    <div class="info-box">
      <span class="icon">💡</span>
      <strong>核心思想：</strong>
      <span v-if="activeTab === 'basic'">函数是 JavaScript 中的一等公民，可以赋值给变量、作为参数传递、作为返回值。箭头函数更简洁，且不绑定自己的 this。</span>
      <span v-else-if="activeTab === 'closure'">闭包是函数和声明该函数的词法环境的组合。它让函数可以访问外部作用域的变量，即使外部函数已经执行完毕。闭包常用于数据私有化、函数工厂、模块化等场景。</span>
      <span v-else>作用域链是 JavaScript 查找变量的机制。当访问一个变量时，引擎会先在当前作用域查找，找不到就去外层作用域找，直到全局作用域。这种机制让内层函数可以访问外层变量，形成了闭包的基础。</span>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const activeTab = ref('basic')
const functionName = ref('')
const functionResult = ref('')
const counterValue = ref(0)
const closureScenario = ref('counter')
const activeMultiplier = ref('double')
const multiplyNumber = ref(null)
const multiplyResult = ref('')

const tabs = [
  { id: 'basic', label: '函数基础' },
  { id: 'closure', label: '闭包' },
  { id: 'scope', label: '作用域链' }
]

const lookupSteps = ref([
  '内层函数访问 innerVar → 在当前作用域找到 ✓',
  '内层函数访问 outerVar → 当前找不到，向外层查找 ✓',
  '内层函数访问 globalVar → 继续向外，在全局作用域找到 ✓',
  '内层函数访问 unknownVar → 所有作用域都找不到 ✗ ReferenceError'
])

const callFunction = () => {
  if (functionName.value.trim()) {
    functionResult.value = `Hello ${functionName.value}`
  }
}

const incrementCounter = () => {
  counterValue.value++
}

const doMultiply = () => {
  if (multiplyNumber.value !== null) {
    const times = activeMultiplier.value === 'double' ? 2 : 3
    multiplyResult.value = `${multiplyNumber.value} × ${times} = ${multiplyNumber.value * times}`
  }
}
</script>

<style scoped>
.closure-demo {
  border: 1px solid var(--vp-c-divider);
  border-radius: 8px;
  background: var(--vp-c-bg-soft);
  padding: 1rem;
}

.demo-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }

.intro-text {
  font-size: 0.9rem;
  line-height: 1.6;
  margin-bottom: 1rem;
  color: var(--vp-c-text-1);
}

.highlight {
  background: var(--vp-c-brand-soft);
  color: var(--vp-c-brand);
  padding: 0.1rem 0.3rem;
  border-radius: 4px;
  font-weight: 500;
}

.demo-tabs {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--vp-c-divider);
  padding-bottom: 0.5rem;
}

.tab-btn {
  background: transparent;
  border: none;
  padding: 0.5rem 1rem;
  cursor: pointer;
  color: var(--vp-c-text-2);
  font-size: 0.9rem;
  border-radius: 6px;
  transition: all 0.2s;
}

.tab-btn:hover {
  background: var(--vp-c-bg-soft);
}

.tab-btn.active {
  background: var(--vp-c-brand);
  color: white;
}

.tab-content {
  min-height: 380px;
}

.function-showcase {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.code-panel {
  background: #1e1e1e;
  border-radius: 6px;
  padding: 0.75rem;
  font-family: 'Monaco', 'Menlo', monospace;
  font-size: 0.8rem;
  color: #d4d4d4;
}

.code-panel.small {
  font-size: 0.75rem;
  padding: 0.5rem;
}

.code-title {
  color: #888;
  font-size: 0.7rem;
  margin-bottom: 0.5rem;
  text-transform: uppercase;
}

.code-line {
  padding: 0.1rem 0;
  line-height: 1.4;
}

.code-line.indent {
  padding-left: 1.5rem;
}

.code-line.indent.indent {
  padding-left: 3rem;
}

.code-line .comment {
  color: #6a9955;
}

.code-line :deep(code) {
  background: #333;
  padding: 0.1rem 0.3rem;
  border-radius: 3px;
}

.playground {
  background: var(--vp-c-bg);
  border-radius: 6px;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.playground-title {
  font-weight: 600;
  color: var(--vp-c-text-1);
  font-size: 0.9rem;
}

.input-group {
  display: flex;
  gap: 0.5rem;
}

.input-group input {
  flex: 1;
  padding: 0.5rem;
  border: 1px solid var(--vp-c-divider);
  border-radius: 6px;
  background: var(--vp-c-bg-soft);
  color: var(--vp-c-text-1);
}

.input-group button {
  background: var(--vp-c-brand);
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 6px;
  cursor: pointer;
}

.output {
  background: var(--vp-c-bg-soft);
  border-radius: 6px;
  padding: 0.75rem;
  min-height: 2.5rem;
  display: flex;
  align-items: center;
}

.output .result {
  color: var(--vp-c-brand);
  font-weight: 600;
  font-size: 1.1rem;
}

.output .placeholder {
  color: var(--vp-c-text-3);
  font-size: 0.85rem;
}

.scenario-selector {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.scenario-selector button {
  flex: 1;
  padding: 0.5rem;
  background: var(--vp-c-bg);
  border: 1px solid var(--vp-c-divider);
  border-radius: 6px;
  cursor: pointer;
  color: var(--vp-c-text-2);
  transition: all 0.2s;
}

.scenario-selector button:hover {
  border-color: var(--vp-c-brand);
}

.scenario-selector button.active {
  background: var(--vp-c-brand);
  color: white;
  border-color: var(--vp-c-brand);
}

.closure-visual {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.counter-demo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.closure-animation {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.closure-box {
  background: var(--vp-c-brand-soft);
  border: 2px solid var(--vp-c-brand);
  border-radius: 8px;
  padding: 1rem;
  text-align: center;
}

.box-title {
  font-weight: 600;
  color: var(--vp-c-brand);
  margin-bottom: 0.5rem;
}

.closure-var {
  font-size: 1.5rem;
  font-weight: bold;
}

.var-label {
  color: var(--vp-c-text-2);
}

.var-value {
  color: var(--vp-c-brand);
  font-size: 2rem;
}

.controls-area {
  display: flex;
  justify-content: center;
}

.action-btn {
  background: var(--vp-c-brand);
  color: white;
  border: none;
  padding: 0.75rem 1.5rem;
  border-radius: 6px;
  font-size: 1rem;
  cursor: pointer;
  transition: opacity 0.2s;
}

.action-btn:hover {
  opacity: 0.9;
}

.explanation {
  background: var(--vp-c-bg-alt);
  border-radius: 6px;
  padding: 0.75rem;
  font-size: 0.85rem;
}

.explanation p {
  margin: 0 0 0.5rem 0;
  font-weight: 600;
  color: var(--vp-c-text-1);
}

.explanation ul {
  margin: 0;
  padding-left: 1.2rem;
  color: var(--vp-c-text-2);
  line-height: 1.6;
}

.explanation code {
  background: var(--vp-c-bg-soft);
  padding: 0.1rem 0.3rem;
  border-radius: 3px;
  font-family: monospace;
}

.config-demo {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.multiplier-playground {
  background: var(--vp-c-bg);
  border-radius: 6px;
  padding: 0.75rem;
}

.function-list {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.func-item {
  flex: 1;
  background: var(--vp-c-bg-soft);
  border: 2px solid var(--vp-c-divider);
  border-radius: 6px;
  padding: 0.75rem;
  text-align: center;
  cursor: pointer;
  transition: all 0.2s;
}

.func-item:hover {
  border-color: var(--vp-c-brand);
}

.func-item.active {
  border-color: var(--vp-c-brand);
  background: var(--vp-c-brand-soft);
}

.func-name {
  font-weight: 600;
  font-family: monospace;
  margin-bottom: 0.25rem;
  color: var(--vp-c-text-1);
}

.func-desc {
  font-size: 0.75rem;
  color: var(--vp-c-text-3);
}

.multiplier-input {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.multiplier-input input {
  flex: 1;
  padding: 0.5rem;
  border: 1px solid var(--vp-c-divider);
  border-radius: 6px;
  background: var(--vp-c-bg-soft);
  color: var(--vp-c-text-1);
}

.multiplier-input button {
  background: var(--vp-c-brand);
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 6px;
  cursor: pointer;
}

.multiply-result {
  background: var(--vp-c-bg-soft);
  border-radius: 6px;
  padding: 1rem;
  text-align: center;
}

.result-equation {
  font-size: 1.2rem;
  font-weight: bold;
  color: var(--vp-c-brand);
}

.scope-chain-demo {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.nested-visual {
  background: var(--vp-c-bg);
  border-radius: 6px;
  padding: 1rem;
}

.scope-level {
  border: 2px solid var(--vp-c-divider);
  border-radius: 6px;
  padding: 0.75rem;
  position: relative;
}

.scope-level.global {
  background: #f5f5f5;
}

.scope-level.outer {
  background: #e8f5e9;
  margin: 0.5rem 0 0.5rem 0.5rem;
  border-color: #c8e6c9;
}

.scope-level.inner {
  background: #e3f2fd;
  margin: 0.5rem 0 0 0.5rem;
  border-color: #bbdefb;
}

.level-title {
  font-weight: 600;
  font-size: 0.85rem;
  margin-bottom: 0.5rem;
  text-transform: uppercase;
  color: var(--vp-c-text-2);
}

.level-vars {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.var-tag {
  background: white;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  font-size: 0.8rem;
  font-family: monospace;
  border: 1px solid var(--vp-c-divider);
}

.lookup-demo {
  background: var(--vp-c-bg-alt);
  border-radius: 6px;
  padding: 0.75rem;
}

.lookup-title {
  font-weight: 600;
  margin-bottom: 0.5rem;
  color: var(--vp-c-text-1);
}

.lookup-steps {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.lookup-step {
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
}

.step-num {
  background: var(--vp-c-brand);
  color: white;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 600;
  flex-shrink: 0;
}

.step-content {
  font-size: 0.85rem;
  color: var(--vp-c-text-2);
  line-height: 1.4;
}

.lookup-rule {
  background: white;
  padding: 0.5rem;
  border-radius: 4px;
  font-size: 0.85rem;
  color: var(--vp-c-text-2);
}

.info-box {
  background: var(--vp-c-bg-alt);
  padding: 0.75rem;
  border-radius: 6px;
  font-size: 0.85rem;
  color: var(--vp-c-text-2);
  margin-top: 0.75rem;
  display: flex;
  gap: 0.25rem;
}

.info-box .icon { flex-shrink: 0; }

@media (max-width: 768px) {
  .function-showcase {
    grid-template-columns: 1fr;
  }

  .counter-demo {
    grid-template-columns: 1fr;
  }
}
</style>
