import { forwardRef, Inject, Injectable } from "@nestjs/common";
import { CreateRazorpayWebhookDto } from "./dto/create-razorpay-webhook.dto";
import { UpdateRazorpayWebhookDto } from "./dto/update-razorpay-webhook.dto";
import { RazorpayWebhook } from "./entities/razorpay-webhook.entity";
import { InjectModel } from "@nestjs/mongoose";
import { Model } from "mongoose";
import { DataSource } from "typeorm";
import { MqttService } from "src/mqtt.service";
const Razorpay = require("razorpay");

@Injectable()
export class RazorpayWebhookService {
  constructor(
    private readonly connection: DataSource,
    @InjectModel("RazorpayWebhook")
    private readonly ServiceModel: Model<RazorpayWebhook>,
    @Inject(forwardRef(() => MqttService))
    private readonly mqttService: MqttService
  ) {}

  async create(createRazorpayWebhookDto: any): Promise<RazorpayWebhook> {
    try {
      if (createRazorpayWebhookDto.event == "qr_code.credited") {
        const hos_id = createRazorpayWebhookDto.payload.qr_code.entity.id;
        if (hos_id == "qr_R6gWMuYMbJj5Fb") {
          try {
            let payment_id = createRazorpayWebhookDto.payload.payment.entity.id;
            const authHeader =
              "Basic " +
              Buffer.from(
                "rzp_live_E1TEgAPfjZ0OIQ" + ":" + "eSskg54N7Bulwusbu7dGEMNr"
              ).toString("base64");

            const response = await fetch(
              `https://api.razorpay.com/v1/payments/${payment_id}/transfers`,
              {
                method: "GET",
                headers: {
                  "content-type": "application/json",
                  Authorization: authHeader,
                },
              }
            );

            const data = await response.json();
            if (data.count <= 0) {
              const razorpay = new Razorpay({
                key_id: "rzp_live_E1TEgAPfjZ0OIQ",
                key_secret: "eSskg54N7Bulwusbu7dGEMNr",
              });

              const submerchantAccountId = "acc_Pf0MtpgdM6aUfd";
              const paymentDetails = await razorpay.payments.fetch(payment_id);
              let refndAmt;
              if (paymentDetails.amount) {
                if (paymentDetails.amount <= 100) {
                  refndAmt = Math.round(paymentDetails.amount);
                } else {
                  refndAmt = Math.round(
                    paymentDetails.amount - paymentDetails.amount * 0.052
                  );
                }
              }

              const transferPayload = {
                transfers: [
                  {
                    account: submerchantAccountId,
                    amount: refndAmt,
                    currency: "INR",
                    notes: {
                      name: "Gaurav Kumar",
                      roll_no: "IEC2011025",
                    },
                    linked_account_notes: ["roll_no"],
                    on_hold: false,
                  },
                ],
              };
              console.log("adfasdfadfadf", transferPayload);

              await razorpay.payments.transfer(payment_id, transferPayload);
            }
          } catch (error) {
            console.log(error, "errrorororo");
          }
        }

        const [qr_hospital_id] = await this.connection.query(
          `select hospital_id,id from hos_qr_codes where qr_code_id = ?`,
          [hos_id]
        );
        if (qr_hospital_id) {
          const response = new this.ServiceModel({
            hospital_id: qr_hospital_id.hospital_id,
            is_read: 0,
            JSON_response: createRazorpayWebhookDto,
            created_at: new Date(),
          });

          let a = await response.save();
          console.log(a, "asdf");

          let mqttResponse = {
            qr_code_id: createRazorpayWebhookDto.payload.qr_code.entity.id,
            amount: createRazorpayWebhookDto.payload.payment.entity.amount,
            payment_id: createRazorpayWebhookDto.payload.payment.entity.id,
            payment_reference_number:
              createRazorpayWebhookDto.payload.payment.entity.acquirer_data.rrn,
            hospital_id: qr_hospital_id.hospital_id,
            reference_number: a._id,
            upi_id: createRazorpayWebhookDto.payload.payment.entity.vpa,
          };
          this.mqttService.publish(
            `plenome/HMS/${qr_hospital_id.hospital_id}`,
            JSON.stringify(mqttResponse)
          );

          return a;
        }
      } else {
        const response = new this.ServiceModel({
          JSON_response: createRazorpayWebhookDto,
        });
        let a = await response.save();
        console.log(a, "asdf");

        return a;
      }
    } catch (error) {
      console.log(error, "err");
    }
  }

  async createqr(hospital_id: number) {
    const razorpay = new Razorpay({
      key_id: "rzp_live_E1TEgAPfjZ0OIQ",
      key_secret: "eSskg54N7Bulwusbu7dGEMNr",
    });
    const qrCode = await razorpay.qrCode.create({
      type: "upi_qr",
      name: "Hospital Billing QR",
      usage: "multiple_use",
      fixed_amount: false,
      description: "Payment for services",
    });

    const qr_table = await this.connection.query(`
  CREATE TABLE IF NOT EXISTS \`hos_qr_codes\` (
    \`id\` INT NOT NULL AUTO_INCREMENT,
    \`qr_code_id\` VARCHAR(255) NOT NULL,
    \`hospital_id\` INT NOT NULL,
    \`created_at\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (\`id\`)
  ) ENGINE=InnoDB;
`);

    const inserted_data = await this.connection.query(
      `insert into hos_qr_codes(qr_code_id, hospital_id) values (?, ?)`,
      [qrCode.id, hospital_id]
    );

    return {
      status: "success",
      status_code: 200,
      data: qrCode,
    };
  }

  async findUnread(
    hospital_id: number,
    limit: number,
    page: number,
    date?: string
  ) {
    const offset = limit * (page - 1);
    const query: any = {
      is_read: 0,
      hospital_id: hospital_id,
    };

    if (date && !isNaN(Date.parse(date))) {
      const start = new Date(`${date}T00:00:00.000Z`);
      const end = new Date(`${date}T00:00:00.000Z`);
      end.setUTCDate(end.getUTCDate() + 1);
      const startUnix = Math.floor(start.getTime() / 1000);
      const endUnix = Math.floor(end.getTime() / 1000);

      query["$or"] = [
        {
          created_at: {
            $gte: start,
            $lt: end,
          },
        },

        {
          "JSON_response.created_at": {
            $gte: startUnix,
            $lt: endUnix,
          },
        },
      ];
    }

    const [result, totalCount] = await Promise.all([
      this.ServiceModel.find(query, {
        hospital_id: true,
        "JSON_response.payload.payment.entity.amount": true,
        "JSON_response.payload.payment.entity.id": true,
        "JSON_response.payload.payment.entity.acquirer_data.rrn": true,
        "JSON_response.payload.qr_code.entity.id": true,
        "JSON_response.payload.payment.entity.vpa": true,
        created_at: true,
        _id: true,
      })
        .sort({ created_at: -1 })
        .skip(offset)
        .limit(limit)
        .exec(),

      this.ServiceModel.countDocuments(query),
    ]);

    const formattedResults = result.map((doc) => ({
      hospital_id: doc.hospital_id,

      amount: doc.JSON_response?.payload?.payment?.entity?.amount,

      payment_id: doc.JSON_response?.payload?.payment?.entity?.id,

      payment_reference_number:
        doc.JSON_response?.payload?.payment?.entity?.acquirer_data?.rrn,

      qr_code_id: doc.JSON_response?.payload?.qr_code?.entity?.id,

      reference_number: doc._id,

      date: doc.created_at,
      upi_id: doc.JSON_response?.payload?.payment?.entity?.vpa,
    }));

    return { read: formattedResults, count: totalCount };
  }

  async findRead(
    hospital_id: number,
    limit: number,
    page: number,
    date?: string,
    patient_id?: string,
    search?: string
  ) {
    const offset = limit * (page - 1);

    const query: any = {
      is_read: 1,

      hospital_id: hospital_id,
    };

    if (patient_id) {
      query["data.patient_id"] = patient_id;
    }

    if (search) {
      query["data.patient_name"] = { $regex: search, $options: "i" };
    }

    if (date && !isNaN(Date.parse(date))) {
      const start = new Date(`${date}T00:00:00.000Z`);
      const end = new Date(`${date}T00:00:00.000Z`);
      end.setUTCDate(end.getUTCDate() + 1);
      const startUnix = Math.floor(start.getTime() / 1000);
      const endUnix = Math.floor(end.getTime() / 1000);
      query["$or"] = [
        {
          created_at: {
            $gte: start,

            $lt: end,
          },
        },

        {
          "JSON_response.created_at": {
            $gte: startUnix,

            $lt: endUnix,
          },
        },
      ];
    }

    const [result, totalCount] = await Promise.all([
      this.ServiceModel.find(query, {
        hospital_id: true,
        "JSON_response.payload.payment.entity.amount": true,
        "JSON_response.payload.payment.entity.id": true,
        "JSON_response.payload.payment.entity.acquirer_data.rrn": true,
        "JSON_response.payload.qr_code.entity.id": true,
        "JSON_response.payload.payment.entity.vpa": true,

        created_at: true,
        data: true,
        _id: true,
      })
        .sort({ created_at: -1 })
        .skip(offset)
        .limit(limit)
        .exec(),

      this.ServiceModel.countDocuments(query),
    ]);
    console.log(totalCount, "totalcount");

    const formattedResults = result.map((doc) => ({
      hospital_id: doc.hospital_id,

      amount: doc.JSON_response?.payload?.payment?.entity?.amount,

      payment_id: doc.JSON_response?.payload?.payment?.entity?.id,

      payment_reference_number:
        doc.JSON_response?.payload?.payment?.entity?.acquirer_data?.rrn,

      qr_code_id: doc.JSON_response?.payload?.qr_code?.entity?.id,

      reference_number: doc._id,
      patient_id: doc.data?.patient_id,
      patient_name: doc.data?.patient_name,

      date: doc.created_at,
      data: doc.data,
      upi_id: doc.JSON_response?.payload?.payment?.entity?.vpa,
    }));

    return { read: formattedResults, count: totalCount };
  }

  async update(reference_id: string, data: any) {
    console.log(reference_id, "asdf");

    let a = await this.ServiceModel.findByIdAndUpdate(reference_id, {
      is_read: 1,
      data: data,
    });

    // Fetch updated document by ID
    let b = await this.ServiceModel.findById(reference_id);
    console.log(b, "pppp");

    return {
      status_code: 200,
      status: "success",
      message: "updated successfully",
    };
  }

  remove(id: number) {
    return `This action removes a #${id} razorpayWebhook`;
  }
}
