<script setup lang="ts">
import type { UploadChangeParam, UploadFile } from 'ant-design-vue';

import type { PointMallProductEditorForm } from '../types';

import { ref } from 'vue';

import { IconifyIcon } from '@vben/icons';

import {
  Button,
  Drawer,
  Form,
  Input,
  InputNumber,
  message,
  Select,
  Switch,
  Upload,
} from 'ant-design-vue';

import { uploadTenantFileApi } from '#/api/files';

import {
  POINTS_MALL_EXCHANGE_TYPE_OPTIONS,
  POINTS_MALL_NOTIFY_CHANNEL_OPTIONS,
  POINTS_MALL_PICKUP_METHOD_OPTIONS,
  POINTS_MALL_REDEEM_TYPE_HINT_MAP,
  POINTS_MALL_REDEEM_TYPE_OPTIONS,
} from '../composables/points-mall-page/constants';

defineProps<{
  canManage: boolean;
  couponOptions: Array<{ label: string; value: string }>;
  form: PointMallProductEditorForm;
  loading: boolean;
  open: boolean;
  submitText: string;
  submitting: boolean;
  title: string;
}>();

const emit = defineEmits<{
  (event: 'close'): void;
  (event: 'openProductPicker'): void;
  (event: 'searchCoupon', keyword: string): void;
  (event: 'setCashAmount', value: null | number): void;
  (event: 'setCouponTemplateId', value: string): void;
  (event: 'setDescription', value: string): void;
  (event: 'setExchangeType', value: 'mixed' | 'points'): void;
  (event: 'setImageUrl', value: string): void;
  (event: 'setName', value: string): void;
  (event: 'setPerMemberLimit', value: null | number): void;
  (event: 'setPhysicalName', value: string): void;
  (event: 'setPickupMethod', value: 'delivery' | 'store_pickup'): void;
  (event: 'setRedeemType', value: 'coupon' | 'physical' | 'product'): void;
  (event: 'setRequiredPoints', value: null | number): void;
  (event: 'setStatus', value: 'disabled' | 'enabled'): void;
  (event: 'setStockTotal', value: null | number): void;
  (event: 'submit'): void;
  (event: 'toggleNotifyChannel', value: 'in_app' | 'sms'): void;
}>();

const isUploading = ref(false);

function parseNullableNumber(value: null | number | string) {
  if (value === null || value === undefined || value === '') {
    return null;
  }
  const parsed = Number(value);
  return Number.isNaN(parsed) ? null : parsed;
}

function setRedeemType(value: unknown) {
  if (value === 'product' || value === 'coupon' || value === 'physical') {
    emit('setRedeemType', value);
  }
}

function setExchangeType(value: unknown) {
  if (value === 'points' || value === 'mixed') {
    emit('setExchangeType', value);
  }
}

function setPickupMethod(value: unknown) {
  if (value === 'store_pickup' || value === 'delivery') {
    emit('setPickupMethod', value);
  }
}

function setStatusByChecked(checked: unknown) {
  emit('setStatus', checked === true ? 'enabled' : 'disabled');
}

async function handleUploadChange(info: UploadChangeParam<UploadFile>) {
  const rawFile = info.file.originFileObj;
  if (!rawFile) {
    return;
  }

  isUploading.value = true;
  try {
    const result = await uploadTenantFileApi(rawFile, 'dish_image');
    if (result.url) {
      emit('setImageUrl', result.url);
      message.success('上传成功');
    } else {
      message.error('上传失败');
    }
  } catch (error) {
    console.error(error);
    message.error('上传失败');
  } finally {
    isUploading.value = false;
  }
}
</script>

<template>
  <Drawer
    :open="open"
    :title="title"
    width="560"
    class="mpm-editor-drawer"
    @close="emit('close')"
  >
    <Form layout="vertical">
      <Form.Item label="兑换类型" required>
        <div class="mpm-pill-row">
          <button
            v-for="item in POINTS_MALL_REDEEM_TYPE_OPTIONS"
            :key="item.value"
            type="button"
            class="mpm-pill"
            :class="{ checked: form.redeemType === item.value }"
            :disabled="!canManage || loading"
            @click="setRedeemType(item.value)"
          >
            {{ item.label }}
          </button>
        </div>
        <div class="mpm-form-hint">
          {{ POINTS_MALL_REDEEM_TYPE_HINT_MAP[form.redeemType] }}
        </div>
      </Form.Item>

      <template v-if="form.redeemType === 'product'">
        <Form.Item label="关联商品" required>
          <div v-if="form.productId" class="mpm-selected-product">
            <span class="name">{{ form.productName || form.productId }}</span>
            <span class="id">ID: {{ form.productId }}</span>
          </div>
          <Button
            :disabled="!canManage || loading"
            @click="emit('openProductPicker')"
          >
            选择商品/套餐
          </Button>
          <div class="mpm-form-hint">兑换后系统自动生成该商品的兑换券</div>
        </Form.Item>
      </template>

      <template v-else-if="form.redeemType === 'coupon'">
        <Form.Item label="关联优惠券" required>
          <Select
            :value="form.couponTemplateId || undefined"
            :options="couponOptions"
            show-search
            :filter-option="false"
            :disabled="!canManage || loading"
            placeholder="请选择优惠券"
            @search="(value) => emit('searchCoupon', String(value ?? ''))"
            @update:value="
              (value) => emit('setCouponTemplateId', String(value ?? ''))
            "
          />
          <div class="mpm-form-hint">
            选择已在优惠券管理中创建的券，兑换后直接发到顾客券包
          </div>
        </Form.Item>
      </template>

      <template v-else>
        <Form.Item label="实物名称" required>
          <Input
            :value="form.physicalName"
            :maxlength="64"
            :disabled="!canManage || loading"
            placeholder="如：定制保温杯、品牌帆布袋"
            @update:value="
              (value) => emit('setPhysicalName', String(value ?? ''))
            "
          />
        </Form.Item>
        <Form.Item label="领取方式">
          <div class="mpm-pill-row">
            <button
              v-for="item in POINTS_MALL_PICKUP_METHOD_OPTIONS"
              :key="item.value"
              type="button"
              class="mpm-pill"
              :class="{ checked: form.pickupMethod === item.value }"
              :disabled="!canManage || loading"
              @click="setPickupMethod(item.value)"
            >
              {{ item.label }}
            </button>
          </div>
        </Form.Item>
      </template>

      <Form.Item label="展示名称" required>
        <Input
          :value="form.name"
          :maxlength="64"
          :disabled="!canManage || loading"
          placeholder="如：招牌奶茶兑换券、满50减15券"
          @update:value="(value) => emit('setName', String(value ?? ''))"
        />
        <div class="mpm-form-hint">顾客在积分商城看到的名称</div>
      </Form.Item>

      <Form.Item label="展示图片">
        <div class="mpm-image-field">
          <img
            v-if="form.imageUrl"
            class="mpm-image-preview"
            :src="form.imageUrl"
            alt="points-product"
          />
          <Upload
            :show-upload-list="false"
            :before-upload="() => false"
            :disabled="!canManage || loading || isUploading"
            @change="handleUploadChange"
          >
            <Button :loading="isUploading" :disabled="!canManage || loading">
              <IconifyIcon icon="lucide:upload-cloud" />
              {{ form.imageUrl ? '重新上传' : '点击上传商品图片' }}
            </Button>
          </Upload>
        </div>
      </Form.Item>

      <Form.Item label="兑换方式" required>
        <div class="mpm-pill-row">
          <button
            v-for="item in POINTS_MALL_EXCHANGE_TYPE_OPTIONS"
            :key="item.value"
            type="button"
            class="mpm-pill"
            :class="{ checked: form.exchangeType === item.value }"
            :disabled="!canManage || loading"
            @click="setExchangeType(item.value)"
          >
            {{ item.label }}
          </button>
        </div>
      </Form.Item>

      <Form.Item label="所需积分" required>
        <InputNumber
          :value="form.requiredPoints ?? undefined"
          :min="0"
          :precision="0"
          :disabled="!canManage || loading"
          style="width: 100%"
          placeholder="请输入所需积分数量"
          @update:value="
            (value) => emit('setRequiredPoints', parseNullableNumber(value))
          "
        />
      </Form.Item>

      <Form.Item v-if="form.exchangeType === 'mixed'" label="现金部分" required>
        <InputNumber
          :value="form.cashAmount ?? undefined"
          :min="0"
          :precision="2"
          :disabled="!canManage || loading"
          style="width: 100%"
          placeholder="请输入需额外支付的金额"
          @update:value="
            (value) => emit('setCashAmount', parseNullableNumber(value))
          "
        />
        <div class="mpm-form-hint">用户兑换时需额外支付的现金金额</div>
      </Form.Item>

      <Form.Item label="库存数量" required>
        <InputNumber
          :value="form.stockTotal ?? undefined"
          :min="0"
          :precision="0"
          :disabled="!canManage || loading"
          style="width: 100%"
          placeholder="请输入库存数量"
          @update:value="
            (value) => emit('setStockTotal', parseNullableNumber(value))
          "
        />
      </Form.Item>

      <Form.Item label="兑换限制">
        <div class="mpm-inline-fields">
          <span>每人限兑</span>
          <InputNumber
            :value="form.perMemberLimit ?? undefined"
            :min="0"
            :precision="0"
            :disabled="!canManage || loading"
            placeholder="不限"
            @update:value="
              (value) => emit('setPerMemberLimit', parseNullableNumber(value))
            "
          />
          <span>次</span>
        </div>
        <div class="mpm-form-hint">留空或填0表示不限制兑换次数</div>
      </Form.Item>

      <Form.Item label="商品描述">
        <Input.TextArea
          :value="form.description"
          :maxlength="512"
          :rows="4"
          :disabled="!canManage || loading"
          placeholder="请输入商品描述信息，如使用规则、有效期等"
          @update:value="(value) => emit('setDescription', String(value ?? ''))"
        />
      </Form.Item>

      <Form.Item label="到账通知">
        <div class="mpm-pill-row">
          <button
            v-for="item in POINTS_MALL_NOTIFY_CHANNEL_OPTIONS"
            :key="item.value"
            type="button"
            class="mpm-pill"
            :class="{ checked: form.notifyChannels.includes(item.value) }"
            :disabled="!canManage || loading"
            @click="emit('toggleNotifyChannel', item.value)"
          >
            {{ item.label }}
          </button>
        </div>
        <div class="mpm-form-hint">
          选择兑换成功后通知顾客的方式，实物商品建议开启短信通知
        </div>
      </Form.Item>

      <Form.Item label="上架状态">
        <div class="mpm-inline-fields">
          <Switch
            :checked="form.status === 'enabled'"
            :disabled="!canManage || loading"
            @change="setStatusByChecked"
          />
          <span class="mpm-form-hint">
            {{ form.status === 'enabled' ? '当前上架中' : '当前已下架' }}
          </span>
        </div>
      </Form.Item>
    </Form>

    <template #footer>
      <div class="mpm-drawer-footer">
        <Button @click="emit('close')">取消</Button>
        <Button
          type="primary"
          :loading="submitting"
          :disabled="!canManage || loading"
          @click="emit('submit')"
        >
          {{ submitText }}
        </Button>
      </div>
    </template>
  </Drawer>
</template>
