<script setup>
import { ref, computed, reactive, watch } from "vue";
import { useNamespace } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
import { useLocale } from "@yh-ui/hooks";
import { smartAddressProps, smartAddressEmits } from "./smart-address";
import { parseAddress } from "./use-address-parser";
import { YhSelect, YhOption } from "../../select";
import { YhCascader } from "../../cascader";
defineOptions({ name: "YhSmartAddress" });
const props = defineProps(smartAddressProps);
const emit = defineEmits(smartAddressEmits);
const ns = useNamespace("smart-address");
const { themeStyle } = useComponentTheme(
  "smart-address",
  computed(() => props.themeOverrides)
);
const { t, tRaw } = useLocale();
const rawText = ref("");
const parseStatus = ref("idle");
const parseTip = ref("");
function getValueByLabel(options, label) {
  if (!label) return null;
  const match = options.find((opt) => opt[props.labelField] === label);
  return match ? match[props.valueField] : null;
}
function handleParse() {
  if (!rawText.value.trim()) return;
  const getKw = (p) => {
    const res = tRaw(p);
    return Array.isArray(res) ? res : void 0;
  };
  const parseOptions = {
    provinceKeywords: getKw("smartaddress.provinceKeywords"),
    cityKeywords: getKw("smartaddress.cityKeywords"),
    districtKeywords: getKw("smartaddress.districtKeywords"),
    streetKeywords: getKw("smartaddress.streetKeywords")
  };
  const result = props.parser ? props.parser(rawText.value) : parseAddress(rawText.value, parseOptions);
  const hasRegion = result.province || result.city || result.district || result.detail;
  if (!hasRegion && !result.phone && !result.name) {
    parseStatus.value = "error";
    parseTip.value = t("smartaddress.parseFailed");
    return;
  }
  const provinceVal = getValueByLabel(props.regionOptions, result.province) || result.province;
  let cityVal = result.city;
  const provinceMatch = props.regionOptions.find((opt) => opt[props.labelField] === result.province);
  const provinceChildren = provinceMatch?.[props.childrenField] || [];
  if (provinceChildren.length) {
    cityVal = getValueByLabel(provinceChildren, result.city) || result.city;
  }
  let districtVal = result.district;
  const cityMatch = provinceChildren.find((opt) => opt[props.labelField] === result.city);
  const cityChildren = cityMatch?.[props.childrenField] || [];
  if (cityChildren.length) {
    districtVal = getValueByLabel(cityChildren, result.district) || result.district;
  }
  const newVal = {
    name: result.name || innerVal.name,
    phone: result.phone || innerVal.phone,
    province: provinceVal || innerVal.province,
    city: cityVal || innerVal.city,
    district: districtVal || innerVal.district,
    street: result.street || innerVal.street,
    detail: result.detail || innerVal.detail
  };
  Object.assign(innerVal, newVal);
  parseStatus.value = "success";
  parseTip.value = t("smartaddress.parseSuccess");
  rawText.value = "";
  emit("update:modelValue", { ...innerVal });
  emit("parsed", result);
  emit("change", { ...innerVal });
  setTimeout(() => {
    parseStatus.value = "idle";
    parseTip.value = "";
  }, 3e3);
}
const innerVal = reactive({ ...props.modelValue });
watch(
  () => props.modelValue,
  (val) => {
    if (val) {
      Object.keys(innerVal).forEach((key) => {
        const k = key;
        innerVal[k] = val[k] ?? "";
      });
    }
  },
  { deep: true }
);
function updateField(field, value) {
  innerVal[field] = value;
  emit("update:modelValue", { ...innerVal });
  emit("change", { ...innerVal });
}
const provinceOptions = computed(() => {
  return props.regionOptions.map((p) => ({
    label: p[props.labelField] || "",
    value: p[props.valueField] || ""
  }));
});
const cityOptions = computed(() => {
  if (!innerVal.province) return [];
  const p = props.regionOptions.find((opt) => opt[props.valueField] === innerVal.province);
  const children = p?.[props.childrenField] || [];
  if (children.length) {
    return children.map((c) => ({
      label: c[props.labelField] || "",
      value: c[props.valueField] || ""
    }));
  }
  return [];
});
const districtOptions = computed(() => {
  if (!innerVal.province || !innerVal.city) return [];
  const p = props.regionOptions.find((opt) => opt[props.valueField] === innerVal.province);
  const provinceChildren = p?.[props.childrenField] || [];
  if (provinceChildren.length) {
    const c = provinceChildren.find((child) => child[props.valueField] === innerVal.city);
    const cityChildren = c?.[props.childrenField] || [];
    if (cityChildren.length) {
      return cityChildren.map((d) => ({
        label: d[props.labelField] || "",
        value: d[props.valueField] || ""
      }));
    }
  }
  return [];
});
const cascaderOptions = computed(() => {
  const transform = (opts) => {
    return opts.map((opt) => ({
      label: opt[props.labelField] || "",
      value: opt[props.valueField] || "",
      children: opt[props.childrenField] ? transform(opt[props.childrenField]) : void 0
    }));
  };
  return transform(props.regionOptions);
});
const regionCascaderValue = computed({
  get() {
    const vals = [];
    if (innerVal.province) vals.push(innerVal.province);
    if (innerVal.city) vals.push(innerVal.city);
    if (innerVal.district) vals.push(innerVal.district);
    return vals;
  },
  set(val) {
    const arr = val;
    if (Array.isArray(arr)) {
      updateField("province", arr[0] || "");
      updateField("city", arr[1] || "");
      updateField("district", arr[2] || "");
    } else {
      updateField("province", "");
      updateField("city", "");
      updateField("district", "");
    }
  }
});
const placeholder = computed(
  () => props.placeholder ?? props.parsePlaceholder ?? t("smartaddress.placeholder")
);
const btnText = computed(() => props.parseButtonText || t("smartaddress.parse"));
const namePlh = computed(() => props.namePlaceholder ?? `${t("smartaddress.name")}...`);
const phonePlh = computed(() => props.phonePlaceholder ?? `${t("smartaddress.phone")}...`);
const streetPlh = computed(() => props.streetPlaceholder ?? `${t("smartaddress.street")}...`);
const detailPlh = computed(() => props.detailPlaceholder ?? `${t("smartaddress.detail")}...`);
</script>

<template>
  <div :class="[ns.b(), ns.is('disabled', disabled)]" :style="themeStyle">
    <!-- 智能识别区 -->
    <div v-if="showParser" :class="ns.e('parser')">
      <textarea
        v-model="rawText"
        :class="ns.e('parser-input')"
        :placeholder="placeholder"
        :disabled="disabled"
        rows="3"
        :aria-label="t('smartaddress.parse')"
      ></textarea>
      <div :class="ns.e('parser-actions')">
        <span
          v-if="parseTip"
          :class="[ns.e('parser-tip'), ns.is('success', parseStatus === 'success'), ns.is('error', parseStatus === 'error')]"
        >
          {{ parseTip }}
        </span>
        <button
          :class="ns.e('parse-btn')"
          :disabled="disabled || !rawText.trim()"
          @click="handleParse"
        >
          <slot name="parse-icon">✦</slot>
          {{ btnText }}
        </button>
      </div>
    </div>

    <!-- 结构化字段 -->
    <div :class="[ns.e('fields'), ns.is('top', labelPlacement === 'top')]">
      <!-- 姓名 -->
      <div v-if="showName" :class="ns.e('field')">
        <label :class="[ns.e('label'), ns.is('required', required)]">
          {{ t("smartaddress.name") }}
        </label>
        <input
          :class="ns.e('input')"
          :value="innerVal.name"
          :disabled="disabled"
          :placeholder="namePlh"
          @input="e => updateField('name', e.target.value)"
        />
      </div>

      <!-- 手机号 -->
      <div v-if="showPhone" :class="ns.e('field')">
        <label :class="[ns.e('label'), ns.is('required', required)]">
          {{ t("smartaddress.phone") }}
        </label>
        <input
          :class="ns.e('input')"
          :value="innerVal.phone"
          :disabled="disabled"
          type="tel"
          inputmode="numeric"
          maxlength="11"
          :placeholder="phonePlh"
          @input="e => updateField('phone', e.target.value)"
        />
      </div>

      <!-- 省/市/区 三个下拉（当前简化为 input，可由外部插槽替换为 Cascader） -->
      <div :class="[ns.e('field'), ns.e('region')]">
        <label :class="[ns.e('label'), ns.is('required', required)]">
          {{ t("smartaddress.province") }}
        </label>
        <slot name="region" :value="innerVal" :update="updateField">
          <!-- 输入框模式 -->
          <div v-if="regionType === 'input'" :class="ns.e('region-inputs')">
            <input
              :class="ns.e('input')"
              :value="innerVal.province"
              :disabled="disabled"
              :placeholder="t('smartaddress.province')"
              @input="e => updateField('province', e.target.value)"
            />
            <input
              :class="ns.e('input')"
              :value="innerVal.city"
              :disabled="disabled"
              :placeholder="t('smartaddress.city')"
              @input="e => updateField('city', e.target.value)"
            />
            <input
              :class="ns.e('input')"
              :value="innerVal.district"
              :disabled="disabled"
              :placeholder="t('smartaddress.district')"
              @input="e => updateField('district', e.target.value)"
            />
          </div>

          <!-- 下拉框模式 -->
          <div v-else-if="regionType === 'select'" :class="ns.e('region-inputs')">
            <YhSelect
              :model-value="innerVal.province"
              :disabled="disabled"
              :placeholder="t('smartaddress.province')"
              style="flex: 1; min-width: 0"
              @update:model-value="val => {
  updateField('province', val);
  updateField('city', '');
  updateField('district', '');
}"
            >
              <YhOption
                v-for="opt in provinceOptions"
                :key="opt.value"
                :label="opt.label"
                :value="opt.value"
              />
            </YhSelect>
            <YhSelect
              :model-value="innerVal.city"
              :disabled="disabled"
              :placeholder="t('smartaddress.city')"
              style="flex: 1; min-width: 0"
              @update:model-value="val => {
  updateField('city', val);
  updateField('district', '');
}"
            >
              <YhOption
                v-for="opt in cityOptions"
                :key="opt.value"
                :label="opt.label"
                :value="opt.value"
              />
            </YhSelect>
            <YhSelect
              :model-value="innerVal.district"
              :disabled="disabled"
              :placeholder="t('smartaddress.district')"
              style="flex: 1; min-width: 0"
              @update:model-value="val => updateField('district', val)"
            >
              <YhOption
                v-for="opt in districtOptions"
                :key="opt.value"
                :label="opt.label"
                :value="opt.value"
              />
            </YhSelect>
          </div>

          <!-- 级联模式 -->
          <div v-else-if="regionType === 'cascader'" :class="ns.e('region-inputs')">
            <YhCascader
              v-model="regionCascaderValue"
              :options="cascaderOptions"
              :disabled="disabled"
              :placeholder="t('smartaddress.province')"
              style="width: 100%"
            />
          </div>
        </slot>
      </div>

      <!-- 街道（可选） -->
      <div v-if="showStreet" :class="ns.e('field')">
        <label :class="ns.e('label')">
          {{ t("smartaddress.street") }}
        </label>
        <input
          :class="ns.e('input')"
          :value="innerVal.street"
          :disabled="disabled"
          :placeholder="streetPlh"
          @input="e => updateField('street', e.target.value)"
        />
      </div>

      <!-- 详细地址 -->
      <div :class="ns.e('field')">
        <label :class="[ns.e('label'), ns.is('required', required)]">
          {{ t("smartaddress.detail") }}
        </label>
        <input
          :class="ns.e('input')"
          :value="innerVal.detail"
          :disabled="disabled"
          :placeholder="detailPlh"
          @input="e => updateField('detail', e.target.value)"
        />
      </div>

      <!-- 自定义扩展字段区 -->
      <slot name="extra" :value="innerVal" :update="updateField" />
    </div>
  </div>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-smart-address {
  --yh-smart-address-parser-bg: var(--yh-color-primary-light-9);
  --yh-smart-address-parser-border: var(--yh-color-primary-light-5);
  --yh-smart-address-parser-radius: var(--yh-radius-base);
  --yh-smart-address-input-bg: var(--yh-fill-color-blank);
  --yh-smart-address-input-border: var(--yh-border-color);
  --yh-smart-address-input-focus-border: var(--yh-color-primary);
  --yh-smart-address-label-color: var(--yh-text-color-secondary);
  --yh-smart-address-label-width: 80px;
  --yh-smart-address-parse-btn-bg: var(--yh-color-primary);
  --yh-smart-address-tip-success: var(--yh-color-success);
  --yh-smart-address-tip-error: var(--yh-color-danger);
}
.yh-smart-address.is-disabled {
  opacity: 0.6;
  pointer-events: none;
}

.yh-smart-address__parser {
  background: var(--yh-smart-address-parser-bg);
  border: 1px solid var(--yh-smart-address-parser-border);
  border-radius: var(--yh-smart-address-parser-radius);
  padding: 12px;
  margin-bottom: 14px;
}

.yh-smart-address__parser-input {
  width: 100%;
  border: 1px solid var(--yh-smart-address-input-border);
  border-radius: var(--yh-radius-small);
  padding: 8px 10px;
  font-size: var(--yh-font-size-sm);
  color: var(--yh-text-color-regular);
  background: var(--yh-smart-address-input-bg);
  resize: none;
  line-height: 1.6;
  box-sizing: border-box;
  transition: border-color var(--yh-transition-base);
}
.yh-smart-address__parser-input:focus {
  outline: none;
  border-color: var(--yh-smart-address-input-focus-border);
}
.yh-smart-address__parser-input::placeholder {
  color: var(--yh-text-color-placeholder);
}

.yh-smart-address__parser-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 8px;
}

.yh-smart-address__parser-tip {
  font-size: var(--yh-font-size-sm);
}
.yh-smart-address__parser-tip.is-success {
  color: var(--yh-smart-address-tip-success);
}

.yh-smart-address__parser-tip.is-error {
  color: var(--yh-smart-address-tip-error);
}

.yh-smart-address__parse-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 16px;
  border: none;
  border-radius: var(--yh-radius-base);
  background: var(--yh-smart-address-parse-btn-bg);
  color: #fff;
  font-size: var(--yh-font-size-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--yh-transition-base);
}
.yh-smart-address__parse-btn:hover:not(:disabled) {
  background: var(--yh-color-primary-dark-2);
}
.yh-smart-address__parse-btn:disabled {
  background: var(--yh-fill-color);
  color: var(--yh-text-color-disabled);
  cursor: not-allowed;
}

.yh-smart-address__fields {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.yh-smart-address__fields.is-top .yh-smart-address__field {
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
}
.yh-smart-address__fields.is-top .yh-smart-address__label {
  width: 100%;
  line-height: 1.4;
  margin-bottom: 2px;
}
.yh-smart-address__fields.is-top .yh-smart-address__input,
.yh-smart-address__fields.is-top .yh-smart-address__region-inputs {
  flex: none;
}

.yh-smart-address__field {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.yh-smart-address__label {
  flex-shrink: 0;
  width: var(--yh-smart-address-label-width);
  font-size: var(--yh-font-size-sm);
  color: var(--yh-smart-address-label-color);
  line-height: 32px;
}
.yh-smart-address__label.is-required::before {
  content: "* ";
  color: var(--yh-color-danger);
}

.yh-smart-address__input {
  flex: 1;
  min-width: 0;
  width: 100%;
  height: 32px;
  padding: 0 11px;
  border: 1px solid var(--yh-smart-address-input-border);
  border-radius: var(--yh-radius-small);
  background: var(--yh-smart-address-input-bg);
  font-size: var(--yh-font-size-sm);
  color: var(--yh-text-color-regular);
  box-sizing: border-box;
  transition: border-color var(--yh-transition-base);
}
.yh-smart-address__input:focus {
  outline: none;
  border-color: var(--yh-smart-address-input-focus-border);
}
.yh-smart-address__input::placeholder {
  color: var(--yh-text-color-placeholder);
}

.yh-smart-address__region {
  align-items: flex-start;
}

.yh-smart-address__region-inputs {
  flex: 1;
  display: flex;
  gap: 8px;
  min-width: 0;
}
.yh-smart-address__region-inputs .yh-smart-address__input,
.yh-smart-address__region-inputs .yh-select {
  flex: 1 !important;
  width: 0 !important;
  min-width: 0 !important;
}

html.dark .yh-smart-address {
  --yh-smart-address-parser-bg: rgba(64, 158, 255, 0.05) !important;
  --yh-smart-address-parser-border: rgba(64, 158, 255, 0.15) !important;
  --yh-smart-address-input-bg: rgba(255, 255, 255, 0.03) !important;
  --yh-smart-address-input-border: rgba(255, 255, 255, 0.08) !important;
  --yh-smart-address-label-color: var(--yh-text-color-secondary) !important;
}
html.dark .yh-smart-address .yh-smart-address__parser-input {
  color: var(--yh-text-color-regular) !important;
}
html.dark .yh-smart-address .yh-smart-address__parser-input::placeholder {
  color: var(--yh-text-color-placeholder) !important;
}
html.dark .yh-smart-address .yh-smart-address__input {
  color: var(--yh-text-color-primary) !important;
}
html.dark .yh-smart-address .yh-smart-address__input::placeholder {
  color: var(--yh-text-color-placeholder) !important;
}
html.dark .yh-smart-address .yh-smart-address__parse-btn:disabled {
  background: rgba(255, 255, 255, 0.06) !important;
  color: var(--yh-text-color-disabled) !important;
}
</style>
