import type { Ref } from 'vue';

/**
 * 文件职责：员工排班数据动作。
 * 1. 加载门店列表、员工列表、班次模板与排班数据。
 * 2. 维护页面级数据快照。
 */
import type { StoreListItemDto } from '#/api/store';
import type {
  StaffDayShiftDto,
  StoreShiftTemplatesDto,
  StoreStaffDto,
} from '#/api/store-staff';
import type {
  StaffFilterState,
  StaffScheduleSnapshot,
} from '#/views/store/staff/types';

import { getStoreListApi } from '#/api/store';
import {
  getStoreStaffListApi,
  getStoreStaffScheduleApi,
} from '#/api/store-staff';

import { EMPTY_SHIFT_TEMPLATES } from './constants';
import {
  cloneScheduleMap,
  cloneShifts,
  cloneTemplates,
  normalizeSparseWeekShifts,
} from './helpers';

interface CreateDataActionsOptions {
  filters: StaffFilterState;
  isScheduleConfigured: Ref<boolean>;
  isTemplateConfigured: Ref<boolean>;
  isPageLoading: Ref<boolean>;
  isStoreLoading: Ref<boolean>;
  scheduleMap: Ref<Record<string, StaffDayShiftDto[]>>;
  scheduleSnapshot: Ref<null | StaffScheduleSnapshot>;
  selectedStoreId: Ref<string>;
  staffDirectory: Ref<StoreStaffDto[]>;
  staffRows: Ref<StoreStaffDto[]>;
  staffTotal: Ref<number>;
  stores: Ref<StoreListItemDto[]>;
  templates: Ref<StoreShiftTemplatesDto>;
}

export function createDataActions(options: CreateDataActionsOptions) {
  /** 判断当前排班映射是否包含任意配置。 */
  function hasAnyConfiguredShift(
    scheduleMap: Record<string, StaffDayShiftDto[]>,
  ) {
    return Object.values(scheduleMap).some((shifts) => shifts.length > 0);
  }

  /** 清空当前门店相关数据。 */
  function clearStoreData() {
    options.staffRows.value = [];
    options.staffDirectory.value = [];
    options.staffTotal.value = 0;
    options.templates.value = cloneTemplates(EMPTY_SHIFT_TEMPLATES);
    options.isTemplateConfigured.value = false;
    options.isScheduleConfigured.value = false;
    options.scheduleMap.value = {};
    options.scheduleSnapshot.value = null;
  }

  /** 加载员工分页列表（受筛选条件影响）。 */
  async function loadStaffPage() {
    if (!options.selectedStoreId.value) {
      options.staffRows.value = [];
      options.staffTotal.value = 0;
      return;
    }

    const result = await getStoreStaffListApi({
      storeId: options.selectedStoreId.value,
      keyword: options.filters.keyword || undefined,
      roleType: options.filters.roleType || undefined,
      status: options.filters.status || undefined,
      page: options.filters.page,
      pageSize: options.filters.pageSize,
    });

    options.staffRows.value = result.items ?? [];
    options.staffTotal.value = result.total ?? 0;
  }

  /** 加载员工全量字典（用于周排班看板）。 */
  async function loadStaffDirectory() {
    if (!options.selectedStoreId.value) {
      options.staffDirectory.value = [];
      return;
    }

    const result = await getStoreStaffListApi({
      storeId: options.selectedStoreId.value,
      page: 1,
      pageSize: 200,
      keyword: undefined,
      roleType: undefined,
      status: undefined,
    });

    options.staffDirectory.value = result.items ?? [];
  }

  /** 加载班次模板与排班配置。 */
  async function loadScheduleSettings() {
    if (!options.selectedStoreId.value) {
      options.templates.value = cloneTemplates(EMPTY_SHIFT_TEMPLATES);
      options.isTemplateConfigured.value = false;
      options.isScheduleConfigured.value = false;
      options.scheduleMap.value = {};
      options.scheduleSnapshot.value = null;
      return;
    }

    const result = await getStoreStaffScheduleApi(
      options.selectedStoreId.value,
    );
    const templates = cloneTemplates(result.templates ?? EMPTY_SHIFT_TEMPLATES);

    const scheduleMap: Record<string, StaffDayShiftDto[]> = {};
    for (const schedule of result.schedules ?? []) {
      scheduleMap[schedule.staffId] = normalizeSparseWeekShifts({
        shifts: schedule.shifts,
        templates,
      });
    }

    options.templates.value = templates;
    options.isTemplateConfigured.value = Boolean(result.isTemplateConfigured);
    options.isScheduleConfigured.value = Boolean(result.isScheduleConfigured);
    options.scheduleMap.value = scheduleMap;
    options.scheduleSnapshot.value = {
      templates: cloneTemplates(templates),
      scheduleMap: cloneScheduleMap(scheduleMap),
    };
  }

  /** 一次性刷新当前门店全部数据。 */
  async function reloadStoreData() {
    if (!options.selectedStoreId.value) {
      clearStoreData();
      return;
    }

    options.isPageLoading.value = true;
    try {
      await Promise.all([
        loadStaffPage(),
        loadStaffDirectory(),
        loadScheduleSettings(),
      ]);
    } catch (error) {
      console.error(error);
    } finally {
      options.isPageLoading.value = false;
    }
  }

  /** 加载门店列表并初始化默认门店。 */
  async function loadStores() {
    options.isStoreLoading.value = true;
    try {
      const result = await getStoreListApi({
        keyword: undefined,
        businessStatus: undefined,
        auditStatus: undefined,
        serviceType: undefined,
        page: 1,
        pageSize: 200,
      });

      options.stores.value = result.items ?? [];

      if (options.stores.value.length === 0) {
        options.selectedStoreId.value = '';
        clearStoreData();
        return;
      }

      const hasSelected = options.stores.value.some(
        (item) => item.id === options.selectedStoreId.value,
      );
      if (!hasSelected) {
        const firstStore = options.stores.value[0];
        if (firstStore) {
          options.selectedStoreId.value = firstStore.id;
          return;
        }
      }

      await reloadStoreData();
    } catch (error) {
      console.error(error);
      options.stores.value = [];
      options.selectedStoreId.value = '';
      clearStoreData();
    } finally {
      options.isStoreLoading.value = false;
    }
  }

  /** 局部更新单员工排班映射。 */
  function patchStaffSchedule(staffId: string, shifts: StaffDayShiftDto[]) {
    const nextMap = {
      ...options.scheduleMap.value,
      [staffId]: cloneShifts(shifts),
    };
    options.scheduleMap.value = nextMap;
    options.isScheduleConfigured.value = hasAnyConfiguredShift(nextMap);
    options.scheduleSnapshot.value = {
      templates: cloneTemplates(options.templates.value),
      scheduleMap: cloneScheduleMap(nextMap),
    };
  }

  /** 批量更新排班映射。 */
  function patchScheduleMap(nextMap: Record<string, StaffDayShiftDto[]>) {
    options.scheduleMap.value = cloneScheduleMap(nextMap);
    options.isScheduleConfigured.value = hasAnyConfiguredShift(nextMap);
    options.scheduleSnapshot.value = {
      templates: cloneTemplates(options.templates.value),
      scheduleMap: cloneScheduleMap(nextMap),
    };
  }

  /** 更新模板并同步快照。 */
  function patchTemplates(nextTemplates: StoreShiftTemplatesDto) {
    options.templates.value = cloneTemplates(nextTemplates);
    options.scheduleSnapshot.value = {
      templates: cloneTemplates(nextTemplates),
      scheduleMap: cloneScheduleMap(options.scheduleMap.value),
    };
  }

  return {
    clearStoreData,
    loadScheduleSettings,
    loadStaffDirectory,
    loadStaffPage,
    loadStores,
    patchScheduleMap,
    patchStaffSchedule,
    patchTemplates,
    reloadStoreData,
  };
}
