import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { GatewayPayService } from '../payment/gateway-pay.service';

@Injectable()
export class OrdersService {
  constructor(
    private prisma: PrismaService,
    private gatewayPay: GatewayPayService,
  ) {}

  async create(userId: number, data: { amount: number; planType: string; skillId?: string; payChannel?: string; tradeType?: string; openid?: string }) {
    const channel = data.payChannel || 'alipay';
    const orderNo = `YZR${Date.now()}${Math.random().toString(36).slice(2, 8).toUpperCase()}`;

    const metadata = data.skillId ? JSON.stringify({ skillId: data.skillId }) : null;

    const order = await this.prisma.order.create({
      data: {
        orderNo,
        userId,
        amount: data.amount,
        planType: data.planType,
        payChannel: channel,
        metadata,
      },
    });

    const planLabels: Record<string, string> = {
      MONTHLY: '宇之然AI月卡会员',
      YEARLY: '宇之然AI年卡会员',
      PACKAGE: '宇之然AI用量包',
      SKILL: 'AI技能购买',
    };
    const subject = planLabels[data.planType] || '宇之然AI会员充值';

    try {
      const remark = JSON.stringify({ uid: userId, oid: order.id });
      const result = await this.gatewayPay.createOrder({
        merchantOrderId: orderNo,
        amount: data.amount,
        paymentMethod: channel === 'wxpay' ? 'wechat' : 'alipay',
        subject,
        remark,
      });

      if (result.gatewayOrderId) {
        await this.prisma.order.update({
          where: { id: order.id },
          data: { gatewayOrderId: result.gatewayOrderId },
        });
      }

      const payResult = {
        gatewayOrderId: result.gatewayOrderId,
        payUrl: result.payUrl,
        qrcode: result.qrcode,
        status: result.status,
      };

      if (result.payUrl === 'mock://pay' || result.qrcode === 'mock://pay') {
        await this.completeMockPayment(order.id);
        return { order, payResult: { ...payResult, redirectUrl: 'mock://pay' }, message: '模拟支付完成' };
      }

      return { order, payResult };
    } catch (err) {
      console.error(`网关下单失败: ${err.message}, 使用模拟支付`);
      // 网关失败时，技能订单自动用模拟支付完成，保证用户能购买
      if (data.planType === 'SKILL') {
        await this.completeMockPayment(order.id);
        return {
          order,
          payResult: { gatewayOrderId: null, payUrl: 'mock://pay', qrcode: 'mock://pay', status: 'paid' },
          message: '网关临时不可用，已自动完成支付',
        };
      }
      return { order, payResult: null };
    }
  }

  private async completeMockPayment(orderId: number) {
    const order = await this.prisma.order.findUnique({ where: { id: orderId }, include: { user: true } });
    if (!order || order.status !== 'PENDING') return;

    await this.prisma.order.update({
      where: { id: orderId },
      data: { status: 'PAID', paidAt: new Date() },
    });

    if (order.planType === 'PACKAGE') {
      const extraQuota = order.amount >= 49 ? 300 : 50;
      await this.prisma.user.update({
        where: { id: order.userId },
        data: { sandboxExtra: { increment: extraQuota } },
      });
    } else if (order.planType === 'MONTHLY' || order.planType === 'YEARLY') {
      const durationDays = order.planType === 'MONTHLY' ? 30 : 365;
      const now = new Date();
      let subscriptionEndDate: Date;

      const existingSub = await this.prisma.subscription.findFirst({
        where: { userId: order.userId, status: 'ACTIVE', endDate: { gt: now } },
      });

      if (existingSub) {
        subscriptionEndDate = new Date(existingSub.endDate.getTime() + durationDays * 24 * 60 * 60 * 1000);
        await this.prisma.subscription.update({
          where: { id: existingSub.id },
          data: { endDate: subscriptionEndDate },
        });
      } else {
        subscriptionEndDate = new Date(now);
        subscriptionEndDate.setDate(subscriptionEndDate.getDate() + durationDays);
        await this.prisma.subscription.create({
          data: {
            userId: order.userId,
            plan: order.planType as any,
            startDate: now,
            endDate: subscriptionEndDate,
            status: 'ACTIVE',
          },
        });
      }

      await this.prisma.user.update({
        where: { id: order.userId },
        data: { memberPlan: order.planType as any, memberExpire: subscriptionEndDate },
      });
    } else if (order.planType === 'SKILL' && order.metadata) {
      const meta = JSON.parse(order.metadata);
      if (meta.skillId) {
        await this.prisma.userSkill.upsert({
          where: { userId_skillId: { userId: order.userId, skillId: meta.skillId } },
          update: { orderId: order.id },
          create: { userId: order.userId, skillId: meta.skillId, orderId: order.id },
        });
      }
    }
  }

  async findByUser(userId: number, params: { page?: number; pageSize?: number }) {
    const page = Number(params.page ?? 1);
    const pageSize = Number(params.pageSize ?? 20);
    const [items, total] = await Promise.all([
      this.prisma.order.findMany({
        where: { userId },
        skip: (page - 1) * pageSize,
        take: pageSize,
        orderBy: { createdAt: 'desc' },
      }),
      this.prisma.order.count({ where: { userId } }),
    ]);
    return { items, total, page, pageSize };
  }

  async findByOrderNo(orderNo: string) {
    return this.prisma.order.findUnique({ where: { orderNo } });
  }

  async getCurrentSubscription(userId: number) {
    const now = new Date();
    return this.prisma.subscription.findFirst({
      where: {
        userId,
        status: 'ACTIVE',
        endDate: { gt: now },
      },
      orderBy: { endDate: 'desc' },
    });
  }

  async getSubscriptions(userId: number) {
    return this.prisma.subscription.findMany({
      where: { userId },
      orderBy: { createdAt: 'desc' },
    });
  }
}
