/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
  Count,
  CountSchema,
  Filter,
  FilterExcludingWhere,
  repository,
  Where,
} from '@loopback/repository';
import {
  post,
  param,
  get,
  getModelSchemaRef,
  patch,
  put,
  del,
  requestBody,
  response,
  HttpErrors,
} from '@loopback/rest';
import {PackagePurchase} from '../models';
import {PackagePurchaseRepository} from '../repositories';
import {inject} from '@loopback/core';
import {Request, RestBindings} from '@loopback/rest';

// PhonePe Configuration
const PHONEPE_CONFIG = {
  merchantId: "MERCHANTUAT",
  saltKey: "099eb0cd-02cf-4e2a-8aca-3e6c6aff0399",
  saltIndex: "1",
  apiEndpoint: "https://api-preprod.phonepe.com/apis/pg-sandbox",
};

export class PackagePurchaseController {
  constructor(
    @repository(PackagePurchaseRepository)
    public packagePurchaseRepository: PackagePurchaseRepository,
    @inject(RestBindings.Http.REQUEST) private request: Request,
  ) { }

  /**
   * Verify PhonePe payment and create package purchase
   */
  // @post('/package-purchases/verify-payment')
  // @response(200, {
  //   description: 'Verify PhonePe payment and create package purchase',
  //   content: {'application/json': {schema: getModelSchemaRef(PackagePurchase)}},
  // })
  // async verifyPayment(
  //   @requestBody({
  //     content: {
  //       'application/json': {
  //         schema: {
  //           type: 'object',
  //           required: ['transactionId', 'packageId', 'userId', 'amount'],
  //           properties: {
  //             transactionId: {type: 'string'},
  //             packageId: {type: 'number'},
  //             userId: {type: 'number'},
  //             amount: {type: 'number'},
  //             packageDuration: {type: 'number'},
  //             propertyVisit: {type: 'number'},
  //             propertyAddToCart: {type: 'number'},
  //             usertypeId: {type: 'number'},
  //           },
  //         },
  //       },
  //     },
  //   })
  //   paymentData: {
  //     transactionId: string;
  //     packageId: number;
  //     userId: number;
  //     amount: number;
  //     packageDuration?: number;
  //     propertyVisit?: number;
  //     propertyAddToCart?: number;
  //     usertypeId?: number;
  //   },
  // ): Promise<PackagePurchase> {
  //   try {
  //     console.log('=== Backend: Verifying Payment ===');
  //     console.log('Payment Data:', paymentData);

  //     // Check if transaction already exists
  //     const existingPurchase = await this.packagePurchaseRepository.findOne({
  //       where: {paymentNo: paymentData.transactionId},
  //     });

  //     if (existingPurchase) {
  //       console.log('Transaction already processed:', paymentData.transactionId);
  //       throw new HttpErrors.BadRequest('Transaction already processed');
  //     }

  //     // Verify payment with PhonePe API
  //     console.log('Verifying with PhonePe API...');
  //     const paymentStatus = await this.verifyPhonePePayment(paymentData.transactionId);

  //     console.log('PhonePe Verification Result:', paymentStatus);

  //     if (!paymentStatus.success) {
  //       throw new HttpErrors.BadRequest(
  //         `Payment verification failed: ${paymentStatus.error || 'Unknown error'}`,
  //       );
  //     }

  //     if (paymentStatus.status !== 'COMPLETED' && paymentStatus.status !== 'SUCCESS') {
  //       throw new HttpErrors.BadRequest(
  //         `Payment is not completed. Current status: ${paymentStatus.status}`,
  //       );
  //     }

  //     // Verify amount matches
  //     const expectedAmount = Math.round(paymentData.amount * 100); // Convert to paise
  //     const actualAmount = paymentStatus.amount;

  //     console.log(`Amount verification - Expected: ${expectedAmount}, Actual: ${actualAmount}`);

  //     if (Math.abs(expectedAmount - actualAmount) > 1) {
  //       // Allow 1 paise difference for rounding
  //       throw new HttpErrors.BadRequest(
  //         `Amount mismatch. Expected: ₹${paymentData.amount}, Got: ₹${actualAmount / 100}`,
  //       );
  //     }

  //     // Calculate dates
  //     const currentDate = new Date();
  //     const packageEndDate = new Date();
  //     packageEndDate.setDate(currentDate.getDate() + (paymentData.packageDuration ?? 30));

  //     console.log('Creating package purchase record...');

  //     // Create package purchase record
  //     const packagePurchase = await this.packagePurchaseRepository.create({
  //       fkPackageId: paymentData.packageId,
  //       fkBuyerIdSellerId: paymentData.userId,
  //       fkUsertypeId: paymentData.usertypeId ?? 1,
  //       date: currentDate.toISOString().split('T')[0], // YYYY-MM-DD
  //       time: currentDate.toTimeString().split(' ')[0], // HH:MM:SS
  //       paymentFag: 1, // 1 for PhonePe
  //       paymentNo: paymentData.transactionId,
  //       paymentAmount: paymentData.amount,
  //       propertyVisit: paymentData.propertyVisit ?? 0,
  //       propertyAddToCart: paymentData.propertyAddToCart ?? 0,
  //       packageEndDate: packageEndDate.toISOString().split('T')[0],
  //       isDefault: 0,
  //       isOn: 1,
  //       isActive: 1,
  //       createdDate: currentDate.toISOString(),
  //       createdBy: paymentData.userId,
  //       lastChanged: currentDate.toISOString(),
  //     });

  //     console.log('Package purchase created:', packagePurchase.packagePurchaseId);

  //     return packagePurchase;
  //   } catch (error) {
  //     console.error('=== Backend: Payment Verification Error ===');
  //     console.error('Error:', error);

  //     if (error instanceof HttpErrors.HttpError) {
  //       throw error;
  //     }

  //     throw new HttpErrors.InternalServerError(
  //       `Failed to verify payment: ${error.message}`,
  //     );
  //   }
  // }

  // Backend Controller Update for DEMO MODE
  // Add this to your package-purchase.controller.ts

  // Update the verifyPayment function to handle demo mode:

  // src/controllers/package-purchase.controller.ts - 修改 verifyPayment 方法

  @post('/package-purchases/verify-payment')
  @response(200, {
    description: 'Verify PhonePe payment and create package purchase',
    content: {'application/json': {schema: getModelSchemaRef(PackagePurchase)}},
  })
  async verifyPayment(
    @requestBody({
      content: {
        'application/json': {
          schema: {
            type: 'object',
            required: ['transactionId', 'packageId', 'userId', 'amount'],
            properties: {
              transactionId: {type: 'string'},
              packageId: {type: 'number'},
              userId: {type: 'number'},
              amount: {type: 'number'},
              packageDuration: {type: 'number'},
              propertyVisit: {type: 'number'},
              propertyAddToCart: {type: 'number'},
              usertypeId: {type: 'number'},
              isDemoMode: {type: 'boolean'},
            },
          },
        },
      },
    })
    paymentData: {
      transactionId: string;
      packageId: number;
      userId: number;
      amount: number;
      packageDuration?: number;
      propertyVisit?: number;
      propertyAddToCart?: number;
      usertypeId?: number;
      isDemoMode?: boolean;
    },
  ): Promise<PackagePurchase> {
    try {
      console.log('=== Backend: Package Purchase Creation ===');
      console.log('Payment Data:', paymentData);

      // 检查是否为演示模式
      const isDemoMode = paymentData.isDemoMode || paymentData.transactionId?.startsWith('DEMO');

      if (isDemoMode) {
        console.log('⚠️ DEMO MODE DETECTED - Skipping PhonePe verification');
      }

      // 更严格地检查交易是否已存在
      const existingPurchase = await this.packagePurchaseRepository.findOne({
        where: {paymentNo: paymentData.transactionId}
      });

      if (existingPurchase) {
        console.log('Transaction already exists:', paymentData.transactionId);

        // 对于演示模式，返回现有购买记录而不是错误
        if (isDemoMode) {
          console.log('Demo mode: Returning existing purchase');
          return existingPurchase;
        }

        // 对于真实支付，返回错误
        throw new HttpErrors.BadRequest('Transaction already processed');
      }

      // 检查同一用户是否在短时间内购买了相同的套餐
      // 这可以防止由于网络延迟等原因导致的重复提交
      const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
      const recentPurchase = await this.packagePurchaseRepository.findOne({
        where: {
          and: [
            {fkBuyerIdSellerId: paymentData.userId},
            {fkPackageId: paymentData.packageId},
            {createdDate: {gt: fiveMinutesAgo.toISOString()}}
          ]
        }
      });

      if (recentPurchase) {
        console.log('Recent similar purchase found:', recentPurchase.packagePurchaseId);

        // 对于演示模式，返回最近的购买记录
        if (isDemoMode) {
          console.log('Demo mode: Returning recent purchase');
          return recentPurchase;
        }

        // 对于真实支付，返回错误
        throw new HttpErrors.BadRequest('A similar purchase was made recently. Please wait before trying again.');
      }

      // 只有在非演示模式下才验证 PhonePe
      if (!isDemoMode) {
        console.log('Verifying with PhonePe API...');
        const paymentStatus = await this.verifyPhonePePayment(paymentData.transactionId);

        console.log('PhonePe Verification Result:', paymentStatus);

        if (!paymentStatus.success) {
          throw new HttpErrors.BadRequest(
            `Payment verification failed: ${paymentStatus.error || 'Unknown error'}`,
          );
        }

        if (paymentStatus.status !== 'COMPLETED' && paymentStatus.status !== 'SUCCESS') {
          throw new HttpErrors.BadRequest(
            `Payment not completed. Status: ${paymentStatus.status}`,
          );
        }

        // 验证真实支付的金额
        const expectedAmount = Math.round(paymentData.amount * 100);
        const actualAmount = paymentStatus.amount;

        if (Math.abs(expectedAmount - actualAmount) > 1) {
          throw new HttpErrors.BadRequest(
            `Amount mismatch. Expected: ₹${paymentData.amount}, Got: ₹${actualAmount / 100}`,
          );
        }
      } else {
        console.log('✅ Demo mode: Skipping PhonePe verification');
      }

      // 计算日期
      const currentDate = new Date();
      const packageEndDate = new Date();
      packageEndDate.setDate(currentDate.getDate() + (paymentData.packageDuration ?? 30));

      console.log('Creating package purchase record...');

      // 创建套餐购买记录
      const packagePurchase = await this.packagePurchaseRepository.create({
        fkPackageId: paymentData.packageId,
        fkBuyerIdSellerId: paymentData.userId,
        fkUsertypeId: paymentData.usertypeId ?? 1,
        date: currentDate.toISOString().split('T')[0],
        time: currentDate.toTimeString().split(' ')[0],
        paymentFag: isDemoMode ? 0 : 1, // 0 表示演示，1 表示 PhonePe
        paymentNo: paymentData.transactionId,
        paymentAmount: paymentData.amount,
        propertyVisit: paymentData.propertyVisit ?? 0,
        propertyAddToCart: paymentData.propertyAddToCart ?? 0,
        packageEndDate: packageEndDate.toISOString().split('T')[0],
        isDefault: 0,
        isOn: 1,
        isActive: 1,
        createdDate: currentDate.toISOString(),
        createdBy: paymentData.userId,
        lastChanged: currentDate.toISOString(),
      });

      console.log('✅ Package purchase created:', packagePurchase.packagePurchaseId);

      if (isDemoMode) {
        console.log('⚠️ DEMO PURCHASE - Payment flag set to 0');
      }

      return packagePurchase;
    } catch (error) {
      console.error('=== Backend: Package Purchase Error ===');
      console.error('Error:', error);

      if (error instanceof HttpErrors.HttpError) {
        throw error;
      }

      throw new HttpErrors.InternalServerError(
        `Failed to create package purchase: ${error.message}`,
      );
    }
  }

  /**
   * PhonePe callback endpoint
   */
  @post('/api/phonepe/callback')
  @response(200, {
    description: 'PhonePe payment callback',
    content: {'application/json': {schema: {type: 'object'}}},
  })
  async handleCallback(): Promise<object> {
    try {
      const body = this.request.body;
      console.log('=== PhonePe Callback Received ===');
      console.log('Callback Body:', JSON.stringify(body, null, 2));

      // Decode base64 response if present
      if (body && body.response) {
        try {
          const decodedResponse = Buffer.from(body.response, 'base64').toString('utf-8');
          console.log('Decoded Response:', decodedResponse);
          const responseData = JSON.parse(decodedResponse);
          console.log('Response Data:', responseData);
        } catch (decodeError) {
          console.error('Failed to decode response:', decodeError);
        }
      }

      return {success: true, message: 'Callback received and logged'};
    } catch (error) {
      console.error('=== Callback Error ===');
      console.error('Error:', error);
      return {success: false, message: 'Callback processing failed'};
    }
  }

  /**
   * Helper method to verify payment with PhonePe API
   */
  private async verifyPhonePePayment(transactionId: string): Promise<any> {
    try {
      const crypto = require('crypto');
      const axios = require('axios');

      console.log('Verifying transaction:', transactionId);

      // Create checksum
      const checksumString = `/pg/v1/status/${PHONEPE_CONFIG.merchantId}/${transactionId}${PHONEPE_CONFIG.saltKey}`;
      const sha256Hash = crypto
        .createHash('sha256')
        .update(checksumString)
        .digest('hex');
      const checksum = `${sha256Hash}###${PHONEPE_CONFIG.saltIndex}`;

      console.log('Checksum String:', checksumString);
      console.log('Checksum:', checksum);

      // Make API request
      const url = `${PHONEPE_CONFIG.apiEndpoint}/pg/v1/status/${PHONEPE_CONFIG.merchantId}/${transactionId}`;
      console.log('API URL:', url);

      const response = await axios.get(url, {
        headers: {
          'Content-Type': 'application/json',
          'X-VERIFY': checksum,
          'X-MERCHANT-ID': PHONEPE_CONFIG.merchantId,
          accept: 'application/json',
        },
      });

      console.log('PhonePe API Response Status:', response.status);
      console.log('PhonePe API Response Data:', JSON.stringify(response.data, null, 2));

      if (response.data.success && response.data.code === 'PAYMENT_SUCCESS') {
        return {
          success: true,
          status: 'COMPLETED',
          amount: response.data.data.amount, // Already in paise
          transactionId: response.data.data.transactionId,
          merchantTransactionId: response.data.data.merchantTransactionId,
          paymentInstrument: response.data.data.paymentInstrument,
        };
      } else if (
        response.data.code === 'PAYMENT_ERROR' ||
        response.data.code === 'PAYMENT_DECLINED'
      ) {
        return {
          success: false,
          status: 'FAILED',
          error: response.data.message || 'Payment failed',
        };
      } else if (response.data.code === 'PAYMENT_PENDING') {
        return {
          success: false,
          status: 'PENDING',
          error: 'Payment is pending',
        };
      } else {
        return {
          success: false,
          status: 'UNKNOWN',
          error: response.data.message || 'Unknown payment status',
        };
      }
    } catch (error: any) {
      console.error('=== PhonePe API Error ===');
      console.error('Error:', error.message);

      if (error.response) {
        console.error('Response Status:', error.response.status);
        console.error('Response Data:', JSON.stringify(error.response.data, null, 2));
      }

      return {
        success: false,
        status: 'ERROR',
        error: error.response?.data?.message || error.message,
      };
    }
  }

  // Standard CRUD operations below...

  @post('/package-purchases')
  @response(200, {
    description: 'PackagePurchase model instance',
    content: {'application/json': {schema: getModelSchemaRef(PackagePurchase)}},
  })
  async create(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(PackagePurchase, {
            title: 'NewPackagePurchase',
            exclude: ['packagePurchaseId'],
          }),
        },
      },
    })
    packagePurchase: Omit<PackagePurchase, 'packagePurchaseId'>,
  ): Promise<PackagePurchase> {
    return this.packagePurchaseRepository.create(packagePurchase);
  }

  @get('/package-purchases/count')
  @response(200, {
    description: 'PackagePurchase model count',
    content: {'application/json': {schema: CountSchema}},
  })
  async count(@param.where(PackagePurchase) where?: Where<PackagePurchase>): Promise<Count> {
    return this.packagePurchaseRepository.count(where);
  }

  @get('/package-purchases')
  @response(200, {
    description: 'Array of PackagePurchase model instances',
    content: {
      'application/json': {
        schema: {
          type: 'array',
          items: getModelSchemaRef(PackagePurchase, {includeRelations: true}),
        },
      },
    },
  })
  async find(
    @param.filter(PackagePurchase) filter?: Filter<PackagePurchase>,
  ): Promise<PackagePurchase[]> {
    return this.packagePurchaseRepository.find(filter);
  }

  @patch('/package-purchases')
  @response(200, {
    description: 'PackagePurchase PATCH success count',
    content: {'application/json': {schema: CountSchema}},
  })
  async updateAll(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(PackagePurchase, {partial: true}),
        },
      },
    })
    packagePurchase: PackagePurchase,
    @param.where(PackagePurchase) where?: Where<PackagePurchase>,
  ): Promise<Count> {
    return this.packagePurchaseRepository.updateAll(packagePurchase, where);
  }

  @get('/package-purchases/{id}')
  @response(200, {
    description: 'PackagePurchase model instance',
    content: {
      'application/json': {
        schema: getModelSchemaRef(PackagePurchase, {includeRelations: true}),
      },
    },
  })
  async findById(
    @param.path.number('id') id: number,
    @param.filter(PackagePurchase, {exclude: 'where'})
    filter?: FilterExcludingWhere<PackagePurchase>,
  ): Promise<PackagePurchase> {
    return this.packagePurchaseRepository.findById(id, filter);
  }

  @patch('/package-purchases/{id}')
  @response(204, {
    description: 'PackagePurchase PATCH success',
  })
  async updateById(
    @param.path.number('id') id: number,
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(PackagePurchase, {partial: true}),
        },
      },
    })
    packagePurchase: PackagePurchase,
  ): Promise<void> {
    await this.packagePurchaseRepository.updateById(id, packagePurchase);
  }

  @put('/package-purchases/{id}')
  @response(204, {
    description: 'PackagePurchase PUT success',
  })
  async replaceById(
    @param.path.number('id') id: number,
    @requestBody() packagePurchase: PackagePurchase,
  ): Promise<void> {
    await this.packagePurchaseRepository.replaceById(id, packagePurchase);
  }

  @del('/package-purchases/{id}')
  @response(204, {
    description: 'PackagePurchase DELETE success',
  })
  async deleteById(@param.path.number('id') id: number): Promise<void> {
    await this.packagePurchaseRepository.deleteById(id);
  }

  @get('/package-purchases/user/{userId}')
  @response(200, {
    description: 'Get package purchases for logged-in user',
    content: {
      'application/json': {
        schema: {
          type: 'array',
          items: getModelSchemaRef(PackagePurchase, {includeRelations: true}),
        },
      },
    },
  })
  async getPackagesByUser(
    @param.path.number('userId') userId: number,
  ): Promise<PackagePurchase[]> {
    return this.packagePurchaseRepository.find({
      where: {
        fkBuyerIdSellerId: userId,
        isActive: 1,          // only active packages
        deletedDate: null,    // ignore deleted
      },
      order: ['packagePurchaseId DESC'],
      include: [{relation: 'package'}], // include package details
    });
  }

}
