import type { Ref } from 'vue';

import type {
  MarketingFullReductionActivityType,
  MarketingFullReductionChannel,
  MarketingFullReductionGiftScopeType,
  MarketingFullReductionSecondHalfDiscountType,
  MarketingFullReductionStoreScopeMode,
} from '#/api/marketing';
import type { StoreListItemDto } from '#/api/store';
import type {
  FullReductionEditorForm,
  FullReductionPickerTarget,
  FullReductionScopeForm,
} from '#/views/marketing/full-reduction/types';

/**
 * 文件职责：满减活动编辑抽屉动作。
 * 1. 管理新增/编辑抽屉与字段更新。
 * 2. 负责详情加载、范围选择回填、表单校验与保存提交。
 */
import { ref } from 'vue';

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

import {
  getMarketingFullReductionDetailApi,
  saveMarketingFullReductionApi,
} from '#/api/marketing';

import {
  createDefaultFullReductionEditorForm,
  createDefaultScopeForm,
  createDefaultTierForm,
} from './constants';
import {
  buildSaveFullReductionPayload,
  cloneScopeForm,
  mapDetailToEditorForm,
} from './helpers';

interface CreateDrawerActionsOptions {
  form: FullReductionEditorForm;
  isDrawerLoading: Ref<boolean>;
  isDrawerOpen: Ref<boolean>;
  isDrawerSubmitting: Ref<boolean>;
  loadActivities: () => Promise<void>;
  openPicker: (
    params: {
      allowAll: boolean;
      initialScope: FullReductionScopeForm;
      scopeStoreId: string;
      target: FullReductionPickerTarget;
      title: string;
    },
    onConfirm: (scope: FullReductionScopeForm) => 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: FullReductionEditorForm) {
    options.form.id = next.id;
    options.form.name = next.name;
    options.form.activityType = next.activityType;
    options.form.reduceTiers = next.reduceTiers.map((item) => ({
      meetAmount: item.meetAmount,
      reduceAmount: item.reduceAmount,
    }));
    options.form.giftRule = {
      buyQuantity: next.giftRule.buyQuantity,
      giftQuantity: next.giftRule.giftQuantity,
      giftScopeType: next.giftRule.giftScopeType,
      applicableScope: cloneScopeForm(next.giftRule.applicableScope),
      giftScope: cloneScopeForm(next.giftRule.giftScope),
    };
    options.form.secondHalfRule = {
      discountType: next.secondHalfRule.discountType,
      applicableScope: cloneScopeForm(next.secondHalfRule.applicableScope),
    };
    options.form.validDateRange = next.validDateRange;
    options.form.channels = [...next.channels];
    options.form.storeScopeMode = next.storeScopeMode;
    options.form.storeIds = [...next.storeIds];
    options.form.scopeStoreId = next.scopeStoreId;
    options.form.stackWithCoupon = next.stackWithCoupon;
    options.form.description = next.description;
    options.form.metrics = { ...next.metrics };
  }

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

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

  function setFormActivityType(value: MarketingFullReductionActivityType) {
    options.form.activityType = value;
  }

  function addReduceTier() {
    options.form.reduceTiers = [
      ...options.form.reduceTiers,
      createDefaultTierForm(),
    ];
  }

  function removeReduceTier(index: number) {
    if (options.form.reduceTiers.length <= 1) {
      return;
    }
    options.form.reduceTiers = options.form.reduceTiers.filter(
      (_, rowIndex) => rowIndex !== index,
    );
  }

  function setReduceTierMeetAmount(index: number, value: null | number) {
    const next = [...options.form.reduceTiers];
    const row = next[index];
    if (!row) return;

    row.meetAmount = normalizeNullableNumber(value);
    options.form.reduceTiers = next;
  }

  function setReduceTierReduceAmount(index: number, value: null | number) {
    const next = [...options.form.reduceTiers];
    const row = next[index];
    if (!row) return;

    row.reduceAmount = normalizeNullableNumber(value);
    options.form.reduceTiers = next;
  }

  function setGiftBuyQuantity(value: null | number) {
    options.form.giftRule.buyQuantity = normalizeNullableInteger(value);
  }

  function setGiftGiftQuantity(value: null | number) {
    options.form.giftRule.giftQuantity = normalizeNullableInteger(value);
  }

  function setGiftScopeType(value: MarketingFullReductionGiftScopeType) {
    options.form.giftRule.giftScopeType = value;
    if (value === 'same_lowest') {
      options.form.giftRule.giftScope = createDefaultScopeForm('all');
      return;
    }

    if (options.form.giftRule.giftScope.scopeType === 'all') {
      options.form.giftRule.giftScope = createDefaultScopeForm('product');
    }
  }

  function setSecondHalfDiscountType(
    value: MarketingFullReductionSecondHalfDiscountType,
  ) {
    options.form.secondHalfRule.discountType = value;
  }

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

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

  function setFormStoreScopeMode(value: MarketingFullReductionStoreScopeMode) {
    options.form.storeScopeMode = value;
    if (value === 'all') {
      options.form.storeIds = [];
      return;
    }

    if (
      options.selectedStoreId.value &&
      !options.form.storeIds.includes(options.selectedStoreId.value)
    ) {
      options.form.storeIds = [
        ...options.form.storeIds,
        options.selectedStoreId.value,
      ];
    }
  }

  function setFormStoreIds(value: string[]) {
    options.form.storeIds = normalizeStoreIds(value);
  }

  function setFormStackWithCoupon(value: boolean) {
    options.form.stackWithCoupon = value;
  }

  function setFormDescription(value: string) {
    options.form.description = value;
  }

  async function openGiftApplicablePicker() {
    await options.openPicker(
      {
        title: '选择适用商品范围',
        target: 'giftApplicable',
        allowAll: true,
        initialScope: options.form.giftRule.applicableScope,
        scopeStoreId: resolveScopeStoreId(),
      },
      (scope) => {
        options.form.giftRule.applicableScope = scope;
      },
    );
  }

  async function openGiftScopePicker() {
    await options.openPicker(
      {
        title: '选择指定赠品范围',
        target: 'giftScope',
        allowAll: false,
        initialScope: options.form.giftRule.giftScope,
        scopeStoreId: resolveScopeStoreId(),
      },
      (scope) => {
        options.form.giftRule.giftScope = scope;
      },
    );
  }

  async function openSecondHalfApplicablePicker() {
    await options.openPicker(
      {
        title: '选择第二份半价适用范围',
        target: 'secondHalfApplicable',
        allowAll: false,
        initialScope: options.form.secondHalfRule.applicableScope,
        scopeStoreId: resolveScopeStoreId(),
      },
      (scope) => {
        options.form.secondHalfRule.applicableScope = scope;
      },
    );
  }

  async function openCreateDrawer() {
    resetForm();
    options.form.scopeStoreId = resolveScopeStoreId();
    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 getMarketingFullReductionDetailApi({
        storeId: operationStoreId,
        activityId,
      });

      const mapped = mapDetailToEditorForm(detail);
      mapped.scopeStoreId = resolveScopeStoreId();
      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.storeScopeMode === 'stores' ? options.form.storeIds : [],
    );
    if (!operationStoreId) {
      return;
    }

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

    options.isDrawerSubmitting.value = true;
    try {
      await saveMarketingFullReductionApi(
        buildSaveFullReductionPayload(
          options.form,
          operationStoreId,
          resolveScopeStoreId(),
        ),
      );
      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) {
    if (!options.form.name.trim()) {
      message.warning('请输入活动名称');
      return false;
    }

    if (options.form.name.trim().length > 64) {
      message.warning('活动名称长度不能超过 64 个字符');
      return false;
    }

    if (!options.form.validDateRange) {
      message.warning('请选择活动时间');
      return false;
    }

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

    if (
      options.form.storeScopeMode === 'stores' &&
      options.form.storeIds.length === 0
    ) {
      message.warning('请选择至少一个适用门店');
      return false;
    }

    if (
      options.form.storeScopeMode === 'stores' &&
      !options.form.storeIds.includes(operationStoreId)
    ) {
      message.warning('指定门店需包含当前门店（用于选品基准）');
      return false;
    }

    if (options.form.description.trim().length > 512) {
      message.warning('活动说明长度不能超过 512 个字符');
      return false;
    }

    if (options.form.activityType === 'reduce' && !validateReduceRules()) {
      return false;
    }

    if (options.form.activityType === 'gift' && !validateGiftRules()) {
      return false;
    }

    if (
      options.form.activityType === 'second_half' &&
      !validateSecondHalfRules()
    ) {
      return false;
    }

    return true;
  }

  function validateReduceRules() {
    if (options.form.reduceTiers.length === 0) {
      message.warning('请至少配置一条满减阶梯');
      return false;
    }

    const normalized = options.form.reduceTiers
      .map((tier, index) => ({
        index,
        meetAmount: Number(tier.meetAmount || 0),
        reduceAmount: Number(tier.reduceAmount || 0),
      }))
      .toSorted((first, second) => first.meetAmount - second.meetAmount);

    for (const tier of normalized) {
      if (tier.meetAmount <= 0 || tier.reduceAmount <= 0) {
        message.warning('满减门槛与优惠金额必须大于 0');
        return false;
      }
      if (tier.reduceAmount >= tier.meetAmount) {
        message.warning('满减优惠金额必须小于门槛金额');
        return false;
      }
    }

    for (let index = 1; index < normalized.length; index += 1) {
      const current = normalized[index];
      const previous = normalized[index - 1];
      if (!current || !previous) {
        continue;
      }

      if (current.meetAmount <= previous.meetAmount) {
        message.warning('满减门槛金额必须严格递增');
        return false;
      }
    }

    return true;
  }

  function validateGiftRules() {
    if (
      !options.form.giftRule.buyQuantity ||
      options.form.giftRule.buyQuantity <= 0
    ) {
      message.warning('购买数量门槛必须大于 0');
      return false;
    }

    if (
      !options.form.giftRule.giftQuantity ||
      options.form.giftRule.giftQuantity <= 0
    ) {
      message.warning('赠送数量必须大于 0');
      return false;
    }

    if (
      !validateScope(
        options.form.giftRule.applicableScope,
        true,
        '适用商品范围',
      )
    ) {
      return false;
    }

    if (
      options.form.giftRule.giftScopeType === 'specified' &&
      !validateScope(options.form.giftRule.giftScope, false, '指定赠品范围')
    ) {
      return false;
    }

    return true;
  }

  function validateSecondHalfRules() {
    if (
      !validateScope(
        options.form.secondHalfRule.applicableScope,
        false,
        '第二份半价适用范围',
      )
    ) {
      return false;
    }

    return true;
  }

  function validateScope(
    scope: FullReductionScopeForm,
    allowAll: boolean,
    scopeName: string,
  ) {
    if (!allowAll && scope.scopeType === 'all') {
      message.warning(`${scopeName}不支持全部商品，请选择分类或商品`);
      return false;
    }

    if (scope.scopeType === 'category' && scope.categoryIds.length === 0) {
      message.warning(`${scopeName}至少选择一个分类`);
      return false;
    }

    if (scope.scopeType === 'product' && scope.productIds.length === 0) {
      message.warning(`${scopeName}至少选择一个商品`);
      return false;
    }

    return true;
  }

  function resolveScopeStoreId() {
    const operationStoreId = options.resolveOperationStoreId(
      options.form.storeScopeMode === 'stores' ? options.form.storeIds : [],
    );
    if (operationStoreId) {
      return operationStoreId;
    }
    return options.stores.value[0]?.id ?? '';
  }

  return {
    addReduceTier,
    drawerMode,
    openCreateDrawer,
    openEditDrawer,
    openGiftApplicablePicker,
    openGiftScopePicker,
    openSecondHalfApplicablePicker,
    removeReduceTier,
    setDrawerOpen,
    setFormActivityType,
    setFormChannels,
    setFormDescription,
    setFormName,
    setFormStackWithCoupon,
    setFormStoreIds,
    setFormStoreScopeMode,
    setFormValidDateRange,
    setGiftBuyQuantity,
    setGiftGiftQuantity,
    setGiftScopeType,
    setReduceTierMeetAmount,
    setReduceTierReduceAmount,
    setSecondHalfDiscountType,
    submitDrawer,
  };
}

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.max(0, Math.floor(numeric));
}

function normalizeStoreIds(value: string[]) {
  return [...new Set(value.map((item) => item.trim()).filter(Boolean))];
}
