import envVars from "../Config/env-vars.js";
import push_notification from "../Config/push_notification.js";
import Booking from "../DB/Model/booking.modal.js";
import Transactions from "../DB/Model/payment/transactions.model.js";
import Service from "../DB/Model/service.modal.js";
import User from "../DB/Model/user.model.js";
import { createPaymentIntent } from "../Utils/Stripe/index.js";

import Stripe from "stripe";
const stripe = new Stripe(envVars.stripeSecretKey);
export const createBooking = async (req, res) => {
    try {
        const { serviceId, bookingDate } = req.body;
        const userId = req.user._id;

        const accepted_by = await Service.findById(serviceId).select("created_by price");

        if (!accepted_by || accepted_by.isDeleted) {
            return res.status(404).json({
                status: false,
                message: "Service not found",
            });
        }

        const newBooking = await Booking.create({
            serviceId,
            userId,
            bookingDate,
            accepted_by: accepted_by.created_by,
            status: "pending",
        });

        const session = await stripe.checkout.sessions.create({
            payment_method_types: ["card"],
            mode: "payment",
            line_items: [
                {
                    price_data: {
                        currency: "usd",
                        product_data: {
                            name: "Service Booking",
                            description: `Booking for service ${serviceId}`,
                        },
                        unit_amount: accepted_by.price * 100,
                    },
                    quantity: 1,
                },
            ],
            metadata: {
                booking_id: newBooking._id.toString(),
                user_id: userId.toString(),
                service_id: serviceId.toString(),
                price: accepted_by.price.toString(),
            },
            success_url: `${process.env.FRONTEND_URL}`,
            cancel_url: `${process.env.FRONTEND_URL}`,
        });

        try {
            const bookingUser = await User.findById(userId).select("full_name");
            const title = "📌 New Booking Request";
            const body = `${bookingUser?.full_name || "A user"} has requested a booking.`;
            const link = `/bookings/${newBooking._id}`;
            await push_notification("booking_request", title, body, link, accepted_by.created_by);
        } catch (notifyErr) {
            console.error("⚠️ Failed to send notification:", notifyErr.message);
        }

        return res.status(201).json({
            status: true,
            message: "Booking created successfully",
            data: {
                booking: newBooking,
                checkoutUrl: session.url,
            },
        });
    } catch (error) {
        console.error("🔥 Error creating booking:", error);
        return res.status(500).json({
            status: false,
            message: "Internal server error",
        });
    }
};

export const getAllBookingRequests = async (req, res) => {
    try {
        const userId = req.user._id
        const getAllRequest = await Booking.find({
            isPaid: true,
            $or: [
                { accepted_by: userId },
                { userId: userId },
            ]
        }).populate([{ path: "userId", populate: [{ path: "image" }] }, { path: "serviceId" }, { path: "accepted_by" }]);
        if (!getAllRequest) {
            return res.status(404).json({
                status: false,
                message: "No booking requests found",
            });
        }
        return res.status(200).json({
            status: true,
            message: "Booking requests retrieved successfully",
            data: getAllRequest
        });

    } catch (error) {
        return res.status(500).json({
            status: false,
            message: "Internal server error",
        })
    }
}

export const getAllMyBooking = async (req, res) => {
    try {
        const userId = req.user._id;
        const { status } = req.query; // "pending" | "in_progress" | "completed" | "rejected"

        // 🟢 Fetch all bookings where user is requester OR provider
        let filter = {
            $or: [
                { accepted_by: userId },
                { userId: userId },
            ]
        };

        // 🟢 Add status filter if provided
        if (status) {
            filter.status = status;
        }

        const bookings = await Booking.find(filter).populate([
            { path: "userId", populate: [{ path: "image" }] },
            { path: "serviceId" },
            { path: "accepted_by", populate: [{ path: "image" }] },
        ]);

        if (!bookings || bookings.length === 0) {
            return res.status(404).json({
                status: false,
                message: "No bookings found",
            });
        }

        return res.status(200).json({
            status: true,
            message: "Bookings retrieved successfully",
            count: bookings.length,
            data: bookings,
        });

    } catch (error) {
        console.error("❌ Error fetching bookings:", error);
        return res.status(500).json({
            status: false,
            message: "Internal server error",
        });
    }
};

export const updateStatus = async (req, res) => {
    try {
        const bookingId = req.params.bookingId;
        const { status } = req.body;

        const updatedBooking = await Booking.findByIdAndUpdate(
            bookingId,
            { status },
            { new: true }
        )
            .populate("userId", "full_name fcmToken")
            .populate("accepted_by", "full_name fcmToken")
            .populate("serviceId", "title");

        if (!updatedBooking) {
            return res.status(404).json({
                status: false,
                message: "Booking not found",
            });
        }

        // 🔄 Transaction update based on booking status
        const txn = await Transactions.findOne({ booking_id: bookingId });
        if (status === "accepted" && txn) {
            await Transactions.findByIdAndUpdate(txn._id, { status: "approved" });
        }

        if (status === "rejected" && txn) {
            try {
                // Stripe refund
                if (txn.payment_id) {
                    const payment = await Payment.findById(txn.payment_id);
                    if (payment?.payment_intent_id) {
                        await stripe.refunds.create({
                            payment_intent: payment.payment_intent_id,
                        });
                    }
                }
                await Transactions.findByIdAndUpdate(txn._id, { status: "refunded" });
            } catch (refundErr) {
                console.error("⚠️ Refund failed:", refundErr.message);
            }
        }

        // ✅ Notifications
        const serviceName = updatedBooking?.serviceId?.title || "Service";
        const requester = updatedBooking?.userId;
        const provider = updatedBooking?.accepted_by;
        const statusMessages = {
            pending: `Your booking for ${serviceName} is now pending.`,
            in_progress: `Your booking for ${serviceName} is now in progress.`,
            completed: `Your booking for ${serviceName} has been completed.`,
            rejected: `Your booking for ${serviceName} has been rejected.`,
            accepted: `Your booking for ${serviceName} has been accepted.`,
        };
        const messageText =
            statusMessages[status] || `Your booking for ${serviceName} is now ${status}.`;

        try {
            if (requester?._id) {
                await push_notification(
                    "booking_status",
                    "Booking Status Updated",
                    messageText,
                    `/bookings/${bookingId}`,
                    requester._id
                );
            }
            if (provider?._id) {
                await push_notification(
                    "booking_status",
                    "Booking Status Updated",
                    messageText,
                    `/bookings/${bookingId}`,
                    provider._id
                );
            }
        } catch (notifyErr) {
            console.error("⚠️ Failed to send booking status notification:", notifyErr.message);
        }

        return res.status(200).json({
            status: true,
            message: "Booking status updated successfully",
            data: updatedBooking,
        });
    } catch (error) {
        console.error("❌ Error updating booking status:", error);
        return res.status(500).json({
            status: false,
            message: "Internal server error",
        });
    }
};
