<script setup lang="ts">
import { computed } from "vue";
import { Document } from "@element-plus/icons-vue";
import AuditBasicInfoReviewPanel from "./AuditBasicInfoReviewPanel.vue";
import AuditWriteOffDocsReviewPanel from "./AuditWriteOffDocsReviewPanel.vue";
import AuditExpertProfileReviewPanel from "./AuditExpertProfileReviewPanel.vue";
import AuditExpertReviewPanel from "./AuditExpertReviewPanel.vue";

export type AuditMaterialModuleCode =
  | "BASIC_INFO"
  | "WRITE_OFF_DOCS"
  | "EXPERT_PROFILE"
  | "EXPERT_LIST"
  | "MEETING_INVOICE";

type ExpertReviewSubModuleCode = "ONSITE_PHOTO" | "LABOR_PROTOCOL";

type MeetingInvoiceAuditFileRow = { fileName?: string; ossKey?: string };

const materialDialogVisible = defineModel<boolean>("materialDialogVisible", {
  required: true,
});
const materialModule = defineModel<AuditMaterialModuleCode>("materialModule", {
  required: true,
});
const expertReviewSubModule = defineModel<ExpertReviewSubModuleCode>(
  "expertReviewSubModule",
  { required: true },
);
const selectedAuditExpertId = defineModel<number | null>(
  "selectedAuditExpertId",
  { required: true },
);

const props = defineProps<{
  materialBudgetView: {
    ready: boolean;
    overCent: number;
    budgetCent: number;
    laborTotalCent: number;
    meetingInvoiceTotalCent: number;
    usedTotalCent: number;
    remainCent: number;
  };
  formatYuan: (cent: unknown) => number;
  basicView: Record<string, any>;
  docView: Record<string, any>;
  expertProfileView: Record<string, any>;
  photoView: Record<string, any>;
  meetingInvoiceView: { sections: any[] };
  expertReviewRows: Array<{ expertId: number; expertName: string }>;
  selectedAuditPhotos: any[];
  selectedAuditLaborDetails: any[];
  selectedAuditExpertName: string;
  canReject: boolean;
  canApprove: boolean;
  toReviewTagType: (
    itemKey: string | string[],
  ) => "success" | "danger" | "info";
  toReviewResultText: (itemKey: string | string[]) => string;
  getFileUrl: (ossKey: unknown) => string;
  isImageAttachment: (name: unknown, ossKey: unknown) => boolean;
  isPdfAttachment: (name: unknown, ossKey: unknown) => boolean;
  openFileUrl: (ossKey: unknown) => void;
  previewOssDocument: (
    ossKey: string,
    fileNameHint?: string,
  ) => void | Promise<void>;
  buildPhotoItemKey: (row: any, idx: number) => string;
  buildLaborItemKey: (row: any, idx: number) => string;
  buildLaborReviewItemKeys: (row: any, idx: number) => string | string[];
  buildMeetingInvoiceFieldItemKey: (
    sectionCode: string,
    fieldKey: string,
  ) => string;
  buildMeetingInvoiceAmountItemKey: (sectionCode: string) => string;
  approvingCurrentModule: boolean;
  materialTaskId: number | null;
  materialContent: string;
  materialAuditNode: string;
  handleSelectAuditExpert: (row: any) => void;
  handleRejectMaterialItem: (itemKey: string, itemLabel: string) => void;
  handleApproveCurrentModule: () => void;
}>();

const emit = defineEmits<{
  materialTabChange: [tabName: string | number];
}>();

const isHigherReview = computed(() => {
  const node = String(props.materialAuditNode || "").trim().toUpperCase();
  return node === "RE_REVIEW" || node === "FINAL_REVIEW";
});

const meetingInvoiceFileDisplayName = (file: MeetingInvoiceAuditFileRow) => {
  const fileName = String(file?.fileName ?? "").trim();
  if (fileName) {
    return fileName;
  }
  const key = String(file?.ossKey ?? "").trim();
  const tail = key.split("/").pop() || key;
  return tail || "附件";
};

const previewMeetingInvoiceFile = (file: MeetingInvoiceAuditFileRow) => {
  const key = String(file?.ossKey ?? "").trim();
  if (!key) {
    return;
  }
  void props.previewOssDocument(key, String(file?.fileName ?? ""));
};
</script>

<template>
  <el-drawer v-model="materialDialogVisible" title="审核资料查看" size="70%">
    <el-tabs
      v-model="materialModule"
      @tab-change="emit('materialTabChange', $event)"
    >
      <el-tab-pane label="会议基本信息" name="BASIC_INFO" />
      <el-tab-pane label="核销材料" name="WRITE_OFF_DOCS" />
      <el-tab-pane label="专家简介/串场" name="EXPERT_PROFILE" />
      <el-tab-pane label="专家列表" name="EXPERT_LIST" />
      <el-tab-pane label="会议发票" name="MEETING_INVOICE" />
    </el-tabs>

    <el-alert
      v-if="materialBudgetView.ready"
      :type="materialBudgetView.overCent > 0 ? 'error' : 'success'"
      :closable="false"
      class="mb-md"
    >
      <template #title>
        预算校验（结论：
        <el-tag
          size="small"
          :type="materialBudgetView.overCent > 0 ? 'danger' : 'success'"
        >
          {{ materialBudgetView.overCent > 0 ? "不通过" : "通过" }}
        </el-tag>
        ）：预算 {{ formatYuan(materialBudgetView.budgetCent) }} 元，劳务
        {{ formatYuan(materialBudgetView.laborTotalCent) }} 元，会议发票
        {{ formatYuan(materialBudgetView.meetingInvoiceTotalCent) }} 元，已用
        {{ formatYuan(materialBudgetView.usedTotalCent) }} 元，
        <span v-if="materialBudgetView.overCent > 0">
          超预算 {{ formatYuan(materialBudgetView.overCent) }} 元
        </span>
        <span v-else>
          剩余 {{ formatYuan(materialBudgetView.remainCent) }} 元
        </span>
      </template>
    </el-alert>

    <AuditBasicInfoReviewPanel
      v-if="materialModule === 'BASIC_INFO'"
      :basic-view="basicView"
      :can-reject="canReject"
      :is-higher-review="isHigherReview"
      :to-review-tag-type="toReviewTagType"
      :to-review-result-text="toReviewResultText"
      :handle-reject-material-item="handleRejectMaterialItem"
    />

    <AuditWriteOffDocsReviewPanel
      v-else-if="materialModule === 'WRITE_OFF_DOCS'"
      :doc-view="docView"
      :can-reject="canReject"
      :is-higher-review="isHigherReview"
      :to-review-tag-type="toReviewTagType"
      :to-review-result-text="toReviewResultText"
      :get-file-url="getFileUrl"
      :is-image-attachment="isImageAttachment"
      :is-pdf-attachment="isPdfAttachment"
      :open-file-url="openFileUrl"
      :preview-oss-document="previewOssDocument"
      :handle-reject-material-item="handleRejectMaterialItem"
    />

    <AuditExpertProfileReviewPanel
      v-else-if="materialModule === 'EXPERT_PROFILE'"
      :expert-profile-view="expertProfileView"
      :can-reject="canReject"
      :is-higher-review="isHigherReview"
      :to-review-tag-type="toReviewTagType"
      :to-review-result-text="toReviewResultText"
      :get-file-url="getFileUrl"
      :is-image-attachment="isImageAttachment"
      :is-pdf-attachment="isPdfAttachment"
      :open-file-url="openFileUrl"
      :preview-oss-document="previewOssDocument"
      :handle-reject-material-item="handleRejectMaterialItem"
    />

    <div v-else-if="materialModule === 'EXPERT_LIST'" class="audit-expert-root">
      <AuditExpertReviewPanel
        v-model:expert-review-sub-module="expertReviewSubModule"
        v-model:selected-audit-expert-id="selectedAuditExpertId"
        :basic-view="basicView"
        :photo-view="photoView"
        :expert-review-rows="expertReviewRows"
        :selected-audit-photos="selectedAuditPhotos"
        :selected-audit-labor-details="selectedAuditLaborDetails"
        :selected-audit-expert-name="selectedAuditExpertName"
        :can-reject="canReject"
        :is-higher-review="isHigherReview"
        :format-yuan="formatYuan"
        :to-review-tag-type="toReviewTagType"
        :to-review-result-text="toReviewResultText"
        :get-file-url="getFileUrl"
        :is-image-attachment="isImageAttachment"
        :is-pdf-attachment="isPdfAttachment"
        :open-file-url="openFileUrl"
        :preview-oss-document="previewOssDocument"
        :build-photo-item-key="buildPhotoItemKey"
        :build-labor-item-key="buildLaborItemKey"
        :build-labor-review-item-keys="buildLaborReviewItemKeys"
        :handle-select-audit-expert="handleSelectAuditExpert"
        :handle-reject-material-item="handleRejectMaterialItem"
      />
    </div>

    <div
      v-else-if="materialModule === 'MEETING_INVOICE'"
      class="audit-meeting-invoice-root"
    >
      <el-alert
        title="以下分项与会议端上传结构一致；图片可点开放大，PDF 可在弹窗内预览"
        type="info"
        :closable="false"
        class="audit-meeting-invoice-hint"
      />
      <div
        v-for="(section, sectionIndex) in meetingInvoiceView.sections"
        :key="section.sectionCode"
        class="audit-meeting-invoice-section"
      >
        <div class="audit-meeting-invoice-section__head">
          <span class="audit-meeting-invoice-section__title">
            {{ sectionIndex + 1 }}、{{ section.sectionTitle }}
          </span>
        </div>
        <div class="audit-meeting-invoice-section__body">
          <div
            v-for="(file, fileIdx) in section.files"
            :key="`${section.sectionCode}-${file.fieldKey}-${file.ossKey || 'empty'}-${fileIdx}`"
            class="audit-meeting-invoice-file-row"
          >
            <div class="audit-meeting-invoice-file-row__label">
              {{ file.rowLabel ?? file.label }}
            </div>
            <div class="audit-meeting-invoice-file-row__main">
              <div class="audit-meeting-invoice-file-row__preview">
                <template v-if="!file.ossKey">
                  <div class="audit-meeting-invoice-file-row__empty">
                    未上传
                  </div>
                </template>
                <el-image
                  v-else-if="
                    isImageAttachment(file.fileName, file.ossKey) &&
                    getFileUrl(file.ossKey)
                  "
                  :src="getFileUrl(file.ossKey)"
                  fit="cover"
                  :preview-src-list="[getFileUrl(file.ossKey)]"
                  :preview-teleported="true"
                  class="audit-meeting-invoice-thumb audit-meeting-invoice-thumb--image"
                />
                <div
                  v-else-if="isPdfAttachment(file.fileName, file.ossKey)"
                  class="audit-meeting-invoice-thumb audit-labor-pdf-thumb"
                  :title="meetingInvoiceFileDisplayName(file)"
                  role="button"
                  tabindex="0"
                  @click="previewMeetingInvoiceFile(file)"
                  @keydown.enter.prevent="previewMeetingInvoiceFile(file)"
                >
                  <el-icon class="audit-labor-pdf-thumb__icon"><Document /></el-icon>
                  <span class="audit-labor-pdf-thumb__label">PDF</span>
                </div>
                <el-button
                  v-else
                  size="small"
                  type="primary"
                  @click="previewMeetingInvoiceFile(file)"
                >
                  查看
                </el-button>
              </div>
              <div
                v-if="file.ossKey"
                class="audit-meeting-invoice-file-row__name"
                :title="meetingInvoiceFileDisplayName(file)"
              >
                {{ meetingInvoiceFileDisplayName(file) }}
              </div>
            </div>
            <div class="audit-meeting-invoice-file-row__actions">
              <template
                v-if="file.showFieldReviewControls !== false && !isHigherReview"
              >
                <el-tag
                  size="small"
                  :type="
                    toReviewTagType(
                      buildMeetingInvoiceFieldItemKey(
                        section.sectionCode,
                        file.fieldKey,
                      ),
                    )
                  "
                >
                  {{
                    toReviewResultText(
                      buildMeetingInvoiceFieldItemKey(
                        section.sectionCode,
                        file.fieldKey,
                      ),
                    )
                  }}
                </el-tag>
                <el-button
                  v-if="canReject"
                  size="small"
                  type="danger"
                  link
                  @click="
                    handleRejectMaterialItem(
                      buildMeetingInvoiceFieldItemKey(
                        section.sectionCode,
                        file.fieldKey,
                      ),
                      `${section.sectionTitle}-${file.label}`,
                    )
                  "
                >
                  不通过
                </el-button>
              </template>
            </div>
          </div>

          <div v-if="section.needAmount" class="audit-meeting-invoice-amount">
            <div class="audit-meeting-invoice-amount__label">
              总费用金额（元）
            </div>
            <div class="audit-meeting-invoice-amount__value">
              {{ section.totalAmountYuan ?? "-" }}
            </div>
            <div class="audit-meeting-invoice-amount__actions">
              <el-tag
                v-if="!isHigherReview"
                size="small"
                :type="
                  toReviewTagType(
                    buildMeetingInvoiceAmountItemKey(section.sectionCode),
                  )
                "
              >
                {{
                  toReviewResultText(
                    buildMeetingInvoiceAmountItemKey(section.sectionCode),
                  )
                }}
              </el-tag>
              <el-button
                v-if="canReject && !isHigherReview"
                size="small"
                type="danger"
                link
                @click="
                  handleRejectMaterialItem(
                    buildMeetingInvoiceAmountItemKey(section.sectionCode),
                    `${section.sectionTitle}-总费用金额`,
                  )
                "
              >
                不通过
              </el-button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="flex-end mt-md">
      <el-button
        v-if="canApprove && !isHigherReview"
        type="success"
        :loading="approvingCurrentModule"
        :disabled="!materialTaskId"
        @click="handleApproveCurrentModule"
      >
        本模块审核通过
      </el-button>
    </div>

    <el-divider />
    <el-input
      :model-value="materialContent"
      type="textarea"
      :rows="6"
      readonly
    />
  </el-drawer>
</template>

<style scoped>
.audit-expert-root {
  min-height: 560px;
}

.audit-labor-pdf-thumb {
  width: 56px;
  height: 56px;
  border-radius: 4px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 4px;
  background: var(--el-fill-color-light);
  cursor: pointer;
  border: 1px solid var(--el-border-color-lighter);
}

.audit-labor-pdf-thumb:focus-visible {
  outline: 2px solid var(--el-color-primary);
  outline-offset: 1px;
}

.audit-labor-pdf-thumb__icon {
  font-size: 22px;
  color: var(--el-text-color-secondary);
}

.audit-labor-pdf-thumb__label {
  font-size: 10px;
  line-height: 1;
  color: var(--el-text-color-regular);
}

.audit-meeting-invoice-root {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.audit-meeting-invoice-hint {
  margin-bottom: 0;
}

.audit-meeting-invoice-section {
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 8px;
  background: var(--el-bg-color);
  overflow: hidden;
}

.audit-meeting-invoice-section__head {
  padding: 10px 14px;
  background: var(--el-fill-color-light);
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.audit-meeting-invoice-section__title {
  font-weight: 600;
  font-size: 14px;
  color: var(--el-text-color-primary);
  padding-left: 10px;
  border-left: 3px solid var(--el-color-primary);
}

.audit-meeting-invoice-section__body {
  padding: 12px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.audit-meeting-invoice-file-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px dashed var(--el-border-color-lighter);
}

.audit-meeting-invoice-file-row:last-of-type {
  border-bottom: none;
  padding-bottom: 4px;
}

.audit-meeting-invoice-file-row__label {
  flex: 0 0 132px;
  font-size: 13px;
  color: var(--el-text-color-regular);
  line-height: 22px;
  padding-top: 4px;
}

.audit-meeting-invoice-file-row__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

.audit-meeting-invoice-file-row__preview {
  display: flex;
  align-items: center;
  gap: 8px;
}

.audit-meeting-invoice-thumb--image {
  width: 64px;
  height: 64px;
  border-radius: 6px;
  border: 1px solid var(--el-border-color-lighter);
  cursor: zoom-in;
}

.audit-meeting-invoice-thumb.audit-labor-pdf-thumb {
  width: 64px;
  height: 64px;
  border-radius: 6px;
}

.audit-meeting-invoice-file-row__empty {
  min-width: 64px;
  min-height: 40px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: var(--el-text-color-placeholder);
  background: var(--el-fill-color-lighter);
  border-radius: 6px;
  border: 1px dashed var(--el-border-color);
}

.audit-meeting-invoice-file-row__name {
  font-size: 12px;
  color: var(--el-text-color-secondary);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.audit-meeting-invoice-file-row__actions {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding-top: 4px;
}

.audit-meeting-invoice-amount {
  margin-top: 8px;
  padding: 12px 14px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  background: var(--el-fill-color-blank);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 6px;
}

.audit-meeting-invoice-amount__label {
  font-size: 13px;
  color: var(--el-text-color-regular);
  font-weight: 500;
}

.audit-meeting-invoice-amount__value {
  font-size: 18px;
  font-weight: 600;
  color: var(--el-text-color-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.audit-meeting-invoice-amount__actions {
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
</style>
