<script setup lang="ts">
import { type ComputedRef, type Ref, computed, nextTick, onMounted, ref, watch } from 'vue';
import { onBeforeRouteLeave } from 'vue-router';
import { fetchGetMySubordinateTree, fetchGetProjectReportOwnerProjectOptions } from '@/service/api';
import { useAuth } from '@/hooks/business/auth';
import SubordinateSelector from '@/components/custom/subordinate-selector.vue';
import TeamContextPanel from '@/components/custom/team-context-panel.vue';
import {
  type TeamViewContext,
  type TeamViewMode,
  collectSubordinateUserIds,
  findSubordinateNode
} from '../shared/team-dashboard';
import TeamReportSummary from './shared/components/team-report-summary.vue';
import WorkReportCreateDialog from './shared/components/create-dialog.vue';
import WorkReportPrototypePageDialog from './shared/components/prototype-page-dialog.vue';
import WorkReportTabs from './shared/components/tabs.vue';
import {
  WORK_REPORT_PROJECT_OWNER_PERMISSION,
  type WorkReportRow,
  type WorkReportType,
  getWorkReportTypeDisplayLabel
} from './shared/types';
import { formatIsoWeekRangeLabel } from './shared/utils';
import type { resolveWorkReportSummaryPeriod } from './shared/utils';
import WeeklyReportIndex from './weekly/index.vue';
import WeeklyReportApprovalRecordDialog from './weekly/modules/approval-record-dialog.vue';
import MonthlyReportIndex from './monthly/index.vue';
import MonthlyReportApprovalRecordDialog from './monthly/modules/approval-record-dialog.vue';
import ProjectReportIndex from './project/index.vue';
import ProjectReportApprovalRecordDialog from './project/modules/approval-record-dialog.vue';

defineOptions({ name: 'PersonalCenterWorkReport' });

type PageDialogMode = 'add' | 'edit' | 'detail';
type ReportListExpose = {
  reload: (page?: number) => Promise<void>;
  teamSummary: Ref<Api.WorkReport.Common.TeamReportSummary | null>;
  teamSummaryLoading: Ref<boolean>;
  summaryPeriod: Ref<ReturnType<typeof resolveWorkReportSummaryPeriod>>;
  summaryPeriodKeys: ComputedRef<string[]>;
  hasSearchedDateRange: ComputedRef<boolean>;
  loadTeamSummary: () => Promise<void>;
};

const { hasAuth } = useAuth();

const activeTab = ref<WorkReportType>('weekly');
const teamViewMode = ref<TeamViewMode>('self');
const subordinateTreeLoading = ref(false);
const subordinateTree = ref<Api.SystemManage.MySubordinateTreeNode | null>(null);
const selectedSubordinateUserId = ref<string | null>(null);
const createVisible = ref(false);
const pageDialogVisible = ref(false);
const pageDialogMode = ref<PageDialogMode>('detail');
const approvalRecordVisible = ref(false);
const currentReportType = ref<WorkReportType>('weekly');
const currentRow = ref<WorkReportRow | null>(null);
const initialPeriod = ref<{
  periodKey: string;
  periodLabel: string;
  periodStartDate: string;
  periodEndDate: string;
} | null>(null);
const initialProjectId = ref('');
const initialFlag = ref(1);
const projectOptions = ref<Api.WorkReport.Project.ProjectReportOwnerProjectOption[]>([]);

const weeklyRef = ref<ReportListExpose | null>(null);
const monthlyRef = ref<ReportListExpose | null>(null);
const projectRef = ref<ReportListExpose | null>(null);

const canShowProjectTab = computed(() => hasAuth(WORK_REPORT_PROJECT_OWNER_PERMISSION));
const canUseTeamDashboard = computed(() => hasAuth('project:work-report:team-dashboard'));
const allSubordinateUserIds = computed(() => collectSubordinateUserIds(subordinateTree.value));
const selectedSubordinateNode = computed(() =>
  findSubordinateNode(subordinateTree.value, selectedSubordinateUserId.value)
);
const subordinateOptions = computed(() => {
  const options: Array<{ label: string; value: string }> = [];

  const walk = (nodes?: Api.SystemManage.MySubordinateTreeNode[] | null) => {
    nodes?.forEach(node => {
      options.push({ label: node.userNickname, value: node.userId });
      walk(node.children ?? null);
    });
  };

  walk(subordinateTree.value?.children ?? null);
  return options;
});
const isRootSelected = computed(() => Boolean(selectedSubordinateNode.value?.isRoot));
const selectedTeamLabel = computed(() => {
  if (teamViewMode.value === 'self') return '我自己';
  if (!selectedSubordinateNode.value) return '--';
  return selectedSubordinateNode.value.isRoot ? '全部下属' : selectedSubordinateNode.value.userNickname;
});
const teamContext = computed<TeamViewContext | null>(() => {
  if (!canUseTeamDashboard.value) return null;

  return {
    mode: teamViewMode.value,
    selectedUserId: selectedSubordinateUserId.value,
    selectedUserIds:
      teamViewMode.value === 'team' && selectedSubordinateUserId.value && !isRootSelected.value
        ? [selectedSubordinateUserId.value]
        : [],
    isRootSelected: teamViewMode.value === 'team' && isRootSelected.value,
    allSubordinateUserIds: allSubordinateUserIds.value,
    selectedLabel: selectedTeamLabel.value
  };
});

/** 项目选项是否加载成功（用于项目半月报列表内部判断） */
const projectOptionsLoaded = ref(false);

const visibleTabs = computed<Array<{ label: string; name: WorkReportType }>>(() => {
  const isTeamReportMode = teamViewMode.value === 'team';
  const tabs: Array<{ label: string; name: WorkReportType }> = [
    { label: getWorkReportTypeDisplayLabel('weekly', isTeamReportMode), name: 'weekly' },
    { label: getWorkReportTypeDisplayLabel('monthly', isTeamReportMode), name: 'monthly' }
  ];

  if (canShowProjectTab.value) {
    tabs.push({ label: getWorkReportTypeDisplayLabel('project', isTeamReportMode), name: 'project' });
  }

  return tabs;
});

const currentApprovalRecordDialogComponent = computed(() => {
  if (currentReportType.value === 'monthly') return MonthlyReportApprovalRecordDialog;
  if (currentReportType.value === 'project') return ProjectReportApprovalRecordDialog;
  return WeeklyReportApprovalRecordDialog;
});

function getListRef(reportType: WorkReportType) {
  if (reportType === 'monthly') return monthlyRef.value;
  if (reportType === 'project') return projectRef.value;
  return weeklyRef.value;
}

const activeReportRef = computed(() => getListRef(activeTab.value));
const activeTeamSummary = computed(() => activeReportRef.value?.teamSummary ?? null);
const activeTeamSummaryLoading = computed(() => activeReportRef.value?.teamSummaryLoading ?? false);
const activeSummaryPeriodKeys = computed(() => {
  const activeRef = activeReportRef.value;
  if (!activeRef) return [];
  return activeRef.summaryPeriodKeys ?? [];
});
const activeSummaryReportType = computed<Api.WorkReport.Common.ReportType>(() => {
  if (activeTab.value === 'monthly') return 'monthly';
  if (activeTab.value === 'project') return 'project';
  return 'weekly';
});
const activeSummaryPeriodLabel = computed(() => {
  const summaryPeriod = activeReportRef.value?.summaryPeriod;
  if (!summaryPeriod) return '';

  if (activeTab.value === 'weekly') {
    return formatIsoWeekRangeLabel(summaryPeriod.periodStartDate, summaryPeriod.periodEndDate);
  }

  return summaryPeriod.periodLabel ?? '';
});

async function loadProjectOptions() {
  if (!canShowProjectTab.value) return;

  const { error, data } = await fetchGetProjectReportOwnerProjectOptions();
  projectOptions.value = error || !data ? [] : data;
  projectOptionsLoaded.value = !error;
}

async function loadSubordinateTree() {
  if (!canUseTeamDashboard.value) return;

  subordinateTreeLoading.value = true;
  const { error, data } = await fetchGetMySubordinateTree();
  subordinateTreeLoading.value = false;

  subordinateTree.value = error || !data ? null : data;
  selectedSubordinateUserId.value = data?.userId || null;
}

function openCreate(reportType: WorkReportType) {
  currentReportType.value = reportType;
  createVisible.value = true;
}

function handleCreateConfirm(
  payload:
    | { reportType: 'weekly' | 'monthly'; period: typeof initialPeriod.value extends infer T ? T : never }
    | {
        reportType: 'project';
        projectId: string;
        flag: number;
        period: typeof initialPeriod.value extends infer T ? T : never;
      }
) {
  currentReportType.value = payload.reportType;
  pageDialogMode.value = 'add';
  currentRow.value = null;
  initialPeriod.value = payload.period as typeof initialPeriod.value;
  initialProjectId.value = 'projectId' in payload ? payload.projectId : '';
  initialFlag.value = 'flag' in payload ? payload.flag : 1;
  pageDialogVisible.value = true;
}

function openEdit(reportType: WorkReportType, row: WorkReportRow) {
  currentReportType.value = reportType;
  pageDialogMode.value = 'edit';
  currentRow.value = row;
  initialPeriod.value = null;
  pageDialogVisible.value = true;
}

function openDetail(reportType: WorkReportType, row: WorkReportRow) {
  currentReportType.value = reportType;
  pageDialogMode.value = 'detail';
  currentRow.value = row;
  initialPeriod.value = null;
  pageDialogVisible.value = true;
}

function openApprovalRecord(reportType: WorkReportType, row: WorkReportRow) {
  currentReportType.value = reportType;
  currentRow.value = row;
  approvalRecordVisible.value = true;
}

async function handleTabChange(tab: WorkReportType) {
  activeTab.value = tab;
  await nextTick();
  await getListRef(tab)?.reload(1);
}

async function reloadReport(reportType = currentReportType.value) {
  await getListRef(reportType)?.reload();
}

function handleSubmitted() {
  pageDialogVisible.value = false;
  reloadReport(currentReportType.value);
}

async function handleSummaryRemind() {
  await activeReportRef.value?.loadTeamSummary();
}

function closeFloatingPanels() {
  createVisible.value = false;
  pageDialogVisible.value = false;
  approvalRecordVisible.value = false;
}

async function handleTeamViewModeChange(mode: TeamViewMode) {
  teamViewMode.value = mode;

  if (mode === 'team') {
    if (!subordinateTree.value) {
      await loadSubordinateTree();
    }
    if (!selectedSubordinateUserId.value) {
      selectedSubordinateUserId.value = subordinateTree.value?.userId || null;
    }
  }

  await nextTick();
  await getListRef(activeTab.value)?.reload(1);
}

watch(selectedSubordinateUserId, async (currentUserId, previousUserId) => {
  if (!canUseTeamDashboard.value || teamViewMode.value !== 'team') return;
  if (!currentUserId || currentUserId === previousUserId) return;

  await nextTick();
  await getListRef(activeTab.value)?.reload(1);
});

onMounted(async () => {
  await loadProjectOptions();
  if (canUseTeamDashboard.value) {
    await loadSubordinateTree();
  }
});

onBeforeRouteLeave(() => {
  closeFloatingPanels();
});
</script>

<template>
  <div
    class="work-report-page-shell min-h-560px gap-16px overflow-hidden xl:grid xl:grid-cols-[240px_minmax(0,1fr)] lt-xl:flex lt-xl:flex-col lt-xl:overflow-auto"
  >
    <!-- 左侧：报告类型导航 -->
    <div
      class="work-report-page-shell__sidebar"
      :class="{ 'work-report-page-shell__sidebar--team': canUseTeamDashboard && teamViewMode === 'team' }"
    >
      <WorkReportTabs
        class="work-report-page-shell__sidebar-card"
        :active-tab="activeTab"
        :tabs="visibleTabs"
        @update:active-tab="handleTabChange"
      />
      <SubordinateSelector
        v-if="canUseTeamDashboard && teamViewMode === 'team'"
        v-model:selected-user-id="selectedSubordinateUserId"
        class="work-report-page-shell__sidebar-card"
        :loading="subordinateTreeLoading"
        :data="subordinateTree"
      />
    </div>

    <!-- 右侧：搜索区 + 列表区 -->
    <div class="flex-col-stretch gap-16px xl:min-h-0">
      <TeamContextPanel
        v-if="canUseTeamDashboard"
        v-model:mode="teamViewMode"
        :loading="subordinateTreeLoading"
        :selected-label="selectedTeamLabel"
        :subordinate-count="subordinateTree?.subordinateCount || 0"
        @update:mode="handleTeamViewModeChange"
      >
        <TeamReportSummary
          v-if="isRootSelected && teamViewMode === 'team'"
          :report-type="activeSummaryReportType"
          :period-keys="activeSummaryPeriodKeys"
          :period-label="activeSummaryPeriodLabel"
          :loading="activeTeamSummaryLoading"
          :summary="activeTeamSummary"
          @reminded="handleSummaryRemind"
        />
      </TeamContextPanel>

      <WeeklyReportIndex
        v-show="activeTab === 'weekly'"
        ref="weeklyRef"
        class="flex-1-hidden"
        :team-context="teamContext"
        :subordinate-options="subordinateOptions"
        @create="openCreate('weekly')"
        @edit="openEdit('weekly', $event)"
        @detail="openDetail('weekly', $event)"
        @approval-record="openApprovalRecord('weekly', $event)"
      />

      <MonthlyReportIndex
        v-show="activeTab === 'monthly'"
        ref="monthlyRef"
        class="flex-1-hidden"
        :team-context="teamContext"
        :subordinate-options="subordinateOptions"
        @create="openCreate('monthly')"
        @edit="openEdit('monthly', $event)"
        @detail="openDetail('monthly', $event)"
        @approval-record="openApprovalRecord('monthly', $event)"
      />

      <ProjectReportIndex
        v-if="canShowProjectTab"
        v-show="activeTab === 'project'"
        ref="projectRef"
        class="flex-1-hidden"
        :team-context="teamContext"
        :project-options="projectOptions"
        :project-options-loaded="projectOptionsLoaded"
        @create="openCreate('project')"
        @edit="openEdit('project', $event)"
        @detail="openDetail('project', $event)"
        @approval-record="openApprovalRecord('project', $event)"
      />
    </div>
    <WorkReportCreateDialog
      v-model:visible="createVisible"
      :default-report-type="currentReportType"
      :project-visible="canShowProjectTab"
      :project-options="projectOptions"
      @confirm="handleCreateConfirm"
    />

    <WorkReportPrototypePageDialog
      v-model:visible="pageDialogVisible"
      :mode="pageDialogMode"
      scene="fill"
      :report-type="currentReportType"
      :row-data="currentRow"
      :initial-period="initialPeriod"
      :initial-project-id="initialProjectId"
      :initial-flag="initialFlag"
      @submitted="handleSubmitted"
    />

    <component
      :is="currentApprovalRecordDialogComponent"
      v-model:visible="approvalRecordVisible"
      :row-data="currentRow"
    />
  </div>
</template>

<style scoped>
.work-report-page-shell {
  height: 100%;
}

.work-report-page-shell__sidebar {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

@media (min-width: 1280px) {
  .work-report-page-shell__sidebar {
    min-height: 0;
  }

  .work-report-page-shell__sidebar--team {
    display: grid;
    grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
  }

  .work-report-page-shell__sidebar-card {
    min-height: 0;
  }
}
</style>
