<template>
  <div class="budget-source-field">
    <!-- 提交用隐藏字段 -->
    <input :name="fieldName" type="hidden" :value="normalizedValue" />

    <!-- 当前展示文本（有值时展示） -->
    <span v-if="hasValue && displayText" class="budget-source-label" :title="displayText">
      {{ displayText }}
    </span>
    <span
      v-else-if="hasValue && budgetDataId"
      class="budget-source-label budget-source-label--muted"
      :title="`预算ID: ${budgetDataId}`"
    >
      预算ID: {{ budgetDataId }}
    </span>
    <span
      v-else-if="hasValue"
      class="budget-source-label budget-source-label--muted"
      :title="normalizedValue"
    >
      {{ normalizedValue }}
    </span>

    <el-button type="primary" size="small" @click="openDialog">选取</el-button>
    <el-button v-if="hasValue" size="small" @click="clearValue">清除</el-button>

    <el-dialog
      title="选择预算来源"
      :visible.sync="dialogVisible"
      :width="pendingAuthorizations.length > 1 ? '1000px' : '720px'"
      :close-on-click-modal="false"
      append-to-body
      @open="onDialogOpen"
      @close="onDialogClose"
    >
      <div style="margin-bottom: 12px">
        <el-select
          v-model="yearId"
          placeholder="请选择年份"
          filterable
          style="width: 100%"
          :loading="yearLoading"
          @change="onYearChange"
        >
          <el-option
            v-for="y in yearOptions"
            :key="String(y.value)"
            :label="y.label"
            :value="y.value"
          />
        </el-select>
      </div>

      <div style="display: flex; gap: 16px">
        <!-- 左侧：预算树 -->
        <div v-loading="treeLoading" style="flex: 1; max-height: 420px; overflow: auto; min-width: 0">
        <div v-if="departmentTree.length" class="tree-block">
          <div class="tree-title">部门预算</div>
          <el-tree
            :data="departmentTree"
            node-key="id"
            :props="treeProps"
            highlight-current
            default-expand-all
            :expand-on-click-node="false"
            :current-node-key="pendingId"
            @node-click="onNodeClick"
          >
            <span class="custom-tree-node" slot-scope="{ node, data }">
              <span class="node-label">{{ node.label }}</span>
              <span v-if="data.is_leaf" class="node-usage-info">
                <span class="usage-item">
                  <span class="usage-label">预算:</span>
                  <span class="usage-value">{{ formatAmount(data.budget_amount) }}</span>
                </span>
                <span class="usage-item">
                  <span class="usage-label">已用:</span>
                  <span class="usage-value usage-value--used">{{ formatAmount(data.used_amount || 0) }}</span>
                </span>
                <span class="usage-item">
                  <span class="usage-label">执行率:</span>
                  <span
                    class="usage-value usage-value--rate"
                    :class="getExecutionRateClass(data.execution_rate || 0)"
                  >
                    {{ formatExecutionRate(data.execution_rate || 0) }}
                  </span>
                </span>
              </span>
            </span>
          </el-tree>
        </div>

        <div v-if="projectTree.length" class="tree-block" style="margin-top: 16px">
          <div class="tree-title">自有账户</div>
          <el-tree
            :data="projectTree"
            node-key="id"
            :props="treeProps"
            highlight-current
            default-expand-all
            :expand-on-click-node="false"
            :current-node-key="pendingId"
            @node-click="onNodeClick"
          >
            <span class="custom-tree-node" slot-scope="{ node, data }">
              <span class="node-label">{{ node.label }}</span>
              <span v-if="data.is_leaf" class="node-usage-info">
                <span class="usage-item">
                  <span class="usage-label">预算:</span>
                  <span class="usage-value">{{ formatAmount(data.budget_amount) }}</span>
                </span>
                <span class="usage-item">
                  <span class="usage-label">已用:</span>
                  <span class="usage-value usage-value--used">{{ formatAmount(data.used_amount || 0) }}</span>
                </span>
                <span class="usage-item">
                  <span class="usage-label">执行率:</span>
                  <span
                    class="usage-value usage-value--rate"
                    :class="getExecutionRateClass(data.execution_rate || 0)"
                  >
                    {{ formatExecutionRate(data.execution_rate || 0) }}
                  </span>
                </span>
              </span>
            </span>
          </el-tree>
        </div>

        <div v-if="specialFundTree.length" class="tree-block" style="margin-top: 16px">
          <div class="tree-title">专项资金</div>
          <el-tree
            :data="specialFundTree"
            node-key="id"
            :props="treeProps"
            highlight-current
            default-expand-all
            :expand-on-click-node="false"
            :current-node-key="pendingId"
            @node-click="onNodeClick"
          >
            <span class="custom-tree-node" slot-scope="{ node, data }">
              <span class="node-label">{{ node.label }}</span>
              <span v-if="data.is_leaf" class="node-usage-info">
                <span class="usage-item">
                  <span class="usage-label">预算:</span>
                  <span class="usage-value">{{ formatAmount(data.budget_amount) }}</span>
                </span>
                <span class="usage-item">
                  <span class="usage-label">已用:</span>
                  <span class="usage-value usage-value--used">{{ formatAmount(data.used_amount || 0) }}</span>
                </span>
                <span class="usage-item">
                  <span class="usage-label">执行率:</span>
                  <span
                    class="usage-value usage-value--rate"
                    :class="getExecutionRateClass(data.execution_rate || 0)"
                  >
                    {{ formatExecutionRate(data.execution_rate || 0) }}
                  </span>
                </span>
              </span>
            </span>
          </el-tree>
        </div>

        <div
          v-if="!treeLoading && departmentTree.length === 0 && projectTree.length === 0 && specialFundTree.length === 0"
          style="text-align: center; color: #909399; padding: 32px 0"
        >
          暂无数据
        </div>
        </div>

        <!-- 右侧：部门分配界面（仅多部门时显示） -->
        <div v-if="pendingAuthorizations.length > 1" style="flex: 0 0 400px; border-left: 1px solid #e4e7ed; padding-left: 16px">
          <div style="margin-bottom: 12px; font-weight: 500; color: #303133">
            部门金额分配
          </div>
          <div style="margin-bottom: 12px; color: #606266; font-size: 12px">
            该预算来源授权给多个部门，请将支付总额分配到各个部门（分配金额可以为0）：
          </div>
          <el-table :data="pendingAllocations" border size="small" style="width: 100%">
            <el-table-column prop="department_name" label="部门" width="180"></el-table-column>
            <el-table-column label="分配金额" width="180">
              <template slot-scope="scope">
                <el-input-number
                  v-model="scope.row.allocated_amount"
                  :min="0"
                  :precision="2"
                  :controls="false"
                  style="width: 100%"
                  size="small"
                  @change="onAllocationChange"
                ></el-input-number>
              </template>
            </el-table-column>
          </el-table>
          <div style="margin-top: 12px; padding: 12px; background-color: #f5f7fa; border-radius: 4px">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px">
              <span style="font-size: 12px; color: #606266">已分配总额：</span>
              <span :style="{ color: allocationTotal === totalAmount ? '#67c23a' : '#f56c6c', fontWeight: 'bold', fontSize: '14px' }">
                {{ formatAmount(allocationTotal) }}
              </span>
            </div>
            <div v-if="totalAmount > 0" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px">
              <span style="font-size: 12px; color: #606266">支付总额：</span>
              <span style="font-weight: 500; font-size: 14px">{{ formatAmount(totalAmount) }}</span>
            </div>
            <div v-if="totalAmount > 0" style="display: flex; justify-content: space-between; align-items: center">
              <span style="font-size: 12px; color: #606266">剩余金额：</span>
              <span :style="{ color: remainingAmount >= 0 ? '#67c23a' : '#f56c6c', fontWeight: 'bold', fontSize: '14px' }">
                {{ formatAmount(remainingAmount) }}
              </span>
            </div>
            <div v-if="totalAmount === 0" style="margin-top: 8px; color: #909399; font-size: 11px; line-height: 1.5">
              提示：当前支付总额为0，您可以在财务确认时填写实际金额
            </div>
          </div>
        </div>
      </div>

      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button 
          type="primary" 
          :disabled="!pendingId || (pendingAuthorizations.length > 1 && totalAmount > 0 && allocationTotal !== totalAmount)"
          @click="confirmPick"
        >
          确定
        </el-button>
      </template>
    </el-dialog>

  </div>
</template>

<script>
import request from "@/utils/request";
import { getBudgetYearOptions, getBudgetDataTree } from "@/api/flow";

export default {
  name: "BudgetSourcePickerField",
  props: {
    fieldName: { type: String, required: true },
    value: { type: [String, Number, Object, Array], default: "" },
    display: { type: String, default: "" },
  },
  data() {
    return {
      dialogVisible: false,
      yearLoading: false,
      treeLoading: false,
      yearOptions: [],
      yearId: null,
      treeData: [],
      pendingId: null,
      // 分配相关
      pendingAuthorizations: [],
      pendingAllocations: [],
      totalAmount: 0,
    };
  },
  computed: {
    // 解析JSON格式的value，兼容旧格式
    parsedValue() {
      const value = this.value;
      if (!value || value === null || value === undefined) {
        return { budget_data_id: null, allocations: null };
      }

      // 已经是对象（推荐的新格式：直接对象落库/回传）
      if (typeof value === "object" && !Array.isArray(value)) {
        return {
          budget_data_id: value?.budget_data_id ?? null,
          allocations: value?.allocations ?? null,
        };
      }

      // 兼容：如果是数组（极端旧数据/异常数据），当作 allocations
      if (Array.isArray(value)) {
        return { budget_data_id: null, allocations: value };
      }

      // 字符串：可能是
      // 1) 旧格式： "123"
      // 2) 新格式： '{"budget_data_id":"2","allocations":[...]}'
      // 3) 双重编码： '"{\"budget_data_id\":\"2\",\"allocations\":[...]}"'
      if (typeof value === "string") {
        const raw = value.trim();
        if (!raw) return { budget_data_id: null, allocations: null };

        const parseMaybeJson = (s) => {
          try {
            return { ok: true, data: JSON.parse(s) };
          } catch (e) {
            return { ok: false, data: null };
          }
        };

        const p1 = parseMaybeJson(raw);
        if (p1.ok) {
          // 解析结果是对象：标准新格式
          if (p1.data && typeof p1.data === "object" && !Array.isArray(p1.data)) {
            return {
              budget_data_id: p1.data?.budget_data_id ?? null,
              allocations: p1.data?.allocations ?? null,
            };
          }
          // 解析结果是数组：当作 allocations（仍可能缺 budget_data_id）
          if (Array.isArray(p1.data)) {
            return { budget_data_id: null, allocations: p1.data };
          }
          // 解析结果是字符串：双重编码常见形态
          if (typeof p1.data === "string") {
            const inner = p1.data.trim();
            // inner 可能是 '{...}' 或者 '2'
            const p2 = parseMaybeJson(inner);
            if (p2.ok && p2.data && typeof p2.data === "object" && !Array.isArray(p2.data)) {
              return {
                budget_data_id: p2.data?.budget_data_id ?? null,
                allocations: p2.data?.allocations ?? null,
              };
            }
            if (p2.ok && Array.isArray(p2.data)) {
              return { budget_data_id: null, allocations: p2.data };
            }
            // inner 可能是数字字符串
            return {
              budget_data_id: isNaN(inner) ? null : String(inner),
              allocations: null,
            };
          }
        }

        // 非JSON：当作旧格式 ID
        return { budget_data_id: isNaN(raw) ? null : String(raw), allocations: null };
      }

      return { budget_data_id: null, allocations: null };
    },
    budgetDataId() {
      return this.parsedValue.budget_data_id;
    },
    allocations() {
      return this.parsedValue.allocations;
    },
    normalizedValue() {
      // 返回JSON格式的字符串（用于表单提交/兜底）
      if (!this.budgetDataId) return "";
      return JSON.stringify({
        budget_data_id: this.budgetDataId,
        allocations: this.allocations,
      });
    },
    hasValue() {
      return this.budgetDataId !== null && this.budgetDataId !== "";
    },
    displayText() {
      // 优先使用后端返回的 `{字段名}_display`
      if (this.display && this.display.trim()) {
        return this.display;
      }
      
      // 如果display为空，但有值，尝试从JSON中解析并生成显示文本
      if (this.hasValue && this.budgetDataId) {
        // 如果value是JSON格式但display为空，显示budget_data_id作为fallback
        // 注意：这里不显示原始JSON，而是显示解析出的ID
        return `预算ID: ${this.budgetDataId}`;
      }
      
      // 如果value存在但不是JSON格式（旧格式），也不显示原始值
      // 避免显示原始JSON字符串
      return "";
    },
    treeProps() {
      return {
        children: "children",
        label: "name",
        disabled: (data) => !data?.is_leaf,
      };
    },
    departmentTree() {
      return (this.treeData || []).filter((n) => n?.budget_type === "department");
    },
    projectTree() {
      return (this.treeData || []).filter((n) => n?.budget_type === "project");
    },
    specialFundTree() {
      return (this.treeData || []).filter((n) => n?.budget_type === "special_fund");
    },
    budgetTypeMap() {
      return {
        department: "部门预算",
        project: "自有账户",
        special_fund: "专项资金",
      };
    },
    // 分配总额
    allocationTotal() {
      return (this.pendingAllocations || []).reduce((sum, item) => {
        return sum + (parseFloat(item.allocated_amount) || 0);
      }, 0);
    },
    // 剩余金额
    remainingAmount() {
      return this.totalAmount - this.allocationTotal;
    },
  },
  methods: {
    openDialog() {
      this.dialogVisible = true;
    },
    onDialogOpen() {
      this.pendingId = null;
      this.ensureInit();
    },
    onDialogClose() {
      this.pendingId = null;
    },
    async ensureInit() {
      if (!this.yearOptions || this.yearOptions.length === 0) {
        await this.loadYearOptions();
      }

      if (!this.yearId && this.yearOptions.length > 0) {
        // 尝试根据当前 value 反查 year_id（可选），否则默认第一项
        const fromValue = await this.tryResolveYearIdByValue();
        this.yearId = fromValue || this.yearOptions[0].value;
      }

      if (this.yearId) {
        await this.loadTree(this.yearId);
      }
    },
    async loadYearOptions() {
      this.yearLoading = true;
      try {
        const res = await getBudgetYearOptions(false);
        const arr = Array.isArray(res) ? res : [];
        this.yearOptions = arr.map((y) => ({
          value: y.value,
          label: y.label || (y.year ? `${y.year}年` : `${y.value}年`),
          year: y.year,
        }));
      } finally {
        this.yearLoading = false;
      }
    },
    async tryResolveYearIdByValue() {
      if (!this.hasValue || !this.budgetDataId) return null;
      try {
        const detail = await request({
          method: "get",
          url: `/api/budget/budget-data/${this.budgetDataId}`,
          isLoading: false,
        });
        const yearId = detail?.year_id ?? null;
        return yearId;
      } catch (e) {
        return null;
      }
    },
    async getDepartmentAuthorizations(budgetDataId) {
      try {
        const res = await request({
          method: "get",
          url: `/api/budget/budget-data/${budgetDataId}/department-authorizations`,
          isLoading: false,
        });
        return Array.isArray(res) ? res : [];
      } catch (e) {
        return [];
      }
    },
    async loadTree(yearId) {
      if (!yearId) return;
      this.treeLoading = true;
      try {
        const res = await getBudgetDataTree({ year_id: yearId }, false);
        this.treeData = Array.isArray(res) ? res : [];
      } finally {
        this.treeLoading = false;
      }
    },
    async onYearChange(val) {
      this.pendingId = null;
      this.treeData = [];
      await this.loadTree(val);
    },
    async onNodeClick(node) {
      if (!node || !node.is_leaf) return;
      this.pendingId = node.id;
      
      // 选择叶子节点时，检查部门授权并显示分配界面
      const authorizations = await this.getDepartmentAuthorizations(node.id);
      if (authorizations.length > 1) {
        // 多部门：显示分配界面
        this.pendingAuthorizations = authorizations;
        // 恢复之前的分配方案（如果有）
        const existingAllocations = this.allocations || [];
        if (existingAllocations.length > 0) {
          // 合并：保留已有的分配，新增的部门设为0
          this.pendingAllocations = authorizations.map(auth => {
            const existing = existingAllocations.find(
              a => String(a.department_id) === String(auth.department_id)
            );
            return {
              department_id: auth.department_id,
              department_name: auth.department?.name || '',
              allocated_amount: existing ? (parseFloat(existing.allocated_amount) || 0) : 0
            };
          });
        } else {
          // 没有之前的分配方案，创建新的
          this.pendingAllocations = authorizations.map(auth => ({
            department_id: auth.department_id,
            department_name: auth.department?.name || '',
            allocated_amount: 0
          }));
        }
      } else {
        // 单部门：清空分配界面
        this.pendingAuthorizations = [];
        this.pendingAllocations = [];
      }
    },
    findPathNames(tree, id, path = []) {
      if (!Array.isArray(tree)) return null;
      for (const n of tree) {
        const nextPath = [...path, n];
        if (String(n.id) === String(id)) return nextPath;
        if (n.children && n.children.length) {
          const found = this.findPathNames(n.children, id, nextPath);
          if (found) return found;
        }
      }
      return null;
    },
    getYearLabel() {
      const opt = (this.yearOptions || []).find(
        (y) => String(y.value) === String(this.yearId)
      );
      return opt?.label || (this.yearId ? `${this.yearId}年` : "");
    },
    async confirmPick() {
      if (!this.pendingId) return;
      
      // 验证多部门分配总额（如果totalAmount > 0）
      if (this.pendingAuthorizations.length > 1 && this.totalAmount > 0) {
        if (this.allocationTotal !== this.totalAmount) {
          this.$message.warning(`分配总额必须等于支付总额 ${this.formatAmount(this.totalAmount)}`);
          return;
        }
      }
      
      // 获取部门授权列表（用于确认）
      const authorizations = await this.getDepartmentAuthorizations(this.pendingId);
      
      let allocations = [];
      if (authorizations.length === 1) {
        // 单部门：自动创建分配方案
        allocations = [{
          department_id: authorizations[0].department_id,
          department_name: authorizations[0].department?.name || '',
          allocated_amount: 0 // 占位，实际金额在financialConfirm时确定
        }];
      } else if (authorizations.length > 1) {
        // 多部门：使用已填写的分配方案
        allocations = this.pendingAllocations || [];
      }
      
      this.doConfirmPick(allocations);
    },
    doConfirmPick(allocations) {
      const nodes = this.findPathNames(this.treeData, this.pendingId) || [];
      const names = nodes.map((n) => n?.name).filter(Boolean);
      const leaf = nodes[nodes.length - 1];
      const typeText = this.budgetTypeMap[leaf?.budget_type] || leaf?.budget_type || "";
      const yearLabel = this.getYearLabel();
      const display = [yearLabel, typeText, ...names].filter(Boolean).join(" / ");

      // 关键：不要再把JSON对象当“字符串”提交给后端 json 字段，否则后端会再次 json_encode 导致双重编码
      const payload = {
        budget_data_id: String(this.pendingId),
        allocations: allocations.length > 0 ? allocations : null,
      };

      // 更新主值与展示值（展示值用于只读/回显）
      this.$emit("input", payload);
      this.$emit("update:display", display);

      this.dialogVisible = false;
      this.pendingId = null;
      // 清空分配相关数据
      this.pendingAuthorizations = [];
      this.pendingAllocations = [];
    },
    onAllocationChange() {
      // 分配金额变化时的处理（实时验证已在按钮disabled中处理）
    },
    onDialogClose() {
      this.pendingId = null;
      // 清空分配相关数据
      this.pendingAuthorizations = [];
      this.pendingAllocations = [];
    },
    formatAmount(amount) {
      if (amount === null || amount === undefined) return "0.00";
      const num = parseFloat(amount);
      if (isNaN(num)) return "0.00";
      return num.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
    },
    formatExecutionRate(rate) {
      if (rate === null || rate === undefined) return "0.00%";
      const num = parseFloat(rate);
      if (isNaN(num)) return "0.00%";
      return num.toFixed(2) + "%";
    },
    getExecutionRateClass(rate) {
      const num = parseFloat(rate);
      if (isNaN(num)) return "";
      if (num >= 100) return "rate-high";
      if (num >= 80) return "rate-medium";
      if (num >= 50) return "rate-normal";
      return "rate-low";
    },
    clearValue() {
      this.$emit("input", "");
      this.$emit("update:display", "");
    },
  },
};
</script>

<style scoped>
.budget-source-field {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.budget-source-label {
  color: #606266;
  font-size: 14px;
  flex: 1;
  min-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.budget-source-label--muted {
  color: #909399;
}

.tree-title {
  font-size: 14px;
  font-weight: 600;
  color: #606266;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid #e4e7ed;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

.node-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.node-usage-info {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: 12px;
  flex-shrink: 0;
  font-size: 12px;
}

.usage-item {
  display: flex;
  align-items: center;
  gap: 4px;
}

.usage-label {
  color: #909399;
  font-size: 12px;
}

.usage-value {
  color: #606266;
  font-weight: 500;
  font-size: 12px;
}

.usage-value--used {
  color: #409eff;
}

.usage-value--rate {
  min-width: 50px;
  text-align: right;
}

.usage-value--rate.rate-high {
  color: #f56c6c;
  font-weight: 600;
}

.usage-value--rate.rate-medium {
  color: #e6a23c;
  font-weight: 500;
}

.usage-value--rate.rate-normal {
  color: #409eff;
}

.usage-value--rate.rate-low {
  color: #909399;
}
</style>


