<script setup lang="tsx">
/* eslint-disable no-void */
import { computed, markRaw, reactive, ref } from 'vue';
import { ElMessageBox, ElTag, ElTooltip } from 'element-plus';
import {
  fetchDeleteWeeklyReport,
  fetchExportWeeklyReportContent,
  fetchGetTeamReportSummary,
  fetchGetWeeklyReportPage,
  fetchSubmitWeeklyReport
} from '@/service/api';
import { useAuth } from '@/hooks/business/auth';
import { useUIPaginatedTable } from '@/hooks/common/table';
import BusinessTableActionCell, { type BusinessTableAction } from '@/components/custom/business-table-action-cell';
import { type TeamViewContext, resolveTeamQueryUserIds } from '@/views/personal-center/shared/team-dashboard';
import {
  type WorkReportRow,
  createWeeklySearchParams,
  createWorkReportContentExportFallbackName,
  downloadBlob,
  formatDateTime,
  formatEmptyText,
  formatPeriod,
  formatPeriodDateRange,
  formatWeeklyPeriodLabel,
  getWorkReportStatusLabel,
  getWorkReportTypeDisplayLabel,
  resolveExportFilename,
  resolveWorkReportStatusTagType,
  transformWorkReportPage
} from '../shared/types';
import { resolveWorkReportSummaryPeriod } from '../shared/utils';
import TeamReportSummary from '../shared/components/team-report-summary.vue';
import WeeklyReportSearch from './modules/search-panel.vue';
import IconMdiDeleteOutline from '~icons/mdi/delete-outline';
import IconMdiEyeOutline from '~icons/mdi/eye-outline';
import IconMdiFileDocumentCheckOutline from '~icons/mdi/file-document-check-outline';
import IconMdiPencilOutline from '~icons/mdi/pencil-outline';
import IconMdiSendOutline from '~icons/mdi/send-outline';
import IconMdiDownloadOutline from '~icons/mdi/download-outline';

defineOptions({ name: 'WeeklyWorkReportIndex' });

const props = defineProps<{
  teamContext?: TeamViewContext | null;
}>();

const emit = defineEmits<{
  (e: 'create'): void;
  (e: 'edit', row: WorkReportRow): void;
  (e: 'detail', row: WorkReportRow): void;
  (e: 'approvalRecord', row: WorkReportRow): void;
}>();

const { hasAuth } = useAuth();
const exporting = ref(false);
const selectedRows = ref<Api.WorkReport.Weekly.WeeklyReport[]>([]);
const searchParams = reactive(createWeeklySearchParams());
const teamSummaryLoading = ref(false);
const teamSummary = ref<Api.WorkReport.Common.TeamReportSummary | null>(null);

const ACTION_ICON_MAP = {
  detail: markRaw(IconMdiEyeOutline),
  edit: markRaw(IconMdiPencilOutline),
  submit: markRaw(IconMdiSendOutline),
  delete: markRaw(IconMdiDeleteOutline),
  approvalRecord: markRaw(IconMdiFileDocumentCheckOutline),
  export: markRaw(IconMdiDownloadOutline)
};

const isTeamMode = computed(() => props.teamContext?.mode === 'team');
const isTeamRootSelected = computed(() => Boolean(isTeamMode.value && props.teamContext?.isRootSelected));
const currentTeamReporterIds = computed(() => resolveTeamQueryUserIds(props.teamContext));
const reportTitle = computed(() => getWorkReportTypeDisplayLabel('weekly', isTeamMode.value));

const table = useUIPaginatedTable<
  Awaited<ReturnType<typeof fetchGetWeeklyReportPage>>,
  Api.WorkReport.Weekly.WeeklyReport
>({
  paginationProps: { currentPage: searchParams.pageNo, pageSize: searchParams.pageSize },
  api: () =>
    fetchGetWeeklyReportPage({
      ...searchParams,
      reporterIds: currentTeamReporterIds.value
    }),
  transform: response => transformWorkReportPage(response, searchParams.pageNo ?? 1, searchParams.pageSize ?? 10),
  onPaginationParamsChange: params => {
    searchParams.pageNo = params.currentPage ?? 1;
    searchParams.pageSize = params.pageSize ?? 10;
  },
  columns: () => [
    { prop: 'index', type: 'index', label: '序号', width: 64 },
    ...(isTeamMode.value ? [{ prop: 'reporterName', label: '提交人', minWidth: 100, showOverflowTooltip: true }] : []),
    {
      prop: 'periodLabel',
      label: '周期',
      minWidth: 150,
      formatter: row => {
        const periodText = formatWeeklyPeriodLabel(row);
        const weekLabel = formatPeriodDateRange(row);
        if (!weekLabel || weekLabel === '--') return periodText;
        return (
          <ElTooltip content={weekLabel} placement="top">
            <span>{periodText}</span>
          </ElTooltip>
        );
      }
    },
    {
      prop: 'reporterDeptName',
      label: '部门',
      minWidth: 80,
      showOverflowTooltip: true,
      formatter: row => row.reporterDeptName || '--'
    },
    { prop: 'supervisorName', label: '直属上级', minWidth: 80 },
    { prop: 'totalWorkHours', label: '总工时', minWidth: 80, formatter: row => formatEmptyText(row.totalWorkHours) },
    {
      prop: 'isBusinessTrip',
      label: '出差',
      minWidth: 80,
      align: 'center',
      formatter: row => (row.isBusinessTrip ? '是' : '否')
    },
    {
      prop: 'totalTravelDays',
      label: '出差天数',
      minWidth: 90,
      formatter: row => formatEmptyText(row.totalTravelDays)
    },
    {
      prop: 'statusCode',
      label: '状态',
      minWidth: 80,
      align: 'center',
      formatter: row => (
        <ElTag type={resolveWorkReportStatusTagType(row.statusCode)}>
          {getWorkReportStatusLabel(row.statusCode, row.statusName)}
        </ElTag>
      )
    },
    { prop: 'submitTime', label: '提交时间', minWidth: 100, formatter: row => formatDateTime(row.submitTime) },
    { prop: 'approvalTime', label: '审批时间', minWidth: 100, formatter: row => formatDateTime(row.approvalTime) },
    {
      prop: 'operate',
      label: '操作',
      width: isTeamMode.value ? 140 : 180,
      align: 'center',
      fixed: 'right',
      formatter: row => <BusinessTableActionCell actions={getRowActions(row)} variant="icon" />
    }
  ]
});

const summaryPeriod = computed(() =>
  resolveWorkReportSummaryPeriod('weekly', {
    currentRow: table.data.value[0],
    periodRange: searchParams.periodStartDate
  })
);

function getRowActions(row: Api.WorkReport.Weekly.WeeklyReport): BusinessTableAction[] {
  const actions: BusinessTableAction[] = [
    {
      key: 'detail',
      label: '查看',
      buttonType: 'primary',
      icon: ACTION_ICON_MAP.detail,
      onClick: () => emit('detail', row)
    }
  ];

  if (isTeamMode.value) {
    actions.push({
      key: 'export',
      label: '导出',
      buttonType: 'success',
      icon: ACTION_ICON_MAP.export,
      onClick: () =>
        exportReportContent(
          {
            exportAll: false,
            ids: [row.id]
          },
          1
        )
    });

    if (['approved', 'rejected'].includes(row.statusCode)) {
      actions.push({
        key: 'approval-record',
        label: '审批记录',
        buttonType: 'info',
        icon: ACTION_ICON_MAP.approvalRecord,
        onClick: () => emit('approvalRecord', row)
      });
    }

    return actions;
  }

  if (['draft', 'rejected'].includes(row.statusCode) && row.allowEdit && hasAuth('project:work-report:update')) {
    actions.push({
      key: 'edit',
      label: '编辑',
      buttonType: 'primary',
      icon: ACTION_ICON_MAP.edit,
      onClick: () => emit('edit', row)
    });
    actions.push({
      key: 'submit',
      label: row.statusCode === 'draft' ? '提交' : '重新提交',
      buttonType: 'success',
      icon: ACTION_ICON_MAP.submit,
      onClick: () => handleSubmitReport(row)
    });
  }

  if (row.statusCode === 'draft' && hasAuth('project:work-report:delete')) {
    actions.push({
      key: 'delete',
      label: '删除',
      buttonType: 'danger',
      icon: ACTION_ICON_MAP.delete,
      onClick: () => handleDelete(row)
    });
  }

  if (['approved', 'rejected'].includes(row.statusCode)) {
    actions.push({
      key: 'approval-record',
      label: '审批记录',
      buttonType: 'info',
      icon: ACTION_ICON_MAP.approvalRecord,
      onClick: () => emit('approvalRecord', row)
    });
  }

  return actions;
}

async function reload(page?: number) {
  await table.getDataByPage(page ?? searchParams.pageNo ?? 1);
  await loadTeamSummary();
}

function resetSearchParams() {
  const pageSize = searchParams.pageSize ?? 10;
  Object.assign(searchParams, createWeeklySearchParams(), { pageSize });
  reload(1);
}

function handleSearch() {
  reload(1);
}

async function handleSubmitReport(row: Api.WorkReport.Weekly.WeeklyReport) {
  try {
    await ElMessageBox.confirm('确认提交该报告吗？', '提交确认', {
      type: 'warning',
      confirmButtonText: row.statusCode === 'draft' ? '确认提交' : '确认重新提交',
      cancelButtonText: '取消'
    });
  } catch {
    return;
  }

  const result = await fetchSubmitWeeklyReport(row.id);

  if (result.error) return;
  window.$message?.success('工作报告已提交');
  await reload();
}

async function handleDelete(row: Api.WorkReport.Weekly.WeeklyReport) {
  try {
    await ElMessageBox.confirm(`确认删除 ${formatPeriod(row)} 吗？`, '删除确认', {
      type: 'warning',
      confirmButtonText: '确认',
      cancelButtonText: '取消'
    });
  } catch {
    return;
  }

  const result = await fetchDeleteWeeklyReport(row.id);

  if (result.error) return;

  window.$message?.success('工作报告已删除');
  await reload();
}

function handleSelectionChange(rows: Api.WorkReport.Weekly.WeeklyReport[]) {
  selectedRows.value = rows;
}

function createExportSearchParams() {
  const { pageNo: _pageNo, pageSize: _pageSize, ...params } = searchParams;
  return {
    ...params,
    reporterIds: currentTeamReporterIds.value
  };
}

async function exportReportContent(
  params: Api.WorkReport.Common.ContentExportParams<Api.WorkReport.Weekly.WeeklyReportSearchParams>,
  reportCount: number
) {
  exporting.value = true;
  const result = await fetchExportWeeklyReportContent(params);
  exporting.value = false;

  if (result.error || !result.data) return;

  const fallbackName = createWorkReportContentExportFallbackName('weekly', reportCount);
  downloadBlob(result.data, resolveExportFilename(result, fallbackName));
}

async function handleExportSelected() {
  if (!selectedRows.value.length) {
    window.$message?.warning('请选择要导出的报告');
    return;
  }

  await exportReportContent(
    {
      exportAll: false,
      ids: selectedRows.value.map(item => item.id)
    },
    selectedRows.value.length
  );
}

async function handleExportAll() {
  const total = table.mobilePagination.value.total || 0;
  if (!total) {
    window.$message?.warning('暂无可导出的报告');
    return;
  }

  await exportReportContent(
    {
      ...createExportSearchParams(),
      exportAll: true,
      ids: []
    },
    total
  );
}

async function handleExportCommand(command: 'selected' | 'all') {
  if (command === 'selected') {
    await handleExportSelected();
    return;
  }

  await handleExportAll();
}

async function loadTeamSummary() {
  if (!isTeamRootSelected.value) {
    teamSummaryLoading.value = false;
    teamSummary.value = null;
    return;
  }

  teamSummaryLoading.value = true;
  const { error, data } = await fetchGetTeamReportSummary({
    reportType: 'weekly',
    periodKey: summaryPeriod.value.periodKey
  });
  teamSummaryLoading.value = false;

  teamSummary.value = error || !data ? null : data;
}

defineExpose({ reload });
</script>

<template>
  <div class="flex-col-stretch gap-16px overflow-hidden">
    <WeeklyReportSearch v-model:model="searchParams" @reset="resetSearchParams" @search="handleSearch" />

    <TeamReportSummary
      v-if="isTeamRootSelected"
      report-type="weekly"
      :period-key="summaryPeriod.periodKey"
      :period-label="formatWeeklyPeriodLabel(summaryPeriod)"
      :loading="teamSummaryLoading"
      :summary="teamSummary"
      @reminded="loadTeamSummary"
    />

    <ElCard class="flex-1-hidden card-wrapper" body-class="business-table-card-body">
      <template #header>
        <div class="flex flex-wrap items-center justify-between gap-12px">
          <div class="flex items-center gap-10px">
            <p class="text-16px font-600">{{ reportTitle }}</p>
            <ElTag effect="plain">{{ table.mobilePagination.value.total || 0 }}</ElTag>
          </div>

          <TableHeaderOperation
            v-model:columns="table.columnChecks.value"
            :loading="table.loading.value"
            @refresh="reload()"
          >
            <template #default>
              <ElDropdown v-auth="'project:work-report:export'" trigger="click" @command="handleExportCommand">
                <ElButton plain :loading="exporting">
                  <template #icon>
                    <icon-mdi-download class="text-icon" />
                  </template>
                  导出
                </ElButton>
                <template #dropdown>
                  <ElDropdownMenu>
                    <ElDropdownItem command="selected" :disabled="exporting || !selectedRows.length">
                      导出选中
                    </ElDropdownItem>
                    <ElDropdownItem command="all" :disabled="exporting">导出全部</ElDropdownItem>
                  </ElDropdownMenu>
                </template>
              </ElDropdown>
              <ElButton
                v-if="!isTeamMode"
                v-auth="'project:work-report:create'"
                plain
                type="primary"
                @click="emit('create')"
              >
                <template #icon>
                  <icon-ic-round-plus class="text-icon" />
                </template>
                新增
              </ElButton>
            </template>
          </TableHeaderOperation>
        </div>
      </template>

      <div class="flex-1">
        <ElTable
          v-loading="table.loading.value"
          height="100%"
          border
          row-key="id"
          :data="table.data.value"
          @selection-change="handleSelectionChange"
        >
          <ElTableColumn type="selection" width="48" />
          <template v-for="col in table.columns.value" :key="String(col.prop)">
            <ElTableColumn v-bind="col" />
          </template>
        </ElTable>
      </div>

      <div class="mt-20px flex justify-end">
        <ElPagination
          v-if="table.mobilePagination.value.total"
          layout="total,prev,pager,next,sizes"
          v-bind="table.mobilePagination.value"
          @current-change="table.mobilePagination.value['current-change']"
          @size-change="table.mobilePagination.value['size-change']"
        />
      </div>
    </ElCard>
  </div>
</template>
