<template>
  <div class="app-container glb-page">
    <el-card shadow="never" class="glb-card">
      <div slot="header" class="glb-card__title">{{ dmT("sectionParams") }}</div>
      <el-form ref="form" :model="form" label-position="top" size="small" class="glb-form glb-form--responsive">
        <el-row :gutter="16">
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item prop="grasslandId" :rules="formRules.grasslandId">
              <template slot="label">{{ dmT("formGrassland") }}</template>
              <el-select
                v-model="form.grasslandId"
                filterable
                remote
                reserve-keyword
                :placeholder="dmT('phGrasslandSelect')"
                :remote-method="searchGrassland"
                :loading="grasslandLoading"
                style="width: 100%"
                @change="handleGrasslandChange"
                @focus="searchGrassland('')"
              >
                <el-option
                  v-for="item in grasslandOptions"
                  :key="item.id"
                  :label="item.grasslandName"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item prop="areaMu" :rules="formRules.areaMu">
              <template slot="label">{{ dmT("formAreaMu") }}</template>
              <div class="dm-input-with-unit">
                <el-input-number
                  v-model="form.areaMu"
                  :min="0"
                  :precision="2"
                  :step="0.1"
                  controls-position="right"
                  class="dm-input-with-unit__input"
                />
                <span class="dm-input-with-unit__suffix">{{ $t("dataModel.grassland.unitMu") }}</span>
              </div>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item prop="grassYieldPerMu" :rules="formRules.grassYieldPerMu">
              <template slot="label">{{ dmT("formGrassYieldPerMu") }}</template>
              <div class="dm-input-with-unit">
                <el-input-number
                  v-model="form.grassYieldPerMu"
                  :min="0"
                  :precision="2"
                  :step="1"
                  controls-position="right"
                  class="dm-input-with-unit__input"
                />
                <span class="dm-input-with-unit__suffix">{{ $t("dataModel.grassland.unitKgPerMu") }}</span>
              </div>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item prop="utilizationRate" :rules="formRules.utilizationRate">
              <template slot="label">{{ dmT("formUtilizationRate") }}</template>
              <div class="dm-input-with-unit">
                <el-input-number
                  v-model="form.utilizationRate"
                  :min="0"
                  :max="1"
                  :precision="4"
                  :step="0.01"
                  controls-position="right"
                  class="dm-input-with-unit__input"
                />
                <span class="dm-input-with-unit__suffix">{{ $t("dataModel.grassland.unitRatio") }}</span>
              </div>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item prop="sheepUnitAnnualForageKg" :rules="formRules.sheepUnitAnnualForageKg">
              <template slot="label">{{ dmT("formSheepAnnualForage") }}</template>
              <div class="dm-input-with-unit">
                <el-input-number
                  v-model="form.sheepUnitAnnualForageKg"
                  :min="0"
                  :precision="2"
                  :step="1"
                  controls-position="right"
                  class="dm-input-with-unit__input"
                />
                <span class="dm-input-with-unit__suffix">{{ dmT("unitKgPerSu") }}</span>
              </div>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item prop="sheepUnitConvertCoeff" :rules="formRules.sheepUnitConvertCoeff">
              <template slot="label">{{ dmT("formSheepConvertCoeff") }}</template>
              <div class="dm-input-with-unit">
                <el-input-number
                  v-model="form.sheepUnitConvertCoeff"
                  :min="0"
                  :precision="2"
                  :step="0.1"
                  controls-position="right"
                  class="dm-input-with-unit__input"
                />
                <span class="dm-input-with-unit__suffix">{{ dmT("unitSuPerHead") }}</span>
              </div>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item prop="breedingHeadCount" :rules="formRules.breedingHeadCount">
              <template slot="label">{{ dmT("formBreedingHeadCount") }}</template>
              <div class="dm-input-with-unit">
                <el-input-number
                  v-model="form.breedingHeadCount"
                  :min="0"
                  :precision="0"
                  :step="1"
                  controls-position="right"
                  class="dm-input-with-unit__input"
                />
                <span class="dm-input-with-unit__suffix">{{ dmT("unitHead") }}</span>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item class="glb-form__actions">
          <el-button
            v-hasPermi="['dataModel:grassLivestockBalance:query']"
            type="primary"
            icon="el-icon-cpu"
            :loading="calculating"
            @click="handleCalculate"
          >{{ dmT("btnCalculate") }}</el-button>
          <el-button icon="el-icon-refresh-left" @click="handleClear">{{ dmT("btnClear") }}</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <br />

    <el-card shadow="never" class="glb-card">
      <div slot="header" class="glb-card__title">{{ dmT("sectionResult") }}</div>
      <el-alert
        v-if="result.warning"
        :title="result.warning"
        type="warning"
        show-icon
        :closable="false"
        class="glb-warning"
      />
      <el-form label-position="top" size="small" class="glb-form glb-form--readonly glb-form--responsive">
        <el-row :gutter="16">
          <el-col v-for="field in resultFieldRows[0]" :key="field.key" :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item>
              <template slot="label">{{ dmT(field.labelKey) }}</template>
              <div class="glb-readonly">{{ formatResultField(field) }}</div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="16">
          <el-col v-for="field in resultFieldRows[1]" :key="field.key" :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item>
              <template slot="label">{{ dmT(field.labelKey) }}</template>
              <div
                v-if="field.key === 'balanceLevelName'"
                class="glb-readonly glb-level"
                :class="balanceLevelClass"
              >{{ formatResultField(field) }}</div>
              <div v-else class="glb-readonly">{{ formatResultField(field) }}</div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="16">
          <el-col v-for="field in resultFieldRows[2]" :key="field.key" :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item>
              <template slot="label">{{ dmT(field.labelKey) }}</template>
              <div class="glb-readonly">{{ formatResultField(field) }}</div>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>

    <br />

    <el-card shadow="never" class="glb-card">
      <el-collapse>
        <el-collapse-item :title="dmT('sectionFormula')" name="formula">
          <ul class="glb-formula-list">
            <li v-for="n in 11" :key="n">{{ dmT("formula" + n) }}</li>
          </ul>
          <p class="glb-formula-level-title">{{ dmT("formulaLevelTitle") }}</p>
          <ul class="glb-formula-list glb-formula-list--compact">
            <li v-for="n in 4" :key="'lv' + n">{{ dmT("formulaLevel" + n) }}</li>
          </ul>
        </el-collapse-item>
      </el-collapse>
    </el-card>
  </div>
</template>

<script>
import dataModelLocaleMixin from "@/mixins/dataModelLocaleMixin"
import { listGrassland, getGrassland } from "@/api/dataModel/grassland"
import {
  calculateGrassLivestockBalance,
  getGrassLivestockBalanceDefaults
} from "@/api/dataModel/grassLivestockBalance"

const RESULT_FIELDS = [
  [
    { key: "availableForageKg", labelKey: "resAvailableForage", type: "decimal", unitKey: "unitKg" },
    { key: "theoreticalCarryingSu", labelKey: "resTheoreticalSu", type: "decimal", unitKey: "unitSu" },
    { key: "actualCarryingSu", labelKey: "resActualSu", type: "decimal", unitKey: "unitSu" },
    { key: "balanceIndex", labelKey: "resBalanceIndex", type: "decimal" }
  ],
  [
    { key: "overloadRate", labelKey: "resOverloadRate", type: "percent" },
    { key: "balanceLevelName", labelKey: "resBalanceLevel", type: "text" },
    { key: "overloadSu", labelKey: "resOverloadSu", type: "signed", unitKey: "unitSu" },
    { key: "annualForageDemandKg", labelKey: "resAnnualForage", type: "decimal", unitKey: "unitKg" }
  ],
  [
    { key: "forageGapKg", labelKey: "resForageGap", type: "signed", unitKey: "unitKg" },
    { key: "theoreticalSuitableHeads", labelKey: "resTheoreticalHeads", type: "decimal", unitKey: "unitHead" },
    { key: "actualOverloadHeads", labelKey: "resActualOverloadHeads", type: "integer", unitKey: "unitHead" }
  ]
]

export default {
  name: "GrassLivestockBalance",
  mixins: [dataModelLocaleMixin],
  data() {
    return {
      dmNs: "grassLivestockBalance",
      grasslandLoading: false,
      calculating: false,
      resultCalculated: false,
      grasslandOptions: [],
      defaultSheepParams: {
        sheepUnitAnnualForageKg: undefined,
        sheepUnitConvertCoeff: undefined
      },
      form: this.emptyForm(),
      result: this.emptyResult()
    }
  },
  computed: {
    resultFieldRows() {
      return RESULT_FIELDS
    },
    formRules() {
      return {
        grasslandId: [{ required: true, message: this.dmT("ruleGrasslandRequired"), trigger: "change" }],
        areaMu: [
          { required: true, message: this.dmT("ruleAreaRequired"), trigger: "blur" },
          { validator: this.validateAreaMu, trigger: "blur" }
        ],
        grassYieldPerMu: [
          { required: true, message: this.dmT("ruleYieldRequired"), trigger: "blur" },
          { validator: this.validateGrassYieldPerMu, trigger: "blur" }
        ],
        utilizationRate: [
          { required: true, message: this.dmT("ruleRateRequired"), trigger: "blur" },
          { validator: this.validateUtilizationRate, trigger: "blur" }
        ],
        sheepUnitAnnualForageKg: [
          { required: true, message: this.dmT("ruleSheepForageRequired"), trigger: "blur" },
          { validator: this.validateSheepForage, trigger: "blur" }
        ],
        sheepUnitConvertCoeff: [
          { required: true, message: this.dmT("ruleSheepCoeffRequired"), trigger: "blur" },
          { validator: this.validateSheepCoeff, trigger: "blur" }
        ],
        breedingHeadCount: [
          { required: true, message: this.dmT("ruleBreedingRequired"), trigger: "blur" },
          { validator: this.validateBreedingHeadCount, trigger: "blur" }
        ]
      }
    },
    balanceLevelClass() {
      if (!this.resultCalculated || this.result.balanceLevel == null) {
        return ""
      }
      const map = {
        1: "glb-level--ok",
        2: "glb-level--basic",
        3: "glb-level--warn",
        4: "glb-level--severe"
      }
      return map[this.result.balanceLevel] || ""
    }
  },
  created() {
    this.loadDefaults()
  },
  methods: {
    emptyForm() {
      return {
        grasslandId: undefined,
        areaMu: undefined,
        grassYieldPerMu: undefined,
        utilizationRate: undefined,
        sheepUnitAnnualForageKg: undefined,
        sheepUnitConvertCoeff: undefined,
        breedingHeadCount: undefined
      }
    },
    emptyResult() {
      return {
        availableForageKg: undefined,
        theoreticalCarryingSu: undefined,
        actualCarryingSu: undefined,
        balanceIndex: undefined,
        overloadRate: undefined,
        balanceLevel: undefined,
        balanceLevelName: undefined,
        overloadSu: undefined,
        annualForageDemandKg: undefined,
        forageGapKg: undefined,
        theoreticalSuitableHeads: undefined,
        actualOverloadHeads: undefined,
        warning: undefined
      }
    },
    clearResult() {
      this.resultCalculated = false
      this.result = this.emptyResult()
    },
    loadDefaults() {
      getGrassLivestockBalanceDefaults()
        .then((res) => {
          const data = res.data || {}
          this.defaultSheepParams = {
            sheepUnitAnnualForageKg:
              data.sheepUnitAnnualForageKg != null ? Number(data.sheepUnitAnnualForageKg) : undefined,
            sheepUnitConvertCoeff:
              data.sheepUnitConvertCoeff != null ? Number(data.sheepUnitConvertCoeff) : undefined
          }
          if (this.form.sheepUnitAnnualForageKg == null && this.defaultSheepParams.sheepUnitAnnualForageKg != null) {
            this.form.sheepUnitAnnualForageKg = this.defaultSheepParams.sheepUnitAnnualForageKg
          }
          if (this.form.sheepUnitConvertCoeff == null && this.defaultSheepParams.sheepUnitConvertCoeff != null) {
            this.form.sheepUnitConvertCoeff = this.defaultSheepParams.sheepUnitConvertCoeff
          }
        })
        .catch(() => {})
    },
    applyDefaultSheepParams() {
      if (this.defaultSheepParams.sheepUnitAnnualForageKg != null) {
        this.form.sheepUnitAnnualForageKg = this.defaultSheepParams.sheepUnitAnnualForageKg
      }
      if (this.defaultSheepParams.sheepUnitConvertCoeff != null) {
        this.form.sheepUnitConvertCoeff = this.defaultSheepParams.sheepUnitConvertCoeff
      }
    },
    validateAreaMu(rule, value, callback) {
      if (value == null || value === "") {
        callback()
        return
      }
      if (Number(value) <= 0) {
        callback(new Error(this.dmT("ruleAreaPositive")))
        return
      }
      callback()
    },
    validateGrassYieldPerMu(rule, value, callback) {
      if (value == null || value === "") {
        callback()
        return
      }
      if (Number(value) < 0) {
        callback(new Error(this.dmT("ruleYieldNonNegative")))
        return
      }
      callback()
    },
    validateUtilizationRate(rule, value, callback) {
      if (value == null || value === "") {
        callback()
        return
      }
      const n = Number(value)
      if (n < 0 || n > 1) {
        callback(new Error(this.dmT("ruleRateRange")))
        return
      }
      callback()
    },
    validateSheepForage(rule, value, callback) {
      if (value == null || value === "") {
        callback()
        return
      }
      if (Number(value) <= 0) {
        callback(new Error(this.dmT("ruleSheepForagePositive")))
        return
      }
      callback()
    },
    validateSheepCoeff(rule, value, callback) {
      if (value == null || value === "") {
        callback()
        return
      }
      if (Number(value) <= 0) {
        callback(new Error(this.dmT("ruleSheepCoeffPositive")))
        return
      }
      callback()
    },
    validateBreedingHeadCount(rule, value, callback) {
      if (value == null || value === "") {
        callback()
        return
      }
      if (!Number.isInteger(Number(value)) || Number(value) < 0) {
        callback(new Error(this.dmT("ruleBreedingNonNegative")))
        return
      }
      callback()
    },
    searchGrassland(query) {
      this.grasslandLoading = true
      listGrassland({ pageNum: 1, pageSize: 50, keyword: query || undefined })
        .then((res) => {
          this.grasslandOptions = res.rows || []
        })
        .finally(() => {
          this.grasslandLoading = false
        })
    },
    ensureGrasslandOption(id, name) {
      if (!id || this.grasslandOptions.some((o) => o.id === id)) {
        return
      }
      this.grasslandOptions.push({ id, grasslandName: name })
    },
    handleGrasslandChange(id) {
      this.clearResult()
      if (!id) {
        return
      }
      getGrassland(id).then((res) => {
        const data = res.data || {}
        this.ensureGrasslandOption(data.id, data.grasslandName)
        this.form.areaMu = data.areaMu != null ? Number(data.areaMu) : undefined
        this.form.grassYieldPerMu = data.grassYieldPerMu != null ? Number(data.grassYieldPerMu) : undefined
        this.form.utilizationRate = data.utilizationRate != null ? Number(data.utilizationRate) : undefined
      })
    },
    buildPayload() {
      return {
        grasslandId: this.form.grasslandId,
        areaMu: this.form.areaMu,
        grassYieldPerMu: this.form.grassYieldPerMu,
        utilizationRate: this.form.utilizationRate,
        sheepUnitAnnualForageKg: this.form.sheepUnitAnnualForageKg,
        sheepUnitConvertCoeff: this.form.sheepUnitConvertCoeff,
        breedingHeadCount: this.form.breedingHeadCount
      }
    },
    handleCalculate() {
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return
        }
        this.calculating = true
        calculateGrassLivestockBalance(this.buildPayload())
          .then((res) => {
            this.result = { ...this.emptyResult(), ...(res.data || {}) }
            this.resultCalculated = true
          })
          .catch(() => {
            this.clearResult()
          })
          .finally(() => {
            this.calculating = false
          })
      })
    },
    handleClear() {
      this.form = this.emptyForm()
      this.applyDefaultSheepParams()
      this.clearResult()
      this.grasslandOptions = []
      this.$nextTick(() => {
        if (this.$refs.form) {
          this.$refs.form.clearValidate()
        }
      })
    },
    formatDecimal(val) {
      if (val == null || val === "") {
        return null
      }
      const n = Number(val)
      if (isNaN(n)) {
        return null
      }
      return n.toFixed(2)
    },
    formatSignedValue(val, unit) {
      const text = this.formatDecimal(val)
      if (text == null) {
        return null
      }
      const n = Number(val)
      if (n < 0) {
        return `${this.formatDecimal(Math.abs(n))}${unit}${this.dmT("surplusSuffix")}`
      }
      return `${text}${unit}`
    },
    formatResultField(field) {
      if (!this.resultCalculated) {
        return this.$t("dataModel.status.dash")
      }
      const val = this.result[field.key]
      if (field.type === "text") {
        return val != null && val !== "" ? val : this.$t("dataModel.status.dash")
      }
      if (field.type === "percent") {
        if (val == null || val === "") {
          return this.$t("dataModel.status.dash")
        }
        return `${this.formatDecimal(val)}%`
      }
      if (field.type === "integer") {
        if (val == null || val === "") {
          return this.$t("dataModel.status.dash")
        }
        const unit = field.unitKey ? this.dmT(field.unitKey) : ""
        return `${val}${unit}`
      }
      const unit = field.unitKey ? this.dmT(field.unitKey) : ""
      if (field.type === "signed") {
        const signed = this.formatSignedValue(val, unit)
        return signed != null ? signed : this.$t("dataModel.status.dash")
      }
      const text = this.formatDecimal(val)
      return text != null ? `${text}${unit}` : this.$t("dataModel.status.dash")
    }
  }
}
</script>

<style scoped>
.glb-card__title {
  font-weight: 600;
  font-size: 15px;
}
.glb-form__actions {
  margin-bottom: 0;
}
.glb-readonly {
  display: inline-block;
  min-height: 32px;
  line-height: 32px;
  color: #606266;
}
.glb-level {
  font-weight: 600;
}
.glb-level--ok {
  color: #67c23a;
}
.glb-level--basic {
  color: #409eff;
}
.glb-level--warn {
  color: #e6a23c;
}
.glb-level--severe {
  color: #f56c6c;
}
.glb-warning {
  margin-bottom: 16px;
}
.glb-formula-list {
  margin: 0;
  padding-left: 20px;
  color: #606266;
  line-height: 1.9;
  font-size: 13px;
}
.glb-formula-list--compact {
  margin-top: 8px;
}
.glb-formula-level-title {
  margin: 16px 0 4px;
  font-size: 13px;
  color: #303133;
  font-weight: 600;
}
.dm-input-with-unit {
  display: flex;
  align-items: center;
  width: 100%;
  min-width: 0;
}
.dm-input-with-unit__input {
  flex: 1;
  width: 100%;
  min-width: 120px;
}
.dm-input-with-unit__input ::v-deep .el-input-number {
  width: 100%;
}
.dm-input-with-unit__suffix {
  flex-shrink: 0;
  margin-left: 8px;
  color: #909399;
  font-size: 13px;
  white-space: nowrap;
}
.glb-form--responsive ::v-deep .el-form-item__label {
  line-height: 1.4;
  padding-bottom: 4px;
}
</style>
