import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import * as crypto from 'crypto';

interface GatewayCreateOrderParams {
  merchantOrderId: string;
  amount: number;
  paymentMethod: 'alipay' | 'wechat';
  subject?: string;
  remark?: string;
}

interface GatewayCreateOrderResult {
  gatewayOrderId: string;
  merchantOrderId: string;
  amount: number;
  paymentMethod: string;
  payUrl?: string;
  qrcode?: string;
  status: string;
}

export interface GatewayQueryResult {
  gatewayOrderId: string;
  merchantOrderId: string;
  amount: number;
  paymentMethod: string;
  status: string;
  transactionId?: string;
  paidAt?: string;
}

@Injectable()
export class GatewayPayService {
  private readonly logger = new Logger(GatewayPayService.name);
  private readonly apiKey: string;
  private readonly apiSecret: string;
  private readonly baseUrl: string;
  private readonly notifyUrl: string;
  private readonly mock: boolean;

  constructor(private prisma: PrismaService) {
    this.apiKey = process.env.GATEWAY_PAY_API_KEY || '';
    this.apiSecret = process.env.GATEWAY_PAY_API_SECRET || '';
    this.baseUrl = (process.env.GATEWAY_PAY_BASE_URL || 'http://localhost:8100').replace(/\/+$/, '');
    this.notifyUrl = process.env.GATEWAY_PAY_NOTIFY_URL || 'https://yuzhiran.com/api/v1/payment/gateway/webhook';
    this.mock = process.env.GATEWAY_PAY_MOCK === 'true' || !this.apiKey;
    if (this.mock) {
      this.logger.warn('GATEWAY_PAY_MOCK=true，使用模拟支付模式');
    }
  }

  private signRequest(method: string, path: string, body: Record<string, any>): string {
    const timestamp = String(Math.floor(Date.now() / 1000));
    const bodySha256 = crypto.createHash('sha256').update(JSON.stringify(body)).digest('hex');
    const signStr = `${method}\n${path}\n${timestamp}\n${bodySha256}`;
    const signature = crypto.createHmac('sha256', this.apiSecret).update(signStr).digest('hex');
    return `PAY ${this.apiKey}:${timestamp}:${signature}`;
  }

  private signGetRequest(method: string, path: string): string {
    const timestamp = String(Math.floor(Date.now() / 1000));
    const emptyHash = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
    const signStr = `${method}\n${path}\n${timestamp}\n${emptyHash}`;
    const signature = crypto.createHmac('sha256', this.apiSecret).update(signStr).digest('hex');
    return `PAY ${this.apiKey}:${timestamp}:${signature}`;
  }

  async createOrder(params: GatewayCreateOrderParams): Promise<GatewayCreateOrderResult> {
    if (this.mock) {
      this.logger.log(`模拟下单: ${params.merchantOrderId}, ${params.paymentMethod}`);
      return {
        gatewayOrderId: `mock_${Date.now()}`,
        merchantOrderId: params.merchantOrderId,
        amount: params.amount,
        paymentMethod: params.paymentMethod,
        payUrl: params.paymentMethod === 'alipay' ? 'mock://pay' : undefined,
        qrcode: params.paymentMethod === 'wechat' ? 'mock://pay' : undefined,
        status: 'pending',
      };
    }

    const body: Record<string, any> = {
      merchant_order_id: params.merchantOrderId,
      amount: params.amount,
      payment_method: params.paymentMethod,
      subject: params.subject || '宇之然AI会员充值',
      notify_url: this.notifyUrl,
    };
    if (params.remark) {
      body.remark = params.remark;
    }

    const auth = this.signRequest('POST', '/v1/pay/orders', body);

    try {
      const res = await fetch(`${this.baseUrl}/v1/pay/orders`, {
        method: 'POST',
        headers: { Authorization: auth, 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      });
      const json = await res.json();
      if (json.code !== 0) throw new Error(json.message || '网关下单失败');
      this.logger.log(`网关下单成功: ${params.merchantOrderId}, gatewayId: ${json.data.gateway_order_id}`);
      return {
        gatewayOrderId: json.data.gateway_order_id,
        merchantOrderId: json.data.merchant_order_id,
        amount: json.data.amount,
        paymentMethod: json.data.payment_method,
        payUrl: json.data.pay_url,
        qrcode: json.data.qrcode,
        status: json.data.status,
      };
    } catch (err: any) {
      this.logger.error(`网关下单失败: ${err.message}，使用模拟模式`);
      return {
        gatewayOrderId: `mock_${Date.now()}`,
        merchantOrderId: params.merchantOrderId,
        amount: params.amount,
        paymentMethod: params.paymentMethod,
        payUrl: params.paymentMethod === 'alipay' ? 'mock://pay' : undefined,
        qrcode: params.paymentMethod === 'wechat' ? 'mock://pay' : undefined,
        status: 'pending',
      };
    }
  }

  async queryOrder(gatewayOrderId: string): Promise<GatewayQueryResult> {
    if (this.mock || gatewayOrderId.startsWith('mock_')) {
      const order = await this.prisma.order.findFirst({ where: { gatewayOrderId } });
      return {
        gatewayOrderId,
        merchantOrderId: order?.orderNo || '',
        amount: order?.amount || 0,
        paymentMethod: order?.payChannel || 'alipay',
        status: order?.status === 'PAID' ? 'paid' : 'pending',
        transactionId: order?.transactionId || undefined,
      };
    }

    const path = `/v1/pay/orders/${gatewayOrderId}`;
    const auth = this.signGetRequest('GET', path);

    try {
      const res = await fetch(`${this.baseUrl}${path}`, {
        headers: { Authorization: auth },
      });
      const json = await res.json();
      if (json.code !== 0) throw new Error(json.message || '查询失败');
      return {
        gatewayOrderId: json.data.gateway_order_id,
        merchantOrderId: json.data.merchant_order_id,
        amount: json.data.amount,
        paymentMethod: json.data.payment_method,
        status: json.data.status,
        transactionId: json.data.transaction_id,
        paidAt: json.data.paid_at,
      };
    } catch (err: any) {
      this.logger.error(`网关查询失败: ${err.message}`);
      return {
        gatewayOrderId,
        merchantOrderId: '',
        amount: 0,
        paymentMethod: 'alipay',
        status: 'unknown',
      };
    }
  }

  async closeOrder(gatewayOrderId: string): Promise<boolean> {
    if (this.mock || gatewayOrderId.startsWith('mock_')) {
      this.logger.log(`模拟关闭订单: ${gatewayOrderId}`);
      return true;
    }

    const path = `/v1/pay/orders/${gatewayOrderId}/close`;
    const auth = this.signRequest('POST', path, {});

    try {
      const res = await fetch(`${this.baseUrl}${path}`, {
        method: 'POST',
        headers: { Authorization: auth, 'Content-Type': 'application/json' },
        body: '{}',
      });
      const json = await res.json();
      if (json.code !== 0) throw new Error(json.message || '关闭订单失败');
      this.logger.log(`网关订单已关闭: ${gatewayOrderId}`);
      return true;
    } catch (err: any) {
      this.logger.error(`关闭网关订单失败: ${err.message}`);
      return false;
    }
  }

  async syncOrderStatus(orderNo: string): Promise<{ updated: boolean; status: string }> {
    const order = await this.prisma.order.findUnique({ where: { orderNo } });
    if (!order) return { updated: false, status: 'not_found' };
    if (order.status !== 'PENDING' || !order.gatewayOrderId) {
      return { updated: false, status: order.status };
    }

    const gatewayResult = await this.queryOrder(order.gatewayOrderId);
    if (gatewayResult.status === 'paid' && order.status === 'PENDING') {
      await this.prisma.order.update({
        where: { id: order.id },
        data: {
          status: 'PAID',
          paidAt: gatewayResult.paidAt ? new Date(gatewayResult.paidAt) : new Date(),
          transactionId: gatewayResult.transactionId || order.transactionId,
        },
      });
      await this.activateSubscription(order.id);
      this.logger.log(`订单状态同步成功: ${orderNo} (PENDING→PAID)`);
      return { updated: true, status: 'PAID' };
    }
    return { updated: false, status: gatewayResult.status };
  }

  async refund(merchantOrderId: string, amount?: number, reason?: string) {
    if (this.mock) {
      this.logger.log(`模拟网关退款: ${merchantOrderId}`);
      await this.prisma.order.update({
        where: { orderNo: merchantOrderId },
        data: { status: 'REFUNDED' },
      }).catch(err => this.logger.warn(`退款更新订单失败: ${err.message}`));
      return { code: 0, message: '模拟退款成功' };
    }

    const body: Record<string, any> = {
      merchant_order_id: merchantOrderId,
      reason: reason || '用户申请退款',
    };
    if (amount) body.amount = amount;

    const auth = this.signRequest('POST', '/v1/pay/refunds', body);

    try {
      const res = await fetch(`${this.baseUrl}/v1/pay/refunds`, {
        method: 'POST',
        headers: { Authorization: auth, 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      });
      const json = await res.json();
      if (json.code === 0) {
        await this.prisma.order.update({
          where: { orderNo: merchantOrderId },
          data: { status: 'REFUNDED' },
        }).catch(err => this.logger.warn(`退款更新订单失败: ${err.message}`));
      }
      return json;
    } catch (err: any) {
      this.logger.error(`网关退款失败: ${err.message}`);
      throw err;
    }
  }

  async handleWebhook(body: any): Promise<{ code: string; message: string }> {
    const event = body?.event;
    const data = body?.data;

    if (!event || !data) {
      return { code: 'FAIL', message: '无效的webhook数据' };
    }

    this.logger.log(`网关webhook事件: ${event}`);

    if (event === 'recharge.completed') {
      const merchantOrderId = data.merchant_order_id;
      const gatewayOrderId = data.order_id;
      const transactionId = data.transaction_id;

      if (!merchantOrderId) {
        return { code: 'FAIL', message: '缺少商户订单号' };
      }

      const order = await this.prisma.order.findUnique({
        where: { orderNo: merchantOrderId },
        include: { user: true },
      });

      if (!order) {
        this.logger.warn(`webhook订单不存在: ${merchantOrderId}`);
        return { code: 'FAIL', message: '订单不存在' };
      }

      if (order.status === 'PAID') {
        this.logger.log(`webhook订单已支付，跳过: ${merchantOrderId}`);
        return { code: 'SUCCESS', message: '订单已处理' };
      }

      await this.prisma.order.update({
        where: { id: order.id },
        data: {
          status: 'PAID',
          paidAt: new Date(),
          transactionId: transactionId || order.transactionId,
          gatewayOrderId: gatewayOrderId || order.gatewayOrderId,
          payChannel: data.payment_method === 'alipay' ? 'alipay' : 'wxpay',
        },
      });

      await this.activateSubscription(order.id);
      return { code: 'SUCCESS', message: '支付成功' };
    }

    if (event === 'order.refunded') {
      const merchantOrderId = data.merchant_order_id;
      if (merchantOrderId) {
        await this.prisma.order.update({
          where: { orderNo: merchantOrderId },
          data: { status: 'REFUNDED' },
        }).catch(() => {});
      }
      return { code: 'SUCCESS', message: '退款处理成功' };
    }

    return { code: 'SUCCESS', message: '事件已接收' };
  }

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

    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 },
        });
        this.logger.log(`网关支付激活技能: 用户${order.userId}, 技能${meta.skillId}`);
      }
      return;
    }

    if (order.planType !== 'MONTHLY' && order.planType !== 'YEARLY') return;

    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,
      },
    });

    this.logger.log(`网关支付激活订阅: 用户${order.userId}, 类型${order.planType}, 到期${subscriptionEndDate}`);
  }
}
