<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
  Button as VanButton,
  Empty as VanEmpty,
  Icon as VanIcon,
  Loading as VanLoading,
  Popup as VanPopup,
} from 'vant'
import { computed, ref, watch } from 'vue'

/**
 * 级联选择器的通用节点结构。
 *
 * 本组件的目标是支持“任意层级”的多级选择：
 * 1) 第一级：通过 `rootOptions` 提供选项
 * 2) 中间级：点击某个节点后，如果节点有 `children` 直接进入下一层
 *    - 如果节点没有 `children`，则通过 `loadChildren` 异步拉取下一层数据
 * 3) 最后一级：当节点满足 `is_leaf === true`（或没有可继续加载的 children）
 *    就会触发 `confirm` 事件，并把“完整路径”回传给父组件
 */
export interface CascadeOption {
  // 节点唯一标识；必须可用于 key 比较以及作为加载状态的判断依据
  id: string | number
  // 节点展示文案（例如 小区名 / 楼栋名 / 单元楼层名等）
  label: string
  /**
   * 第一级的小区副标题（例如 “2栋”）。
   *
   * 为了满足你“去掉 extra，把字段放同级”的约定，这里把原本 `extra.sub_text`
   * 扁平化为同级字段。
   */
  sub_text?: string

  /**
   * 叶子/门牌区域的附加信息（用于默认渲染卡片样式）。
   * - `code`：例如 U001
   * - `status_text`：例如 入户/未检
   * - `status_type`：例如 '#16a34a'（用于计算背景色）
   */
  code?: string
  status_text?: string
  status_type?: string
  // 可选：直接给出下一层 children
  children?: CascadeOption[]
  // 是否叶子节点（到这里点击后即认为选项完成）
  is_leaf?: boolean
}

/**
 * 最终确认后向外回传的 payload：
 * - `path`：从第一级到最后一级的节点链路（包含点击的每一层）
 * - `leaf`：最终点击确认的那一个节点
 */
interface CascadeConfirmPayload {
  leaf: CascadeOption
  path: CascadeOption[]
}

interface ExpandedOptionLabelSlotPayload {
  item: CascadeOption
  levelIndex: number
  pathNodes: CascadeOption[]
}

interface ExpandedFloorHeaderSlotPayload {
  unit: CascadeOption
  floor: CascadeOption
  levelIndex: number
  pathNodes: CascadeOption[]
}

/**
 * 组件对外参数：
 * - `modelValue`：是否显示弹层（v-model）
 * - `title`：顶部标题
 * - `rootOptions`：第一级选项（必须）
 * - `loadChildren`：当节点没有 children 时，用于异步加载下一层数据
 */
const props = withDefaults(defineProps<{
  // 弹层显示开关（v-model）
  modelValue: boolean
  // 顶部标题（可选）
  title?: string
  // 第一层选项
  rootOptions: CascadeOption[]
  /**
   * 需要“展开展示”的层级索引（0-based）
   *
   * 例：
   * - `2` 表示当当前层是第3层时，不再通过点击单元进入下一层，
   *   而是直接把该层节点的 children（甚至 grandchildren）在一个页面里展开。
   */
  expandedLevelIndexes?: number[]
  /**
   * 加载子节点的回调
   *
   * 当用户点击了当前层的某个节点：
   * - 如果该节点带有 `children`（且非空），组件直接使用
   * - 否则会调用该函数异步拉取下一层
   *
   * @param node 当前点击的节点
   * @param path 当前已经选中的路径（不包含 nextChildren）
   * @param levelIndex 当前点击节点所在的层级索引（0-based）
   * @returns 下一层选项数组
   */
  loadChildren?: (node: CascadeOption, path: CascadeOption[], levelIndex: number) => Promise<CascadeOption[]>

  /**
   * 各层对应的图标列表。
   *
   * - 下标 0 对应第 1 层（小区）
   * - 下标 1 对应第 2 层（楼栋）
   * - 以此类推
   *
   * 组件默认会提供一组图标；父组件可传入自定义值。
   */
  iconList?: string[]

  /**
   * 是否在“最终选中后关闭”时保留当前打开状态。
   *
   * - false: 每次打开都从首层开始
   * - true: 若上次是通过最终选中关闭，则下次打开恢复上次层级与路径
   *
   * 约束：
   * - 仅最终选择触发保存
   * - 手动关闭/返回上一级不会自动保存
   */
  preserveLastStateOnConfirm?: boolean
}>(), {
  title: '选择地址',
  loadChildren: undefined,
  expandedLevelIndexes: () => [],
  iconList: () => ['fa:building', 'fa:building', 'fa6-solid:door-open', 'fa:building'],
  preserveLastStateOnConfirm: false,
})

/**
 * 组件对外事件：
 * - `update:modelValue`：关闭弹层时通知父组件更新 v-model
 * - `confirm`：用户完成选择（通常是最后一级点击）时触发
 */
const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void
  (e: 'confirm', payload: CascadeConfirmPayload): void
}>()

/**
 * `pathNodes`：当前已选中的节点链路（每点一层就追加一个节点）
 * 例如：小区 -> 楼栋 -> 单元 -> 楼层
 */
const pathNodes = ref<CascadeOption[]>([])

/**
 * `levelOptions`：每一层的候选项数组集合
 * - 第0层：levelOptions[0] = rootOptions
 * - 当用户点击第0层某节点后：会把它的 children/加载结果放到 levelOptions[1]
 *
 * 这里的数组长度天然等于“当前已经展开到的层级数量”
 */
const levelOptions = ref<CascadeOption[][]>([])

// 异步加载状态（用于显示 loading）
const isLoading = ref(false)
// 当前正在加载的节点 id（用于只在对应按钮上显示 loading）
const loadingNodeId = ref<string | number | null>(null)

// 不同层级使用的图标：支持父组件传递；不传则使用默认值
const iconList = computed(() => props.iconList)

// “最终选中关闭”后缓存的层级状态（组件实例内缓存，组件销毁后会丢失）
const savedPathNodes = ref<CascadeOption[] | null>(null)
const savedLevelOptions = ref<CascadeOption[][] | null>(null)

/**
 * 当前展示的层级索引（0-based）
 * - 如果 levelOptions 里有 1 个数组：表示只展示第1层（索引 0）
 * - 如果 levelOptions 里有 2 个数组：表示展示第2层（索引 1）
 */
const currentLevelIndex = computed(() => {
  return Math.max(levelOptions.value.length - 1, 0)
})

/**
 * 当前层要渲染的选项数组
 * 注意：当展开到下一层时，这个 computed 会自动刷新
 */
const currentOptions = computed(() => {
  return levelOptions.value[currentLevelIndex.value] || []
})

/**
 * 当前层是否启用“展开展示模式”。
 * 启用后会渲染：
 * 当前层节点(如单元) -> 下级节点(如楼层) -> 叶子节点(如户号)
 */
const isExpandedLevel = computed(() => {
  return props.expandedLevelIndexes.includes(currentLevelIndex.value)
})

/**
 * 初始化/重置展开层级数据。
 *
 * 当弹层刚打开、或者 rootOptions 发生变化时，会调用此方法：
 * - 清空用户已经选择的路径
 * - 只保留第一级候选项
 * - 清空 loading 状态
 */
function initLevels() {
  pathNodes.value = []
  levelOptions.value = [props.rootOptions || []]
  isLoading.value = false
  loadingNodeId.value = null
}

function hasSavedState(): boolean {
  return !!savedPathNodes.value && !!savedLevelOptions.value
}

// 恢复缓存状态时使用深拷贝，避免响应式引用互相污染
function restoreSavedState() {
  if (!hasSavedState())
    return
  pathNodes.value = JSON.parse(JSON.stringify(savedPathNodes.value))
  levelOptions.value = JSON.parse(JSON.stringify(savedLevelOptions.value))
  isLoading.value = false
  loadingNodeId.value = null
}

function saveCurrentStateForNextOpen() {
  savedPathNodes.value = JSON.parse(JSON.stringify(pathNodes.value))
  savedLevelOptions.value = JSON.parse(JSON.stringify(levelOptions.value))
}

function clearSavedState() {
  savedPathNodes.value = null
  savedLevelOptions.value = null
}

function stripChildrenFromPath(path: CascadeOption[]): CascadeOption[] {
  return path.map((node) => {
    const { children, ...rest } = node
    return rest
  })
}

/**
 * 统一“最终选中”出口：
 * 1) 回传 payload 给父组件
 * 2) 根据配置决定是否保存当前状态
 * 3) 关闭弹层
 */
function finalizeSelection(payload: CascadeConfirmPayload) {
  emit('confirm', {
    ...payload,
    path: stripChildrenFromPath(payload.path),
  })
  if (props.preserveLastStateOnConfirm) {
    saveCurrentStateForNextOpen()
  }
  else {
    clearSavedState()
  }
  closePopup()
}

// 当弹层从“隐藏 -> 显示”时，初始化层级（每次打开都从第一级开始）
watch(() => props.modelValue, (visible) => {
  if (visible) {
    // 若启用了“确认后保留状态”且缓存可用，优先恢复
    if (props.preserveLastStateOnConfirm && hasSavedState()) {
      restoreSavedState()
    }
    else {
      // 无缓存时回到首层默认状态
      initLevels()
    }
  }
})

// rootOptions 数据变更时，如果弹层已经打开，则重新初始化
watch(() => props.rootOptions, () => {
  if (!props.modelValue)
    return
  // 这里不清空 savedState，避免影响“下次打开恢复”能力
  initLevels()
}, { deep: true })

/**
 * 关闭弹层：通过 emit 通知父组件更新 v-model
 * 注意：不在这里触发 confirm。
 */
function closePopup() {
  emit('update:modelValue', false)
}

/**
 * 返回上一层逻辑：
 * - 如果已经在第一级（只有一个层级数组），则直接关闭弹层
 * - 否则：
 *   - 截断 levelOptions（去掉最后一层）
 *   - 截断 pathNodes（去掉最后一次选择的节点）
 */
function handleBack() {
  if (levelOptions.value.length <= 1) {
    closePopup()
    return
  }
  levelOptions.value = levelOptions.value.slice(0, -1)
  pathNodes.value = pathNodes.value.slice(0, -1)
}

/**
 * 点击当前层某个选项时的行为：
 * 1) 拼接出 `nextPath`（当前层路径 + 被点击的 option）
 * 2) 如果该节点是叶子（option.is_leaf）：直接 confirm 并关闭
 * 3) 如果该节点已有 children：直接进入下一层并渲染 children
 * 4) 如果该节点没有 children：
 *    - 如果没有提供 loadChildren：把它当作叶子（confirm 并关闭）
 *    - 否则异步加载 children，加载成功则进入下一层，否则当作叶子 confirm
 */
async function handleOptionClick(option: CascadeOption) {
  // 在展开模式下，当前层点击行为由“内部明细点击”接管，避免误触发原始跳层逻辑
  if (isExpandedLevel.value) {
    return
  }

  const levelIndex = currentLevelIndex.value
  const nextPath = [...pathNodes.value.slice(0, levelIndex), option]

  if (option.is_leaf) {
    finalizeSelection({ leaf: option, path: nextPath })
    return
  }

  // 若当前节点直接给了 children，优先使用本地数据
  if (Array.isArray(option.children) && option.children.length > 0) {
    pathNodes.value = nextPath
    levelOptions.value = [...levelOptions.value.slice(0, levelIndex + 1), option.children]
    return
  }

  // 如果没有 children 且没有提供异步加载函数：按“无法继续”的结果结束选择
  if (!props.loadChildren) {
    finalizeSelection({ leaf: option, path: nextPath })
    return
  }

  // 进入异步加载模式：显示 loading，避免用户反复点击造成并发问题
  isLoading.value = true
  loadingNodeId.value = option.id
  try {
    // loadChildren 由业务方实现，返回下一层选项
    const children = await props.loadChildren(option, nextPath, levelIndex)
    const nextChildren = Array.isArray(children) ? children : []

    // 约定：如果加载到的 children 为空，则认为当前 option 是最后一级
    if (nextChildren.length === 0) {
      finalizeSelection({ leaf: option, path: nextPath })
      return
    }

    // 加载成功后进入下一层渲染
    pathNodes.value = nextPath
    levelOptions.value = [...levelOptions.value.slice(0, levelIndex + 1), nextChildren]
  }
  finally {
    // 无论成功失败都关闭 loading
    isLoading.value = false
    loadingNodeId.value = null
  }
}

/**
 * 展开模式下，点击“楼层”节点：
 * - 若楼层本身是叶子，直接完成选择
 * - 若楼层存在户号 children，则进入下一步由户号按钮确认
 */
function handleExpandedFloorClick(unit: CascadeOption, floor: CascadeOption) {
  const levelIndex = currentLevelIndex.value
  const basePath = pathNodes.value.slice(0, levelIndex)
  const floorPath = [...basePath, unit, floor]

  if (floor.is_leaf || !Array.isArray(floor.children) || floor.children.length === 0) {
    finalizeSelection({ leaf: floor, path: floorPath })
  }
}

/**
 * 展开模式下，点击“户号”节点后直接回传完整路径。
 */
function handleExpandedLeafClick(unit: CascadeOption, floor: CascadeOption, leaf: CascadeOption) {
  const levelIndex = currentLevelIndex.value
  const basePath = pathNodes.value.slice(0, levelIndex)
  const fullPath = [...basePath, unit, floor, leaf]
  finalizeSelection({ leaf, path: fullPath })
}

/**
 * 点击“进入”：
 * - 直接选择当前 unit（门牌号所属单元）
 * - 回传选中路径给父组件
 * - 同时关闭当前弹层
 */
function handleExpandedUnitEnter(unit: CascadeOption) {
  const nextPath = [...pathNodes.value, unit]
  finalizeSelection({ leaf: unit, path: nextPath })
}

/**
 * 提供给 option-label 插槽的参数构造函数。
 * 说明：
 * - 普通模式：item 为当前层的直接选项（小区/楼栋/单元等）
 * - 展开模式：item 通常是楼层节点（由调用方决定渲染文案）
 */
function getOptionLabelSlotPayload(item: CascadeOption): ExpandedOptionLabelSlotPayload {
  // 将当前层级/路径透出给插槽，便于父组件按层级定制渲染
  return {
    item,
    levelIndex: currentLevelIndex.value,
    pathNodes: pathNodes.value,
  }
}

/**
 * 提供给 expanded-floor-header 插槽的参数构造函数。
 */
function getExpandedFloorHeaderSlotPayload(unit: CascadeOption, floor: CascadeOption): ExpandedFloorHeaderSlotPayload {
  // 扩展插槽上下文，便于业务组合“单元 + 门牌”展示
  return {
    unit,
    floor,
    levelIndex: currentLevelIndex.value,
    pathNodes: pathNodes.value,
  }
}
</script>

<template>
  <!--
    底部弹层：
    - `v-model` 控制显示
    - `position="bottom"` 贴合移动端体验
    - `closeable` 允许点击右上角关闭
  -->
  <VanPopup
    :show="modelValue"
    position="bottom"
    round
    closeable
    :style="{ height: '72vh' }"
    @click-close-icon="closePopup"
    @update:show="(val) => emit('update:modelValue', val)"
  >
    <div class="cascade-picker">
      <!-- 顶部栏：返回上一层 + 标题 -->
      <div class="header">
        <VanIcon name="arrow-left" size="20" class="back-icon" @click="handleBack" />
        <div class="title">
          <!--
            标题策略：
            - 如果当前已选了至少一层，展示“上一层的 label”
            - 否则展示外部传入 title
          -->
          {{ pathNodes[currentLevelIndex - 1]?.label || title }}
        </div>
      </div>

      <!-- 内容区：渲染当前层 options -->
      <div class="content">
        <!-- 面包屑：展示当前路径（便于用户理解层级位置） -->
        <div v-if="pathNodes.length > 0" class="path-breadcrumb">
          <VanIcon name="wap-home" size="25" color="#2563eb" />
          <div class="path-breadcrumb-text">
            <span v-for="(item, index) in pathNodes" :key="`${item.id}_${index}`">
              <!-- 第一个用 item.label，其余用 “ / ”分隔 -->
              {{ index === 0 ? item.label : ` - ${item.label}` }}
            </span>
          </div>
        </div>

        <!-- 当前层无数据时显示空态（且不在加载中） -->
        <VanEmpty v-if="currentOptions.length === 0 && !isLoading" description="暂无数据" />
        <div v-else-if="!isExpandedLevel" class="grid">
          <VanButton
            v-for="item in currentOptions"
            :key="item.id"
            class="option-btn"
            plain
            block
            @click="handleOptionClick(item)"
          >
            <slot name="option-label" v-bind="getOptionLabelSlotPayload(item)">
              <div class="default-option-label">
                <!-- 第一行：图标 + 标题（同一行） -->
                <div class="default-option-top">
                  <Icon v-if="iconList[currentLevelIndex]" :icon="iconList[currentLevelIndex]" style="color: #9ca3af; font-size: 14px;" />
                  <div class="default-option-title">
                    {{ item.label }}
                  </div>
                </div>

                <!-- 第二行：副标题居中（仅在第一层展示） -->
                <div
                  v-if="item.sub_text"
                  class="default-option-subtext"
                >
                  {{ item.sub_text }}
                </div>
                <div
                  v-if="item.status_text"
                  class="house-status default-option-status"
                  :style="{
                    color: item.status_type || '#6b7280',
                    backgroundColor: `${(item.status_type || '#6b7280')}22`,
                  }"
                >
                  {{ item.status_text }}
                </div>
              </div>
            </slot>
            <!-- 只在“正在加载的节点”上显示 loading，避免全局 loading 造成错觉 -->
            <VanLoading
              v-if="isLoading && loadingNodeId === item.id"
              size="14"
              class="item-loading"
            />
          </VanButton>
        </div>
        <div v-else class="expanded-section-list">
          <div
            v-for="unit in currentOptions"
            :key="unit.id"
            class="expanded-unit-card"
          >
            <div class="expanded-unit">
              <div class="expanded-unit-header">
                <VanIcon name="coupon" size="16" color="#1e40af" />
                <span class="expanded-unit-title">{{ unit.label }}</span>
              </div>
              <span class="expanded-unit-value">  共 {{ unit.children?.length || 0 }} 户</span>
              <span class="expanded-unit-enter" @click="handleExpandedUnitEnter(unit)">
                进入
              </span>
            </div>
            <div
              v-for="floor in (unit.children || [])"
              :key="floor.id"
              class="expanded-floor-block"
              :class="{ 'leaf-floor-block': !floor.children || floor.children.length === 0 }"
            >
              <div class="expanded-floor-header" @click="handleExpandedFloorClick(unit, floor)">
                <slot name="expanded-floor-header" v-bind="getExpandedFloorHeaderSlotPayload(unit, floor)">
                  <div class="default-house-card">
                    <div class="house-no">
                      {{ floor.label }}
                    </div>
                    <div class="house-code">
                      {{ floor.code || '' }}
                    </div>
                    <div
                      class="house-status"
                      :style="{
                        color: floor.status_type || '#6b7280',
                        backgroundColor: `${(floor.status_type || '#6b7280')}22`,
                      }"
                    >
                      {{ floor.status_text || '未检' }}
                    </div>
                  </div>
                </slot>
              </div>
              <div v-if="floor.children && floor.children.length > 0" class="expanded-house-grid">
                <VanButton
                  v-for="house in (floor.children || [])"
                  :key="house.id"
                  class="house-btn"
                  plain
                  @click="handleExpandedLeafClick(unit, floor, house)"
                >
                  {{ house.label }}
                </VanButton>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </VanPopup>
</template>

<style scoped lang="less">
.cascade-picker {
  // 弹层内部整体采用纵向布局
  height: 100%;
  display: flex;
  flex-direction: column;
  // 背景色与移动端卡片风格保持一致
  background: #fff;

  .header {
    // 顶部固定高度
    height: 52px;
    display: flex;
    align-items: center;
    background: #fff;
    border-bottom: 1px solid #f1f3f5;
    position: relative;

    .back-icon {
      // 返回按钮靠左，使用较高 z-index 避免被标题覆盖
      margin-left: 12px;
      color: #3f4954;
      z-index: 1;
    }

    .title {
      // 标题居中展示
      position: absolute;
      left: 0;
      right: 0;
      text-align: center;
      font-size: 18px;
      font-weight: 600;
      color: #1f2937;
      padding: 0 42px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  .path-breadcrumb {
    // 面包屑区域用于展示当前已选路径
    padding: 4px 0 8px 0;
    font-size: 16px;
    font-weight: 700;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 8px;

    .path-breadcrumb-text {
      flex: 1;
      min-width: 0;
      line-height: 25px; // 首行和 25px icon 垂直居中
      white-space: normal;
      overflow-wrap: anywhere;
      word-break: break-word;
    }
  }

  .content {
    // 内容区可滚动
    flex: 1;
    overflow-y: auto;
    margin: 10px 12px;
    padding: 10px 14px;
    background: #f9fafb;
    border-radius: 10px;
  }

  .grid {
    // 选项网格：两列布局，适配截图中的“卡片格子”风格
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }

  .option-btn {
    // 默认“卡片按钮”样式：对齐 `XCellList` 的 `card_item_main` 风格
    background-color: var(--van-background-2);
    border-radius: var(--van-radius-lg);
    padding: var(--van-padding-sm);
    min-height: 72px;
    height: 72px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
    transition: all 0.3s ease;
    border: 1px solid #e5e7eb;
    position: relative;
    overflow: hidden;

    &:active {
      transform: scale(0.98);
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.02);
    }

    :deep(.van-button__content) {
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .option-label {
      // 旧 class（当未配置 option-label 插槽时不再使用，但保留兼容）
      font-size: var(--van-font-size-lg);
      font-weight: 700;
      color: var(--van-text-color);
      max-width: 90%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .item-loading {
      // loading 右上角显示
      position: absolute;
      right: 8px;
      top: 8px;
    }
  }

  .expanded-section-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .expanded-unit-card {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }

  .expanded-unit {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
  }

  .expanded-unit-enter {
    margin-left: auto;
    font-size: 11px;
    color: #2563eb;
    padding: 4px 12px;
    border-radius: 999px;
    background: #eff6ff;
    cursor: pointer;
  }

  .expanded-unit-header {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: #dbeafe;
    border-radius: 10px;
    padding: 2px 6px;
  }

  .expanded-unit-title {
    font-size: 13px;
    color: #1e40af;
  }

  .expanded-unit-value {
    font-size: 11px;
    color: var(--van-text-color-2);
    margin-left: 2px;
  }

  // coupon 图标当前由 expanded-unit-header 负责胶囊背景

  .expanded-floor-block {
    width: 100%;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
    padding-top: var(--van-padding-xs);
    margin-top: var(--van-padding-xs);
  }

  .leaf-floor-block {
    border-top: none;
    padding-top: 0;
    margin-top: 0;
    width: calc(25% - 6px);
    min-width: 0;

    .expanded-floor-header {
      margin-bottom: 0;
    }
  }

  .expanded-floor-header {
    // header 本身不承载文本样式，实际内容由默认 house-card/插槽决定
    padding: 0;
    margin-bottom: 8px;
  }

  .expanded-house-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px;
  }

  .house-btn {
    // 叶子节点（未使用插槽时）的默认卡片样式
    min-height: 44px;
    border-radius: var(--van-radius-lg);
    padding: var(--van-padding-xs) var(--van-padding-sm);
    background-color: var(--van-background-2);
    border: 1px solid rgba(0, 0, 0, 0.04);
    color: var(--van-text-color);
  }

  .default-option-label {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;

    .default-option-top {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
      width: 100%;
    }

    .default-option-title {
      color: #374151;
      font-size: 14px;
      font-weight: 500;
      max-width: 8em;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      text-align: center;
    }

    .default-option-subtext {
      color: #6b7280;
      font-size: 12px;
      line-height: 16px;
      width: 100%;
      text-align: center;
    }

    .default-option-status {
      margin-top: 2px;
      padding: 1px 8px;
      border-radius: 4px;
      font-size: 11px;
      line-height: 14px;
    }
  }

  .default-house-card {
    width: 100%;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    background: #fff;
    height: 90px;
    padding: 10px 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    .house-no {
      font-size: 18px;
      line-height: 22px;
      font-weight: 700;
      color: #000;
    }

    .house-code {
      margin-top: 5px;
      font-size: 10px;
      color: #94a3b8;
      max-width: 5em;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      text-align: center;
    }

    .house-status {
      margin-top: 6px;
      padding: 1px 8px;
      border-radius: 4px;
      font-size: 11px;
      line-height: 14px;
    }
  }
}
</style>
