import Taro from '@tarojs/taro';
import { createOrder, WxPayResult } from '@/api/shop/shopOrder';
import { OrderCreateRequest } from '@/api/shop/shopOrder/model';
import { getSelectedStoreFromStorage, getSelectedStoreIdFromStorage } from '@/utils/storeSelection';
import type { ShopStoreRider } from '@/api/shop/shopStoreRider/model';
import type { ShopStoreWarehouse } from '@/api/shop/shopStoreWarehouse/model';
import request from '@/utils/request';
import { getWxOpenId, getUserInfo } from '@/api/layout';

/**
 * 支付类型枚举
 */
export enum PaymentType {
  BALANCE = 0,  // 余额支付
  WECHAT = 1,   // 微信支付
  ALIPAY = 3,   // 支付宝支付
}

/**
 * 支付结果回调
 */
export interface PaymentCallback {
  // Return `false` to skip default "支付成功" toast + redirect.
  onSuccess?: () => void | boolean | Promise<void | boolean>;
  onError?: (error: string) => void;
  onComplete?: () => void;
}

/**
 * 统一支付处理类
 */
export class PaymentHandler {
  // 简单缓存，避免频繁请求（小程序单次运行生命周期内有效）
  private static storeRidersCache = new Map<number, ShopStoreRider[]>();
  private static warehousesCache: ShopStoreWarehouse[] | null = null;

  /**
   * 【关键修复】支付前确保当前微信用户的 openid 已正确绑定到后端
   *
   * 问题场景：
   * 1. 用户通过手机号注册 → openid 未绑定 → 后端用空 openid 创建预支付单 → 支付时报"账号不一致"
   * 2. 用户切换了微信账号 → 本地缓存的用户信息是旧账号的 → openid 与当前支付人不匹配
   * 3. 自动登录(loginByOpenId)未触发 getWxOpenId 绑定流程
   *
   * 解决方案：每次微信支付前，重新获取 wx.login code 并调用 getWxOpenId 绑定，
   *           确保后端记录的 openid = 当前实际支付人的 openid
   */
  private static async ensureOpenIdBeforePay(): Promise<void> {
    try {
      // 非微信环境跳过（如 H5 开发调试）
      let isWeapp = false;
      try {
        isWeapp = Taro.getEnv() === Taro.ENV_TYPE.WEAPP;
      } catch (_e) {
        isWeapp = process.env.TARO_ENV === 'weapp';
      }
      if (!isWeapp) return;

      // 获取当前登录用户的最新信息（检查是否已有 openid）
      let currentUser = null;
      try {
        currentUser = await getUserInfo();
      } catch (_e) {
        // getUserInfo 失败时不阻塞支付（可能是 token 过期等），让后续接口自行报错
        console.warn('[ensureOpenId] 获取用户信息失败，跳过 openid 校验');
        return;
      }

      // 如果用户已有 openid，仍然需要刷新：因为用户可能切换了微信账号
      // 每次都重新获取 code + 绑定，确保 openid 是当前微信会话的

      const code = await new Promise<string | undefined>((resolve, reject) => {
        Taro.login({
          success: (res) => resolve(res.code as string),
          fail: (e) => reject(e),
          timeout: 5000, // 5秒超时
        });
      });

      if (!code) {
        console.warn('[ensureOpenId] wx.login 未返回 code');
        return;
      }

      // 调用后端绑定/更新 openid
      await getWxOpenId({ code });
      console.log('[ensureOpenId] openid 刷新/绑定成功');

      // 同步本地 User 缓存，确保后续逻辑能读到最新 openid
      try {
        const freshUser = await getUserInfo();
        if (freshUser) {
          Taro.setStorageSync('User', freshUser);
        }
      } catch (_e) {
        // ignore: 服务端已更新 openid，本地缓存不同步也不影响本次支付
      }
    } catch (error) {
      // openid 刷新失败不阻塞支付流程（可能网络波动），
      // 但记录日志方便排查；若确实不一致，微信支付侧会报错
      console.warn('[ensureOpenId] openid 刷新失败(非阻塞):', error);
    }
  }

  /**
   * 执行支付
   * @param orderData 订单数据
   * @param paymentType 支付类型
   * @param callback 回调函数
   */
  static async pay(
    orderData: OrderCreateRequest,
    paymentType: PaymentType,
    callback?: PaymentCallback
  ): Promise<void> {
    Taro.showLoading({ title: '支付中...' });

    try {
      // 若调用方未指定门店，则自动注入“已选门店”，用于订单门店归属/统计。
      if (orderData.storeId === undefined || orderData.storeId === null) {
        const storeId = getSelectedStoreIdFromStorage();
        if (storeId) {
          orderData.storeId = storeId;
        }
      }
      if (!orderData.storeName) {
        const store = getSelectedStoreFromStorage();
        if (store?.name) {
          orderData.storeName = store.name;
        }
      }

      // 自动派单：按门店骑手优先级（dispatchPriority）选择 riderId（不覆盖手动指定）
      if ((orderData.riderId === undefined || orderData.riderId === null) && orderData.storeId) {
        const riderUserId = await this.pickRiderUserIdForStore(orderData.storeId);
        if (riderUserId) {
          orderData.riderId = riderUserId;
        }
      }

      // 仓库选择：若未指定 warehouseId，则按“离门店最近”兜底选择一个（不覆盖手动指定）
      if ((orderData.warehouseId === undefined || orderData.warehouseId === null) && orderData.storeId) {
        const warehouseId = await this.pickWarehouseIdForStore(orderData.storeId);
        if (warehouseId) {
          orderData.warehouseId = warehouseId;
        }
      }

      // 设置支付类型
      orderData.payType = paymentType;

      // 【关键修复】微信支付前，强制刷新/绑定当前微信用户的 openid
      // 防止"下单账号与支付账号不一致"错误
      if (paymentType === PaymentType.WECHAT) {
        await this.ensureOpenIdBeforePay();
      }

      console.log('创建订单请求:', orderData);

      // 创建订单
      const result = await createOrder(orderData);

      console.log('订单创建结果:', result);

      if (!result) {
        throw new Error('创建订单失败');
      }

      // 验证订单创建结果
      if (!result.orderNo) {
        throw new Error('订单号获取失败');
      }

      let paymentSuccess = false;

      // 根据支付类型处理
      switch (paymentType) {
        case PaymentType.WECHAT:
          await this.handleWechatPay(result);
          paymentSuccess = true;
          break;
        case PaymentType.BALANCE:
          paymentSuccess = await this.handleBalancePay(result);
          break;
        case PaymentType.ALIPAY:
          await this.handleAlipay(result);
          paymentSuccess = true;
          break;
        default:
          throw new Error('不支持的支付方式');
      }

      // 只有确认支付成功才显示成功提示和跳转
      if (paymentSuccess) {
        console.log('支付成功，订单号:', result.orderNo);

        // 先收起 loading，避免遮挡 modal/toast
        try {
          Taro.hideLoading();
        } catch (_e) {
          // ignore
        }

        const onSuccessResult = await callback?.onSuccess?.();
        const skipDefaultSuccessBehavior = onSuccessResult === false;

        if (!skipDefaultSuccessBehavior) {
          Taro.showToast({
            title: '支付成功',
            icon: 'success'
          });

          // 跳转到订单页面
          setTimeout(() => {
            Taro.navigateTo({ url: '/user/order/order' });
          }, 2000);
        }
      } else {
        throw new Error('支付未完成');
      }

    } catch (error: any) {
      console.error('支付失败:', error);

      // 获取详细错误信息
      const errorMessage = this.getErrorMessage(error);

      Taro.showToast({
        title: errorMessage,
        icon: 'error'
      });

      // 标记错误已处理，避免上层重复处理
      error.handled = true;
      callback?.onError?.(errorMessage);

      // 重新抛出错误，让上层知道支付失败
      throw error;
    } finally {
      Taro.hideLoading();
      callback?.onComplete?.();
    }
  }

  private static parseLngLat(raw: string | undefined): { lng: number; lat: number } | null {
    const text = (raw || '').trim();
    if (!text) return null;
    const parts = text.split(/[,\s]+/).filter(Boolean);
    if (parts.length < 2) return null;
    const a = parseFloat(parts[0]);
    const b = parseFloat(parts[1]);
    if (Number.isNaN(a) || Number.isNaN(b)) return null;
    const looksLikeLngLat = Math.abs(a) <= 180 && Math.abs(b) <= 90;
    const looksLikeLatLng = Math.abs(a) <= 90 && Math.abs(b) <= 180;
    if (looksLikeLngLat) return { lng: a, lat: b };
    if (looksLikeLatLng) return { lng: b, lat: a };
    return null;
  }

  private static distanceMeters(a: { lng: number; lat: number }, b: { lng: number; lat: number }) {
    const toRad = (x: number) => (x * Math.PI) / 180;
    const R = 6371000;
    const dLat = toRad(b.lat - a.lat);
    const dLng = toRad(b.lng - a.lng);
    const lat1 = toRad(a.lat);
    const lat2 = toRad(b.lat);
    const sin1 = Math.sin(dLat / 2);
    const sin2 = Math.sin(dLng / 2);
    const h = sin1 * sin1 + Math.cos(lat1) * Math.cos(lat2) * sin2 * sin2;
    return 2 * R * Math.asin(Math.min(1, Math.sqrt(h)));
  }

  private static async getRidersForStore(storeId: number): Promise<ShopStoreRider[]> {
    const cached = this.storeRidersCache.get(storeId);
    if (cached) return cached;

    // 后端字段可能叫 dealerId 或 storeId，这里都带上，服务端忽略未知字段即可。
    // 这里做一次路径兼容（camel vs kebab），避免接口路径不一致导致整单失败。
    const list = await this.listByCompatEndpoint<ShopStoreRider>(
      ['/shop/shop-store-rider'],
      {
        storeId: storeId,
        status: 1
      }
    );

    const usable = (list || []).filter(r => r?.isDelete !== 1 && (r.status === undefined || r.status === 1));
    this.storeRidersCache.set(storeId, usable);
    return usable;
  }

  private static async pickRiderUserIdForStore(storeId: number): Promise<number | undefined> {
    const riders = await this.getRidersForStore(storeId);
    if (!riders.length) return undefined;

    // 优先：启用 + 在线 + 自动派单，再按 dispatchPriority 由高到低
    const score = (r: ShopStoreRider) => {
      const enabled = (r.status === undefined || r.status === 1) ? 1 : 0;
      const online = r.workStatus === 1 ? 1 : 0;
      const auto = r.autoDispatchEnabled === 1 ? 1 : 0;
      const p = typeof r.dispatchPriority === 'number' ? r.dispatchPriority : 0;
      return enabled * 1000 + online * 100 + auto * 10 + p;
    };

    const sorted = [...riders].sort((a, b) => score(b) - score(a));
    return sorted[0]?.userId;
  }

  private static async getWarehouses(): Promise<ShopStoreWarehouse[]> {
    if (this.warehousesCache) return this.warehousesCache;
    const list = await this.listByCompatEndpoint<ShopStoreWarehouse>(
      ['/shop/shop-store-warehouse'],
      {}
    );
    const usable = (list || []).filter(w => w?.isDelete !== 1 && (w.status === undefined || w.status === 1));
    this.warehousesCache = usable;
    return usable;
  }

  private static async pickWarehouseIdForStore(storeId: number): Promise<number | undefined> {
    const store = getSelectedStoreFromStorage();
    if (!store?.id || store.id !== storeId) return undefined;

    // 一门店一默认仓库：优先使用门店自带的 warehouseId
    if (store.warehouseId) return store.warehouseId;

    const storeCoords = this.parseLngLat(store.lngAndLat || store.location);
    if (!storeCoords) return undefined;

    const warehouses = await this.getWarehouses();
    if (!warehouses.length) return undefined;

    // 优先选择“门店仓”，否则选最近的任意仓库
    const candidates = warehouses.filter(w => w.type?.includes('门店') || w.type?.includes('门店仓'));
    const list = candidates.length ? candidates : warehouses;

    const withDistance = list
      .map(w => {
        const coords = this.parseLngLat(w.lngAndLat);
        if (!coords) return { w, d: Number.POSITIVE_INFINITY };
        return { w, d: this.distanceMeters(storeCoords, coords) };
      })
      .sort((a, b) => a.d - b.d);

    return withDistance[0]?.w?.id;
  }

  private static async listByCompatEndpoint<T>(
    urls: string[],
    params: Record<string, any>
  ): Promise<T[]> {
    for (const url of urls) {
      try {
        const res: any = await (request as any).get(url, params, { showError: false });
        if (res?.code === 0 && Array.isArray(res?.data)) {
          return res.data as T[];
        }
      } catch (_e) {
        // try next
      }
    }
    return [];
  }

  /**
   * 处理微信支付
   */
  private static async handleWechatPay(result: WxPayResult): Promise<void> {
    console.log('处理微信支付:', result);

    if (!result) {
      throw new Error('微信支付参数错误');
    }

    // 验证微信支付必要参数
    if (!result.timeStamp || !result.nonceStr || !result.package || !result.paySign) {
      throw new Error('微信支付参数不完整');
    }

    try {
      await Taro.requestPayment({
        timeStamp: result.timeStamp,
        nonceStr: result.nonceStr,
        package: result.package,
        signType: result.signType as any, // 类型转换，因为微信支付的signType是字符串
        paySign: result.paySign,
      });

      console.log('微信支付成功');
    } catch (payError: any) {
      console.error('微信支付失败:', payError);

      // 处理微信支付特定错误
      if (payError.errMsg) {
        if (payError.errMsg.includes('cancel')) {
          throw new Error('用户取消支付');
        } else if (payError.errMsg.includes('fail')) {
          throw new Error('微信支付失败，请重试');
        }
      }

      throw new Error('微信支付失败');
    }
  }

  /**
   * 处理余额支付
   */
  private static async handleBalancePay(result: any): Promise<boolean> {
    console.log('处理余额支付:', result);

    if (!result || !result.orderNo) {
      throw new Error('余额支付参数错误');
    }

    // 检查支付状态 - 根据后端返回的字段调整
    if (result.payStatus === false || result.payStatus === 0 || result.payStatus === '0') {
      throw new Error('余额不足或支付失败');
    }

    // 检查订单状态 - 1表示已付款
    if (result.orderStatus !== undefined && result.orderStatus !== 1) {
      throw new Error('订单状态异常，支付可能未成功');
    }

    // 验证实际扣款金额
    if (result.payPrice !== undefined) {
      const payPrice = parseFloat(result.payPrice);
      if (payPrice <= 0) {
        throw new Error('支付金额异常');
      }
    }

    // 如果有错误信息字段，检查是否有错误
    if (result.error || result.errorMsg) {
      throw new Error(result.error || result.errorMsg);
    }

    console.log('余额支付验证通过');
    return true;
  }

  /**
   * 处理支付宝支付
   */
  private static async handleAlipay(_result: any): Promise<void> {
    // 支付宝支付逻辑，根据实际情况实现
    throw new Error('支付宝支付暂未实现');
  }

  /**
   * 获取详细错误信息
   */
  private static getErrorMessage(error: any): string {
    if (!error.message) {
      return '支付失败，请重试';
    }

    const message = error.message;

    // 配送范围/电子围栏相关错误（优先于“地址信息有误”的兜底）
    if (
      message.includes('不在配送范围') ||
      message.includes('配送范围') ||
      message.includes('电子围栏') ||
      message.includes('围栏')
    ) {
      // Toast 文案尽量短（小程序 showToast 标题长度有限），更详细的引导可在业务页面用 Modal 呈现。
      return '暂不支持配送';
    }

    // 余额相关错误
    if (message.includes('余额不足') || message.includes('balance')) {
      return '账户余额不足，请充值后重试';
    }

    // 优惠券相关错误
    if (message.includes('优惠券') || message.includes('coupon')) {
      return '优惠券使用失败，请重新选择';
    }

    // 库存相关错误
    if (message.includes('库存') || message.includes('stock')) {
      return '商品库存不足，请减少购买数量';
    }

    // 地址相关错误
    if (message.includes('地址') || message.includes('address')) {
      return '收货地址信息有误，请重新选择';
    }

    // 订单相关错误
    if (message.includes('订单') || message.includes('order')) {
      return '订单创建失败，请重试';
    }

    // 网络相关错误
    if (message.includes('网络') || message.includes('network') || message.includes('timeout')) {
      return '网络连接异常，请检查网络后重试';
    }

    // 微信支付相关错误
    if (message.includes('微信') || message.includes('wechat') || message.includes('wx')) {
      return '微信支付失败，请重试';
    }

    // 返回原始错误信息
    return message;
  }
}

/**
 * 快捷支付方法
 */
export const quickPay = {
  /**
   * 微信支付
   */
  wechat: (orderData: OrderCreateRequest, callback?: PaymentCallback) => {
    return PaymentHandler.pay(orderData, PaymentType.WECHAT, callback);
  },

  /**
   * 余额支付
   */
  balance: (orderData: OrderCreateRequest, callback?: PaymentCallback) => {
    return PaymentHandler.pay(orderData, PaymentType.BALANCE, callback);
  },

  /**
   * 支付宝支付
   */
  alipay: (orderData: OrderCreateRequest, callback?: PaymentCallback) => {
    return PaymentHandler.pay(orderData, PaymentType.ALIPAY, callback);
  }
};

/**
 * 构建单商品订单数据
 */
export function buildSingleGoodsOrder(
  goodsId: number,
  quantity: number = 1,
  addressId?: number,
  options?: {
    comments?: string;
    deliveryType?: number;
    couponId?: any;
    selfTakeMerchantId?: number;
    skuId?: number;
    specInfo?: string;
    buyerRemarks?: string;
    sendStartTime?: string;
    deliveryMethod?: string;
    deliveryFloor?: number;
  }
): OrderCreateRequest {
  return {
    goodsItems: [
      {
        goodsId,
        quantity,
        skuId: options?.skuId,
        specInfo: options?.specInfo
      }
    ],
    addressId,
    payType: PaymentType.WECHAT, // 默认微信支付，会被PaymentHandler覆盖
    comments: options?.buyerRemarks || options?.comments || '',
    sendStartTime: options?.sendStartTime,
    deliveryType: options?.deliveryType || 0,
    couponId: options?.couponId,
    selfTakeMerchantId: options?.selfTakeMerchantId,
    deliveryMethod: options?.deliveryMethod,
    deliveryFloor: options?.deliveryFloor
  };
}

/**
 * 构建购物车订单数据
 */
export function buildCartOrder(
  cartItems: Array<{ goodsId: number; quantity: number }>,
  addressId?: number,
  options?: {
    comments?: string;
    deliveryType?: number;
    couponId?: number;
    selfTakeMerchantId?: number;
  }
): OrderCreateRequest {
  return {
    goodsItems: cartItems.map(item => ({
      goodsId: item.goodsId,
      quantity: item.quantity
    })),
    addressId,
    payType: PaymentType.WECHAT, // 默认微信支付，会被PaymentHandler覆盖
    comments: options?.comments || '购物车下单',
    deliveryType: options?.deliveryType || 0,
    couponId: options?.couponId,
    selfTakeMerchantId: options?.selfTakeMerchantId
  };
}
