<template>
  <div class="app-container">
    <el-card shadow="never">
      <el-form ref="queryForm" :model="queryParams" size="small" :inline="true">
        <el-form-item prop="appointeeName">
          <template slot="label">{{ tsT("queryAppointeeName") }}</template>
          <el-input
            v-model="queryParams.appointeeName"
            :placeholder="tsT('queryAppointeeNamePh')"
            clearable
            style="width: 160px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item>
          <template slot="label">{{ tsT("queryAppointDate") }}</template>
          <el-date-picker
            v-model="queryDateRange"
            type="daterange"
            value-format="yyyy-MM-dd"
            range-separator="-"
            :start-placeholder="tsT('queryDateRangePh')"
            :end-placeholder="tsT('queryDateRangeEndPh')"
            clearable
            style="width: 240px"
          />
        </el-form-item>
        <el-form-item prop="status">
          <template slot="label">{{ tsT("queryStatus") }}</template>
          <el-select v-model="queryParams.status" :placeholder="tsCommon('pleaseSelect')" clearable style="width: 140px">
            <el-option
              v-for="item in statusOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">{{ tsCommon("search") }}</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{ tsCommon("reset") }}</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <br />

    <el-card shadow="never">
      <el-table v-loading="loading" :data="tableList" border>
        <el-table-column :label="tsT('colAppointeeName')" prop="appointeeName" align="center" min-width="100" :show-overflow-tooltip="true" />
        <el-table-column :label="tsT('colAppointDate')" prop="appointDate" align="center" width="120" />
        <el-table-column :label="tsT('colTimeSlot')" align="center" width="130">
          <template slot-scope="scope">
            <span>{{ formatTimeSlot(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colContactPhone')" prop="contactPhone" align="center" width="120" :show-overflow-tooltip="true" />
        <el-table-column :label="tsT('colServiceAddress')" prop="serviceAddress" align="center" min-width="140" :show-overflow-tooltip="true" />
        <el-table-column :label="tsT('colServiceRequirement')" prop="serviceRequirement" align="center" min-width="140" :show-overflow-tooltip="true" />
        <el-table-column :label="tsT('colStatus')" align="center" width="100">
          <template slot-scope="scope">
            <el-tag
              v-if="expertAppointmentStatusTagType(scope.row.status)"
              :type="expertAppointmentStatusTagType(scope.row.status)"
              size="mini"
            >
              {{ displayStatus(scope.row) }}
            </el-tag>
            <span v-else>{{ displayStatus(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colRejectReason')" prop="rejectReason" align="center" min-width="120" :show-overflow-tooltip="true" />
        <el-table-column :label="tsCommon('colOp')" align="center" class-name="small-padding fixed-width" width="360" fixed="right">
          <template slot-scope="scope">
            <el-button
              v-hasPermi="['techService:expertMyAppointment:query']"
              type="text"
              size="mini"
              @click="handleView(scope.row)"
            >{{ tsCommon("view") }}</el-button>
            <el-button
              v-if="canConfirmOrReject(scope.row)"
              v-hasPermi="['techService:expertMyAppointment:confirm']"
              type="text"
              size="mini"
              @click="handleConfirm(scope.row)"
            >{{ tsT("actionConfirm") }}</el-button>
            <el-button
              v-if="canConfirmOrReject(scope.row)"
              v-hasPermi="['techService:expertMyAppointment:reject']"
              type="text"
              size="mini"
              @click="openReject(scope.row)"
            >{{ tsT("actionReject") }}</el-button>
            <el-button
              v-if="canComplete(scope.row)"
              v-hasPermi="['techService:expertMyAppointment:complete']"
              type="text"
              size="mini"
              @click="handleComplete(scope.row)"
            >{{ tsT("actionComplete") }}</el-button>
            <el-button
              v-if="canViewReview(scope.row)"
              v-hasPermi="['techService:expertMyAppointment:reviewList']"
              type="text"
              size="mini"
              @click="handleViewReviews(scope.row)"
            >{{ tsT("actionViewReview") }}</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
      />
    </el-card>

    <el-dialog :title="tsT('viewTitle')" :visible.sync="viewOpen" width="680px" append-to-body>
      <el-descriptions v-if="viewRow.id" :column="1" border size="small">
        <el-descriptions-item :label="tsT('viewAppointeeName')">{{ viewRow.appointeeName || dash }}</el-descriptions-item>
        <el-descriptions-item :label="tsT('viewAppointDate')">{{ viewRow.appointDate || dash }}</el-descriptions-item>
        <el-descriptions-item :label="tsT('viewTimeSlot')">{{ formatTimeSlot(viewRow) || dash }}</el-descriptions-item>
        <el-descriptions-item :label="tsT('viewContactPhone')">{{ viewRow.contactPhone || dash }}</el-descriptions-item>
        <el-descriptions-item :label="tsT('viewServiceAddress')">{{ viewRow.serviceAddress || dash }}</el-descriptions-item>
        <el-descriptions-item :label="tsT('viewServiceRequirement')">{{ viewRow.serviceRequirement || dash }}</el-descriptions-item>
        <el-descriptions-item :label="tsT('viewStatus')">{{ displayStatus(viewRow) }}</el-descriptions-item>
        <el-descriptions-item v-if="viewRow.status === STATUS_REJECTED" :label="tsT('viewRejectReason')">
          {{ viewRow.rejectReason || dash }}
        </el-descriptions-item>
        <el-descriptions-item v-if="viewRow.confirmTime" :label="tsT('viewConfirmTime')">{{ viewRow.confirmTime }}</el-descriptions-item>
        <el-descriptions-item v-if="viewRow.rejectTime" :label="tsT('viewRejectTime')">{{ viewRow.rejectTime }}</el-descriptions-item>
      </el-descriptions>
      <div v-if="viewRow.status === STATUS_COMPLETED" class="expert-appt-review-block">
        <div class="expert-appt-review-block__title">{{ tsT("viewReviewSection") }}</div>
        <template v-if="hasDetailReview(viewRow)">
          <div class="expert-appt-review-block__row">
            <span class="expert-appt-review-block__label">{{ tsT("viewPunctuality") }}</span>
            <el-rate :value="viewRow.punctualityScore" disabled show-score text-color="#ff9900" score-template="{value}" />
          </div>
          <div class="expert-appt-review-block__row">
            <span class="expert-appt-review-block__label">{{ tsT("viewAttitude") }}</span>
            <el-rate :value="viewRow.attitudeScore" disabled show-score text-color="#ff9900" score-template="{value}" />
          </div>
          <div class="expert-appt-review-block__row">
            <span class="expert-appt-review-block__label">{{ tsT("viewGuidance") }}</span>
            <el-rate :value="viewRow.guidanceScore" disabled show-score text-color="#ff9900" score-template="{value}" />
          </div>
          <div class="expert-appt-review-block__summary">
            <span class="expert-appt-review-block__label">{{ tsT("viewSummary") }}</span>
            <span>{{ viewRow.summary || dash }}</span>
          </div>
        </template>
        <div v-else class="expert-appt-review-block__empty">{{ tsT("noReview") }}</div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="viewOpen = false">{{ tsCommon("close") }}</el-button>
        <el-button
          v-if="canViewReview(viewRow)"
          v-hasPermi="['techService:expertMyAppointment:reviewList']"
          type="primary"
          plain
          @click="handleViewReviews(viewRow)"
        >{{ tsT("actionViewReview") }}</el-button>
        <el-button
          v-if="canConfirmOrReject(viewRow)"
          v-hasPermi="['techService:expertMyAppointment:confirm']"
          type="primary"
          @click="handleConfirm(viewRow)"
        >{{ tsT("actionConfirm") }}</el-button>
        <el-button
          v-if="canConfirmOrReject(viewRow)"
          v-hasPermi="['techService:expertMyAppointment:reject']"
          type="danger"
          plain
          @click="openReject(viewRow)"
        >{{ tsT("actionReject") }}</el-button>
        <el-button
          v-if="canComplete(viewRow)"
          v-hasPermi="['techService:expertMyAppointment:complete']"
          type="primary"
          plain
          @click="handleComplete(viewRow)"
        >{{ tsT("actionComplete") }}</el-button>
      </div>
    </el-dialog>

    <el-dialog :title="tsT('rejectTitle')" :visible.sync="rejectOpen" width="480px" append-to-body @close="cancelReject">
      <el-form ref="rejectForm" :model="rejectForm" label-width="100px">
        <el-form-item prop="rejectReason" :rules="rejectRules">
          <template slot="label">{{ tsT("rejectReason") }}</template>
          <el-input
            v-model="rejectForm.rejectReason"
            type="textarea"
            :rows="4"
            maxlength="100"
            show-word-limit
            :placeholder="tsT('rejectReasonPh')"
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancelReject">{{ tsCommon("cancel") }}</el-button>
        <el-button type="primary" :loading="rejectSubmitting" @click="submitReject">{{ tsCommon("ok") }}</el-button>
      </div>
    </el-dialog>

    <el-dialog :title="tsT('reviewTitle')" :visible.sync="reviewOpen" width="920px" append-to-body>
      <el-table v-loading="reviewLoading" :data="reviewList" border>
        <template slot="empty">
          <span>{{ tsT("emptyReviews") }}</span>
        </template>
        <el-table-column :label="tsT('colReviewerName')" prop="reviewerName" align="center" min-width="90" />
        <el-table-column :label="tsT('colReviewTime')" prop="reviewTime" align="center" width="160" />
        <el-table-column :label="tsT('viewPunctuality')" align="center" width="130">
          <template slot-scope="scope">
            <el-rate :value="scope.row.punctualityScore" disabled />
          </template>
        </el-table-column>
        <el-table-column :label="tsT('viewAttitude')" align="center" width="130">
          <template slot-scope="scope">
            <el-rate :value="scope.row.attitudeScore" disabled />
          </template>
        </el-table-column>
        <el-table-column :label="tsT('viewGuidance')" align="center" width="130">
          <template slot-scope="scope">
            <el-rate :value="scope.row.guidanceScore" disabled />
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colReviewSummary')" prop="summary" align="center" min-width="160" :show-overflow-tooltip="true" />
      </el-table>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="reviewOpen = false">{{ tsCommon("close") }}</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import techServiceLocaleMixin from "@/mixins/techServiceLocaleMixin"
import {
  listExpertMyAppointment,
  getExpertMyAppointment,
  confirmExpertMyAppointment,
  rejectExpertMyAppointment,
  listExpertMyAppointmentReviews,
  completeExpertMyAppointment
} from "@/api/techService/expertMyAppointment"

const STATUS_PENDING = 0
const STATUS_CONFIRMED = 1
const STATUS_REJECTED = 2
const STATUS_COMPLETED = 4

export default {
  name: "TechServiceExpertMyAppointment",
  mixins: [techServiceLocaleMixin],
  data() {
    return {
      tsNs: "expertMyAppointment",
      STATUS_PENDING,
      STATUS_CONFIRMED,
      STATUS_REJECTED,
      STATUS_COMPLETED,
      loading: false,
      tableList: [],
      total: 0,
      queryDateRange: null,
      queryParams: {
        pageNum: 1,
        pageSize: 20,
        appointeeName: undefined,
        startDate: undefined,
        endDate: undefined,
        status: undefined
      },
      viewOpen: false,
      viewRow: {},
      rejectOpen: false,
      rejectSubmitting: false,
      rejectTargetId: null,
      rejectForm: {
        rejectReason: ""
      },
      reviewOpen: false,
      reviewLoading: false,
      reviewList: []
    }
  },
  computed: {
    dash() {
      return this.$t("techService.status.dash")
    },
    statusOptions() {
      return [0, 1, 2, 3, 4].map((value) => ({
        value,
        label: this.expertAppointmentStatusText(value)
      }))
    },
    rejectRules() {
      return [
        { required: true, message: this.tsT("rejectReasonRequired"), trigger: "blur" },
        { min: 1, max: 100, message: this.tsT("rejectReasonLen"), trigger: "blur" }
      ]
    }
  },
  created() {
    this.getList()
  },
  methods: {
    getList() {
      if (!this.checkQueryDateRange()) {
        return
      }
      this.syncDateRangeToQuery()
      this.loading = true
      listExpertMyAppointment(this.queryParams)
        .then((res) => {
          this.tableList = res.rows || []
          this.total = res.total || 0
        })
        .finally(() => {
          this.loading = false
        })
    },
    checkQueryDateRange() {
      if (this.queryDateRange && this.queryDateRange.length === 2) {
        const [start, end] = this.queryDateRange
        if (start && end && start > end) {
          this.$modal.msgWarning(this.tsT("dateRangeInvalid"))
          return false
        }
      }
      return true
    },
    syncDateRangeToQuery() {
      if (this.queryDateRange && this.queryDateRange.length === 2) {
        this.queryParams.startDate = this.queryDateRange[0]
        this.queryParams.endDate = this.queryDateRange[1]
      } else {
        this.queryParams.startDate = undefined
        this.queryParams.endDate = undefined
      }
    },
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    resetQuery() {
      this.queryDateRange = null
      this.queryParams = {
        pageNum: 1,
        pageSize: 20,
        appointeeName: undefined,
        startDate: undefined,
        endDate: undefined,
        status: undefined
      }
      this.$nextTick(() => {
        if (this.$refs.queryForm) {
          this.$refs.queryForm.resetFields()
        }
      })
      this.getList()
    },
    formatTimeSlot(row) {
      if (!row) {
        return ""
      }
      const start = row.timeStart
      const end = row.timeEnd
      if (start && end) {
        return `${start}~${end}`
      }
      return start || end || ""
    },
    displayStatus(row) {
      if (!row || row.status == null) {
        return this.dash
      }
      if (row.statusLabel) {
        return row.statusLabel
      }
      return this.expertAppointmentStatusText(row.status)
    },
    canConfirmOrReject(row) {
      return row && row.status === STATUS_PENDING
    },
    canComplete(row) {
      if (!row) {
        return false
      }
      if (row.canComplete != null) {
        return !!row.canComplete
      }
      return row.status === STATUS_CONFIRMED
    },
    canViewReview(row) {
      return row && row.status === STATUS_COMPLETED
    },
    hasDetailReview(row) {
      return (
        row &&
        (row.punctualityScore != null ||
          row.attitudeScore != null ||
          row.guidanceScore != null ||
          (row.summary && String(row.summary).trim()))
      )
    },
    handleView(row) {
      getExpertMyAppointment(row.id).then((res) => {
        this.viewRow = res.data || {}
        this.viewOpen = true
      })
    },
    handleConfirm(row) {
      if (!row || !row.id) {
        return
      }
      this.$modal
        .confirm(this.tsT("confirmAcceptMsg"))
        .then(() => confirmExpertMyAppointment(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.tsT("msgConfirmOk"))
          this.viewOpen = false
          this.getList()
        })
        .catch(() => {})
    },
    handleComplete(row) {
      if (!row || !row.id) {
        return
      }
      this.$modal
        .confirm(this.tsT("confirmCompleteMsg"))
        .then(() => completeExpertMyAppointment(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.tsT("msgCompleteOk"))
          this.viewOpen = false
          this.getList()
        })
        .catch(() => {})
    },
    openReject(row) {
      if (!row || !row.id) {
        return
      }
      this.rejectTargetId = row.id
      this.rejectForm.rejectReason = ""
      this.rejectOpen = true
      this.$nextTick(() => {
        if (this.$refs.rejectForm) {
          this.$refs.rejectForm.clearValidate()
        }
      })
    },
    cancelReject() {
      this.rejectOpen = false
      this.rejectTargetId = null
      this.rejectForm.rejectReason = ""
    },
    submitReject() {
      this.$refs.rejectForm.validate((valid) => {
        if (!valid || !this.rejectTargetId) {
          return
        }
        const reason = (this.rejectForm.rejectReason || "").trim()
        if (!reason) {
          this.$modal.msgWarning(this.tsT("rejectReasonRequired"))
          return
        }
        this.rejectSubmitting = true
        rejectExpertMyAppointment(this.rejectTargetId, { rejectReason: reason })
          .then(() => {
            this.$modal.msgSuccess(this.tsT("msgRejectOk"))
            this.rejectOpen = false
            this.viewOpen = false
            this.getList()
          })
          .finally(() => {
            this.rejectSubmitting = false
          })
      })
    },
    handleViewReviews(row) {
      if (!row || !row.id) {
        return
      }
      this.reviewOpen = true
      this.reviewLoading = true
      this.reviewList = []
      listExpertMyAppointmentReviews(row.id)
        .then((res) => {
          this.reviewList = res.data || []
        })
        .finally(() => {
          this.reviewLoading = false
        })
    }
  }
}
</script>

<style scoped lang="scss">
.expert-appt-review-block {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid #ebeef5;
}

.expert-appt-review-block__title {
  font-weight: 600;
  font-size: 14px;
  color: #303133;
  margin-bottom: 12px;
}

.expert-appt-review-block__row {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  gap: 12px;
}

.expert-appt-review-block__label {
  flex-shrink: 0;
  width: 88px;
  font-size: 13px;
  color: #606266;
}

.expert-appt-review-block__summary {
  font-size: 13px;
  line-height: 1.6;
  color: #303133;

  .expert-appt-review-block__label {
    display: block;
    margin-bottom: 6px;
  }
}

.expert-appt-review-block__empty {
  font-size: 13px;
  color: #909399;
}
</style>
