import { Injectable } from "@nestjs/common";
import { CreateNewBillingDto } from "./dto/create-new-billing.dto";
import { UpdateNewBillingDto } from "./dto/update-new-billing.dto";
import { DataSource } from "typeorm";
import axios from "axios";
import { phrupdatepaymentdetails } from "./entities/new-billing.entity";
import { awsConfig } from "src/aws.config";
import invoiceHTML from "./template-html";

@Injectable()
export class NewBillingService {
  constructor(private readonly connection: DataSource) { }

  async phrfindAll(
    hospital_id: number,
    aayush_unique_id: string,
    payment_module: string,
    bill_type: string,
    limit: number,
    page: number,
    search_text?: string
  ) {
    try {
      const [getBaseURL] = await this.connection.query(
        `select phr_api_base_url from hospitals where plenome_id = ?`,
        [hospital_id]
      );
      let apiURL = `${getBaseURL.phr_api_base_url}/new-billing/phr-billing-summary-bills?aayush_unique_id=${aayush_unique_id}&limit=${limit}&page=${page}`;
      console.log(apiURL, "apiURL");

      if (payment_module) {
        apiURL += `&payment_module=${payment_module}`;
      }
      if (bill_type) {
        apiURL += `&bill_type=${bill_type}`;
      }
      if (search_text) {
        apiURL += `&search_text=${search_text}`;
      }

      const getfindall = await axios.get(apiURL);
      return getfindall.data;
    } catch (error) {
      throw new Error(error);
    }
  }

  async findtransactiondetails(
    hospital_id: number,
    aayush_unique_id: string,
    payment_module: string,
    limit: number,
    page: number
  ) {
    try {
      const [getBaseURL] = await this.connection.query(
        `select phr_api_base_url from hospitals where plenome_id = ?`,
        [hospital_id]
      );
      let apiURL = `${getBaseURL.phr_api_base_url}/new-billing/phr-transaction-list?aayush_unique_id=${aayush_unique_id}&limit=${limit}&page=${page}`;
      if (payment_module) {
        apiURL += `&payment_module=${payment_module}`;
      }

      const getfindall = await axios.get(apiURL);
      return getfindall.data;
    } catch (error) {
      throw new Error(error);
    }
  }

  async phr_patient_wallet(aayush_unique_id: string) {
    const [patients] = await this.connection.query(
      `SELECT id, mobileno FROM patients WHERE aayush_unique_id = ?`,
      [aayush_unique_id]
    );
    console.log(patients, "patients");

    const existing_user = patients; // get first result

    if (!existing_user) {
      return {
        status: "failed",
        status_code: 400,
        message: "No user found",
      };
    }

    // Now get user_id from `users`
    const [users] = await this.connection.query(
      `SELECT id FROM users WHERE username = ?`,
      ["91" + existing_user.mobileno]
    );

    const user = users;

    if (!user) {
      return {
        status: "failed",
        status_code: 400,
        message: "No user found in users table",
      };
    }

    // Fetch coin value (optional step)
    const [coin_values] = await this.connection.query(
      `SELECT * FROM coin_value ORDER BY created_at DESC LIMIT 1`
    );
    const value_per_coin = coin_values;

    // Now fetch aayush coins
    const [coins] = await this.connection.query(
      `SELECT COALESCE(SUM(total_coins_remaining), 0) AS coins_remaining 
   FROM aayush_coins 
   WHERE user_id = ? 
     AND coins_usage <> 'fully_used'  
     AND is_expired = 0`,
      [user.id]
    );
    console.log(coins, "coins");

    const coins_remaining = coins?.coins_remaining || 0;

    if (coins_remaining === 0) {
      return {
        status: "failed",
        status_code: 201,
        message: "No Aayush coins available for the patient",
      };
    }

    return [
      {
        status: "success",
        coins_remaining,
        value_per_coin,
      },
    ];
  }

  async coins_used(
    hospital_id: number,
    aayush_unique_id: string,
    coins_used: number
  ) {
    try {
      const [getBaseURL] = await this.connection.query(
        `select phr_api_base_url from hospitals where plenome_id = ?`,
        [hospital_id]
      );
      let apiURL = `${getBaseURL.phr_api_base_url}/new-billing/phr-coins-used?aayush_unique_id=${aayush_unique_id}&coins_used= ${coins_used}`;
      const getfindall = await axios.post(apiURL);
      return getfindall.data;
    } catch (error) {
      console.log(error, "err");

      throw new Error(error);
    }
  }

  async add_overall_charges(
    aayush_unique_id: string,
    hospital_id: number,
    body: any
  ) {
    try {
      const [getBaseURL] = await this.connection.query(
        `select phr_api_base_url from hospitals where plenome_id = ?`,
        [hospital_id]
      );
      let apiURL = `${getBaseURL.phr_api_base_url}/new-billing/add-in-overallcharge?aayush_unique_id=${aayush_unique_id}&hospital_id=${hospital_id}`;

      const getfindall = await axios.post(apiURL, body);
      return getfindall.data;
    } catch (error) {
      console.log(error, "err");

      throw new Error(error);
    }
  }

  async update_overall_charges(
    aayush_unique_id: string,
    hospital_id: number,
    body: any
  ) {
    try {
      const [getBaseURL] = await this.connection.query(
        `select phr_api_base_url from hospitals where plenome_id = ?`,
        [hospital_id]
      );
      let apiURL = `${getBaseURL.phr_api_base_url}/new-billing/update-in-overallcharge?aayush_unique_id=${aayush_unique_id}&hospital_id=${hospital_id}`;
      const getfindall = await axios.post(apiURL, body);
      return getfindall.data;
    } catch (error) {
      console.log(error, "err");

      throw new Error(error);
    }
  }

  async phr_wallet_credit_transactions(
    aayush_unique_id: string,
    transaction_status: string
  ) {
    const [patient_data] = await this.connection.query(
      `select id, mobileno from patients where aayush_unique_id = ?`,
      [aayush_unique_id]
    );
    if (!patient_data?.mobileno) {
      return {
        status: "failed",
        status_code: 500,
        message: "Enter valid aayush_unique_id",
      };
    }
    let num = patient_data.mobileno;

    if (num.length === 10) {
      num = `91${num}`;
    }

    const [user_id] = await this.connection.query(
      `select id from users where username = ?`,
      [num]
    );
    console.log(user_id, 1);

    const [coin_amt] = await this.connection.query(
      `select * from coin_value order by created_at desc limit 1`
    );

    const coin_value = await coin_amt.coin_amount;

    const debit_transaction = await this.connection.query(
      `
  SELECT 
      id,
      payment_date,
      "Wallet Usage",
      (wallet_paid_amount / ?) AS coins_used
  FROM transactions
  WHERE patient_id = ?
    AND wallet_paid_amount > 0

  UNION ALL

  SELECT 
      id,
      payment_date,
      "Temp Appointment Wallet Usage",
      (temp_wallet_paid_amount / ?) AS coins_used
  FROM transactions
  WHERE patient_id = ?
    AND temp_wallet_paid_amount > 0
  `,
      [coin_value, patient_data.id, coin_value, patient_data.id]
    );

    const user_aayush_coins = await this.connection.query(
      `select total_coins_issued, created_at as issued_date, module from aayush_coins where user_id = ${user_id.id}`
    );
    if (transaction_status == "credited") {
      return {
        status: "success",
        status_code: 200,
        message: "data fetched successfully",
        credited_coins: user_aayush_coins,
      };
    }
    if (transaction_status == "debited") {
      return {
        status: "success",
        status_code: 200,
        message: "data fetched successfully",
        debited_coins: debit_transaction,
      };
    }
    return {
      status: "success",
      status_code: 200,
      message: "data fetched successfully",
      debited_coins: debit_transaction,
      credited_coins: user_aayush_coins,
    };
  }

  async phr_update_paymentdata(
    transaction_id: string,
    hospital_id: number,
    Entity: phrupdatepaymentdetails
  ) {
    try {
      const [getBaseURL] = await this.connection.query(
        `select phr_api_base_url from hospitals where plenome_id = ?`,
        [hospital_id]
      );
      let apiURL = `${getBaseURL.phr_api_base_url}/phr-appointment/update/paymentdata?transaction_id=${transaction_id}&hospital_id=${hospital_id}`;
      const getfindall = await axios.post(apiURL, Entity);
      return getfindall.data;
    } catch (error) {
      console.log(error, "err");

      throw new Error(error);
    }
  }

  // async invoice_data(hos_transaction_id: string, hospital_id: number) {
  //   try {
  //     const [getBaseURL] = await this.connection.query(
  //       `select phr_api_base_url from hospitals where plenome_id = ?`,
  //       [hospital_id]
  //     );
  //     let apiURL = `${getBaseURL.phr_api_base_url}/new-billing/get-transaction-details?hos_transaction_id=${hos_transaction_id}&hospital_id=${hospital_id}`;

  //     const getfindall = await axios.get(apiURL);
  //     return getfindall.data;
  //   } catch (error) {
  //     console.log(error, "err");

  //     throw new Error(error);
  //   }
  // }

  async invoice_data(hos_transaction_id: string, hospital_id: number) {
    try {
      const axios = require("axios");
      const puppeteer = require("puppeteer");
      const AWS = require("aws-sdk");

      const [getBaseURL] = await this.connection.query(
        `select * from hospitals where plenome_id = ?`,
        [hospital_id]
      );

      const apiURL = `${getBaseURL.phr_api_base_url}/new-billing/get-transaction-details?hos_transaction_id=${hos_transaction_id}&hospital_id=${hospital_id}`;

      const { data } = await axios.get(apiURL);
      data.data[0].hospital_details = getBaseURL;

      if (getBaseURL.logo) {
        const s3 = new AWS.S3({
          accessKeyId: awsConfig.accessKeyId,
          secretAccessKey: awsConfig.secretAccessKey,
          region: awsConfig.region,
        });

        const s3Object = await s3
          .getObject({
            Bucket: awsConfig.bucketName,
            Key: getBaseURL.logo,
          })
          .promise();

        let base64_logo: string | null = null;

        if (s3Object.Body) {
          const buffer = Buffer.isBuffer(s3Object.Body)
            ? s3Object.Body
            : Buffer.from(s3Object.Body as any);

          base64_logo = buffer.toString("base64");
          console.log(base64_logo, "base");
        }
        data.data[0].hospital_details = {
          ...data.data[0].hospital_details,
          logo_base64: base64_logo,
        };
      }

      const html = invoiceHTML(data);

      const browser = await puppeteer.launch({
        headless: "new",
        args: ["--no-sandbox", "--disable-setuid-sandbox"],
        executablePath: '/usr/bin/chromium-browser',
      });

      const page = await browser.newPage();
      await page.setContent(html, { waitUntil: "networkidle0" });

      const pdfBuffer = await page.pdf({
        format: "A4",
        printBackground: true,
        margin: {
          top: "10mm",
          bottom: "10mm",
          left: "10mm",
          right: "10mm",
        },
      });

      await browser.close();
      const base64 = Buffer.from(pdfBuffer).toString("base64");

      return {
        base64,
      };
    } catch (error) {
      console.error("Invoice PDF generation failed:", error);
      throw new Error("Invoice PDF generation failed");
    }
  }
}
