import type { Ref } from 'vue';

import type {
  MarketingSeckillActivityType,
  MarketingSeckillChannel,
} from '#/api/marketing';
import type { StoreListItemDto } from '#/api/store';
import type {
  SeckillEditorForm,
  SeckillEditorProductForm,
} from '#/views/marketing/seckill/types';

/**
 * 文件职责：秒杀活动主编辑抽屉动作。
 */
import { ref } from 'vue';

import { message } from 'ant-design-vue';

import {
  getMarketingSeckillDetailApi,
  saveMarketingSeckillApi,
} from '#/api/marketing';

import {
  createDefaultSeckillEditorForm,
  createDefaultSeckillSessionForm,
} from './constants';
import {
  buildSaveSeckillPayload,
  cloneProductForm,
  cloneSessionForm,
  mapDetailToEditorForm,
} from './helpers';

interface CreateDrawerActionsOptions {
  form: SeckillEditorForm;
  isDrawerLoading: Ref<boolean>;
  isDrawerOpen: Ref<boolean>;
  isDrawerSubmitting: Ref<boolean>;
  loadActivities: () => Promise<void>;
  openPicker: (
    pickerOptions: {
      selectedProductIds: string[];
      selectedProducts: SeckillEditorProductForm[];
      storeId: string;
    },
    onConfirm: (products: SeckillEditorProductForm[]) => void,
  ) => Promise<void>;
  resolveOperationStoreId: (preferredStoreIds?: string[]) => string;
  selectedStoreId: Ref<string>;
  stores: Ref<StoreListItemDto[]>;
}

export function createDrawerActions(options: CreateDrawerActionsOptions) {
  const drawerMode = ref<'create' | 'edit'>('create');

  function setDrawerOpen(value: boolean) {
    options.isDrawerOpen.value = value;
  }

  function applyForm(next: SeckillEditorForm) {
    options.form.id = next.id;
    options.form.name = next.name;
    options.form.activityType = next.activityType;
    options.form.validDateRange = next.validDateRange;
    options.form.timeRange = next.timeRange;
    options.form.sessions = next.sessions.map((item) => cloneSessionForm(item));
    options.form.channels = [...next.channels];
    options.form.perUserLimit = next.perUserLimit;
    options.form.preheatEnabled = next.preheatEnabled;
    options.form.preheatHours = next.preheatHours;
    options.form.products = next.products.map((item) => cloneProductForm(item));
    options.form.metrics = { ...next.metrics };
    options.form.status = next.status;
    options.form.storeIds = [...next.storeIds];
  }

  function resetForm() {
    applyForm(createDefaultSeckillEditorForm());
  }

  function setFormName(value: string) {
    options.form.name = value;
  }

  function setActivityType(value: MarketingSeckillActivityType) {
    options.form.activityType = value;
    if (value === 'hourly' && options.form.sessions.length === 0) {
      options.form.sessions = [createDefaultSeckillSessionForm()];
    }
  }

  function setFormValidDateRange(value: SeckillEditorForm['validDateRange']) {
    options.form.validDateRange = value;
  }

  function setFormTimeRange(value: SeckillEditorForm['timeRange']) {
    options.form.timeRange = value;
  }

  function addSession() {
    options.form.sessions = [
      ...options.form.sessions,
      createDefaultSeckillSessionForm(),
    ];
  }

  function removeSession(index: number) {
    options.form.sessions = options.form.sessions.filter(
      (_, rowIndex) => rowIndex !== index,
    );
  }

  function setSessionStartTime(index: number, value: string) {
    const row = options.form.sessions[index];
    if (!row) {
      return;
    }
    row.startTime = value;
    options.form.sessions = [...options.form.sessions];
  }

  function setSessionDuration(index: number, value: null | number) {
    const row = options.form.sessions[index];
    if (!row) {
      return;
    }
    row.durationMinutes = normalizeNullableInteger(value);
    options.form.sessions = [...options.form.sessions];
  }

  function setFormChannels(value: MarketingSeckillChannel[]) {
    options.form.channels = [...new Set(value)];
  }

  function toggleChannel(channel: MarketingSeckillChannel) {
    if (options.form.channels.includes(channel)) {
      setFormChannels(options.form.channels.filter((item) => item !== channel));
      return;
    }
    setFormChannels([...options.form.channels, channel]);
  }

  function setFormPerUserLimit(value: null | number) {
    options.form.perUserLimit = normalizeNullableInteger(value);
  }

  function setPreheatEnabled(value: boolean) {
    options.form.preheatEnabled = value;
    if (!value) {
      options.form.preheatHours = null;
      return;
    }

    if (!options.form.preheatHours || options.form.preheatHours <= 0) {
      options.form.preheatHours = 1;
    }
  }

  function setPreheatHours(value: null | number) {
    options.form.preheatHours = normalizeNullableInteger(value);
  }

  function setProductSeckillPrice(index: number, value: null | number) {
    const row = options.form.products[index];
    if (!row) {
      return;
    }
    row.seckillPrice = normalizeNullableNumber(value);
    options.form.products = [...options.form.products];
  }

  function setProductStockLimit(index: number, value: null | number) {
    const row = options.form.products[index];
    if (!row) {
      return;
    }
    row.stockLimit = normalizeNullableInteger(value);
    options.form.products = [...options.form.products];
  }

  function setProductPerUserLimit(index: number, value: null | number) {
    const row = options.form.products[index];
    if (!row) {
      return;
    }
    row.perUserLimit = normalizeNullableInteger(value);
    options.form.products = [...options.form.products];
  }

  function removeProduct(index: number) {
    options.form.products = options.form.products.filter(
      (_, rowIndex) => rowIndex !== index,
    );
  }

  async function openProductPicker() {
    const operationStoreId = resolveScopeStoreId();
    if (!operationStoreId) {
      message.warning('请选择具体门店后再添加商品');
      return;
    }

    await options.openPicker(
      {
        storeId: operationStoreId,
        selectedProducts: options.form.products.map((item) =>
          cloneProductForm(item),
        ),
        selectedProductIds: options.form.products.map((item) => item.productId),
      },
      (products) => {
        const currentById = new Map(
          options.form.products.map((item) => [item.productId, item]),
        );
        const merged = products.map((item) => {
          const existing = currentById.get(item.productId);
          return existing ? cloneProductForm(existing) : cloneProductForm(item);
        });
        options.form.products = merged;
      },
    );
  }

  async function openCreateDrawer() {
    if (!options.selectedStoreId.value) {
      message.warning('请选择具体门店后再创建活动');
      return;
    }

    resetForm();
    options.form.storeIds = [options.selectedStoreId.value];
    drawerMode.value = 'create';
    options.isDrawerOpen.value = true;
  }

  async function openEditDrawer(
    activityId: string,
    preferredStoreIds: string[] = [],
  ) {
    const operationStoreId = options.resolveOperationStoreId(preferredStoreIds);
    if (!operationStoreId) {
      return;
    }

    options.isDrawerLoading.value = true;
    try {
      const detail = await getMarketingSeckillDetailApi({
        storeId: operationStoreId,
        activityId,
      });
      const mapped = mapDetailToEditorForm(detail);
      if (mapped.storeIds.length === 0) {
        mapped.storeIds = [operationStoreId];
      }
      applyForm(mapped);
      drawerMode.value = 'edit';
      options.isDrawerOpen.value = true;
    } catch (error) {
      console.error(error);
      message.error('加载活动详情失败');
    } finally {
      options.isDrawerLoading.value = false;
    }
  }

  async function submitDrawer() {
    const operationStoreId = options.resolveOperationStoreId(
      options.form.storeIds,
    );
    if (!operationStoreId) {
      message.warning('请选择可操作门店');
      return;
    }

    if (!validateBeforeSubmit(operationStoreId)) {
      return;
    }

    options.isDrawerSubmitting.value = true;
    try {
      await saveMarketingSeckillApi(
        buildSaveSeckillPayload(options.form, operationStoreId),
      );
      message.success(
        drawerMode.value === 'create' ? '活动已创建' : '活动已更新',
      );
      options.isDrawerOpen.value = false;
      await options.loadActivities();
    } catch (error) {
      console.error(error);
    } finally {
      options.isDrawerSubmitting.value = false;
    }
  }

  function validateBeforeSubmit(operationStoreId: string) {
    const normalizedName = options.form.name.trim();
    if (!normalizedName) {
      message.warning('请输入活动名称');
      return false;
    }
    if (normalizedName.length > 64) {
      message.warning('活动名称长度不能超过 64 个字符');
      return false;
    }

    if (options.form.storeIds.length === 0) {
      message.warning('活动门店不能为空');
      return false;
    }
    if (!options.form.storeIds.includes(operationStoreId)) {
      message.warning('活动门店必须包含当前操作门店');
      return false;
    }

    if (
      options.form.activityType === 'timed' &&
      (!options.form.validDateRange || !options.form.timeRange)
    ) {
      message.warning('请完整设置活动时间');
      return false;
    }

    if (options.form.activityType === 'hourly') {
      if (options.form.sessions.length === 0) {
        message.warning('请至少配置一个场次');
        return false;
      }

      const sessionTimeSet = new Set<string>();
      for (const session of options.form.sessions) {
        if (!isTimeText(session.startTime)) {
          message.warning('场次时间格式必须为 HH:mm');
          return false;
        }

        if (!session.durationMinutes || session.durationMinutes <= 0) {
          message.warning('场次持续时长必须大于 0');
          return false;
        }

        if (sessionTimeSet.has(session.startTime)) {
          message.warning('场次时间不能重复');
          return false;
        }
        sessionTimeSet.add(session.startTime);
      }
    }

    if (options.form.channels.length === 0) {
      message.warning('请至少选择一个适用渠道');
      return false;
    }

    if (options.form.perUserLimit !== null && options.form.perUserLimit <= 0) {
      message.warning('每人限购必须大于 0');
      return false;
    }

    if (
      options.form.preheatEnabled &&
      (!options.form.preheatHours || options.form.preheatHours <= 0)
    ) {
      message.warning('预热小时数必须大于 0');
      return false;
    }

    if (options.form.products.length === 0) {
      message.warning('请至少添加一个秒杀商品');
      return false;
    }

    for (const row of options.form.products) {
      if (!row.productId) {
        message.warning('商品数据异常，请重新选择商品');
        return false;
      }
      if (!row.seckillPrice || row.seckillPrice <= 0) {
        message.warning(`商品「${row.name}」秒杀价必须大于 0`);
        return false;
      }
      if (row.seckillPrice > row.originalPrice) {
        message.warning(`商品「${row.name}」秒杀价不能高于原价`);
        return false;
      }
      if (!row.stockLimit || row.stockLimit <= 0) {
        message.warning(`商品「${row.name}」限量必须大于 0`);
        return false;
      }
      if (row.stockLimit < row.soldCount) {
        message.warning(`商品「${row.name}」限量不能小于已抢数量`);
        return false;
      }
      if (row.perUserLimit !== null && row.perUserLimit <= 0) {
        message.warning(`商品「${row.name}」限购必须大于 0`);
        return false;
      }
      if (
        options.form.perUserLimit &&
        row.perUserLimit &&
        row.perUserLimit > options.form.perUserLimit
      ) {
        message.warning(`商品「${row.name}」限购不能大于活动每人限购`);
        return false;
      }
    }

    return true;
  }

  function resolveScopeStoreId() {
    if (options.selectedStoreId.value) {
      return options.selectedStoreId.value;
    }

    if (options.form.storeIds.length > 0) {
      return options.form.storeIds[0] ?? '';
    }

    return options.stores.value[0]?.id ?? '';
  }

  return {
    addSession,
    drawerMode,
    openCreateDrawer,
    openEditDrawer,
    openProductPicker,
    removeProduct,
    removeSession,
    setActivityType,
    setDrawerOpen,
    setFormChannels,
    setFormName,
    setFormPerUserLimit,
    setFormTimeRange,
    setFormValidDateRange,
    setPreheatEnabled,
    setPreheatHours,
    setProductPerUserLimit,
    setProductSeckillPrice,
    setProductStockLimit,
    setSessionDuration,
    setSessionStartTime,
    submitDrawer,
    toggleChannel,
  };
}

function isTimeText(value: string) {
  return /^(?:[01]\d|2[0-3]):[0-5]\d$/.test((value || '').trim());
}

function normalizeNullableNumber(value: null | number) {
  if (value === null || value === undefined) {
    return null;
  }
  const numeric = Number(value);
  if (Number.isNaN(numeric)) {
    return null;
  }
  return Number(numeric.toFixed(2));
}

function normalizeNullableInteger(value: null | number) {
  if (value === null || value === undefined) {
    return null;
  }
  const numeric = Number(value);
  if (Number.isNaN(numeric)) {
    return null;
  }
  return Math.floor(numeric);
}
