import * as functions from "firebase-functions";
import { getUserByDoctorId } from "./user-service";
import { increaseWalletBalance } from "./user-wallet-functions";
import { OrderStatus } from "./collections";
const admin = require("firebase-admin");
const db = admin.firestore();
const { firestore } = require("firebase-admin");
const notificationFunction = require("./notification-function");

export const timeslotAdded = functions.firestore
  .document("/DoctorTimeslot/{doctorTimeslotId}")
  .onCreate((snapshot, context) => {
    //snapshot.ref.update({ balance: 0 });
    const newValue = snapshot.data();
    if (newValue.repeat === "weekly on the same day and time") {
      console.log("weekly on the same day and time");
    }
    return Promise.resolve();
  });

export async function refundTimeslot(timeSlotId: string, refundId: string) {
  try {
    var timeslotSnapshot = await db
      .collection("DoctorTimeslot")
      .doc(timeSlotId)
      .get();
    if (
      timeslotSnapshot.data().available == false &&
      timeslotSnapshot.data().charged == true
    ) {
      let refundObject = {
        status: "refund",
        refundId: refundId,
      };
      //update Timeslot Status
      await timeslotSnapshot.ref.update(refundObject);
      //update Order collection status
      let orderSnapshot = await db
        .collection("Order")
        .where("timeSlotId", "==", timeSlotId)
        .get();
      let order = orderSnapshot.docs[0];
      order.ref.update(refundObject);

      console.log("update timeslot refund success");
    } else {
      throw "timeslot available, not purchase yet";
    }
  } catch (error) {
    throw error;
  }
}

/** this function will reschedule the timeslot that has been purchase
 * this function get callen in @ClientApp
 */
export const rescheduleTimeslot = functions.https.onCall(
  async (request, response) => {
    var timeSlotNow = await db
      .collection("DoctorTimeslot")
      .doc(request.timeSlotIdNow)
      .get();

    var timeSlotChanged = await db
      .collection("DoctorTimeslot")
      .doc(request.timeslotChanged)
      .get();
    console.log("timeslot now data : " + JSON.stringify(timeSlotNow.data()));

    if (timeSlotNow.data().status == "complete") {
      throw new functions.https.HttpsError(
        "unknown",
        "The appointment has been marked as complete, and cannot be rescheduled"
      );
    }
    if (timeSlotNow.data().status == "refund") {
      throw new functions.https.HttpsError(
        "unknown",
        "The appointment has been refunded, and cannot be rescheduled"
      );
    }
    if (timeSlotChanged.data().available == false) {
      throw new functions.https.HttpsError(
        "unknown",
        "The selected timeslot is no longer available"
      );
    }
    if (timeSlotNow.data().pastTimeSlot) {
      throw new functions.https.HttpsError(
        "unknown",
        "The appointment has been rescheduled once, and cannot be rescheduled again"
      );
    }

    //Update Timeslot
    await timeSlotNow.ref.update({
      timeSlot: timeSlotChanged.data().timeSlot,
      price: timeSlotChanged.data().price,
      duration: timeSlotChanged.data().duration,
      pastTimeSlot: timeSlotNow.data().timeSlot,
      pastDuration: timeSlotNow.data().duration,
      pastPrice: timeSlotNow.data().price,
    });
    await timeSlotChanged.ref.update({
      available: false,
      timseSlotChanged: true,
      timeSlotChangedTo: timeSlotNow.id,
    });
    var timeSlotNow2 = await db
      .collection("DoctorTimeslot")
      .doc(request.timeSlotIdNow)
      .get();
    var timeSlotChanged2 = await db
      .collection("DoctorTimeslot")
      .doc(request.timeSlotIdNow)
      .get();
    console.log("successfully reschedule appointment");
    console.log(
      "timeslot now data after change : " + JSON.stringify(timeSlotNow2.data())
    );
    console.log(
      "timeslot changed data after change : " +
        JSON.stringify(timeSlotChanged2.data())
    );
    await notificationFunction.rescheduleTimeslotNotification(
      timeSlotNow.data().doctorId
    );
  }
);

// user confirm consultation complete, give money to doctor & create transaction
export const confirmConsultation = functions.https.onCall(async (request) => {
  try {
    // Start a Firestore batch to ensure atomic updates
    const batch = db.batch();

    // Get the order first to check status
    const order = await db.collection("Order").doc(request.orderId).get();
    const orderData = order.data();

    if (!orderData) {
      throw new functions.https.HttpsError("not-found", "Order not found");
    }

    if (orderData.status !== OrderStatus.pay) {
      throw new functions.https.HttpsError(
        "failed-precondition",
        "Order must be in payment_success status"
      );
    }

    //get doctor timeslot
    let timeSlot = await db
      .collection("DoctorTimeslot")
      .doc(orderData.timeSlotId)
      .get();

    if (!timeSlot.exists) {
      throw new functions.https.HttpsError("not-found", "TimeSlot not found");
    }

    const timeSlotData = timeSlot.data();
    const doctorId = timeSlotData?.doctorId;

    //get user id by doctor and increase their wallet balance
    const doctorUser = await getUserByDoctorId(doctorId);
    const userId = doctorUser.uid;
    console.log("doctor id : " + doctorId);
    console.log("doctor user id : " + userId);

    const completedAt = firestore.Timestamp.fromDate(new Date());

    // Prepare all updates in batch
    // 1. Update order status
    batch.update(order.ref, {
      status: "success",
      completedAt: completedAt,
    });

    // 2. Update timeslot status
    batch.update(timeSlot.ref, {
      status: "complete",
      completedAt: completedAt,
    });

    // 3. Create transaction document
    const transactionRef = db.collection("Transaction").doc();
    batch.set(transactionRef, {
      userId: userId,
      amount: orderData.amount,
      status: "complete",
      type: "payment",
      timeSlot: orderData.timeSlotId,
      createdAt: completedAt,
    });

    // Commit all updates atomically
    await batch.commit();
    console.log("Batch updates committed successfully");

    // After successful batch commit, update wallet balance
    await increaseWalletBalance(userId, orderData.amount);
    console.log("increase wallet balance success");

    // Send completion notification to doctor
    const notificationTitle = "Consultation Completed";
    const notificationMessage = `Consultation completed and payment of ${
      orderData.amount
    } has been processed for your session on ${new Date(
      timeSlotData.timeSlot.toDate()
    ).toLocaleString()}`;

    await notificationFunction.sendNotification(
      doctorUser.token,
      notificationTitle,
      notificationMessage,
      {
        type: "consultation_completed",
        timeSlotId: orderData.timeSlotId,
        orderId: request.orderId,
        amount: orderData.amount,
        completedAt: completedAt.toDate().toISOString(),
      }
    );
    console.log("Completion notification sent to doctor");

    return { success: true };
  } catch (error) {
    console.error("Error in confirmConsultation:", error);
    throw error;
  }
});
