const User = require('../model/userModel')
const { body, validationResult } = require("express-validator");
const bcrypt = require("bcrypt");
const Mailer = require('../mail/mailer');
const { Cart, CartItem } = require('../cart/cart');
const instance = require("../razorpay/index.js");
const path = require('path');
const axios = require('axios');
const logs = require('../helper/systemlog');

// const cart = new Cart();
// let dbProducts = [];

exports.validateInput = (method) => {
    switch (method) {
        case "login":
            return [
                body('mobile', 'Mobile is Required').not().isEmpty(),
                body('password', 'Password should be minimum 8 characters').isLength({ min: 8 }),
            ]

        case "register":
            return [
                body('fullname', 'Fullname is Required').not().isEmpty(),
                body('email', 'Email is Required').not().isEmpty().isEmail(),
                body('mobile', 'Mobile Number is Required').not().isEmpty().isLength({ min: 10, max: 10 }),
                body('password', 'Password should be minimum 8 characters').isLength({ min: 8 }),
                body('c_password', 'Confirm Password not match password').custom((value, { req }) => value === req.body.password)
            ]

        case "contact":
            return [
                body('name', 'Name is Required').not().isEmpty(),
                body('email', 'Email is Required').not().isEmpty().isEmail(),
                body('mobile', 'Mobile Number is Required').not().isEmpty().isLength({ min: 10, max: 10 }),
                body('product', 'Product is Required').not().isEmpty(),
                body('message', 'Message is Required').not().isEmpty()
            ]

        case "profile":
            return [
                body('name', 'Fullname is Required').not().isEmpty(),
                body('email', 'Email is Required').not().isEmpty().isEmail(),
                body('dob', 'Date of Birth is Required').not().isEmpty(),
                body('gender', 'Gender is Required').not().isEmpty(),
            ]

        case "changepassword":
            return [
                body('password', 'Current Password should be minimum 8 characters').not().isEmpty().isLength({ min: 8 }),
                body('new_password', 'New Password should be minimum 8 characters').not().isEmpty().isLength({ min: 8 }),
                body('confirm_password', 'Confirm Password not match password').custom((value, { req }) => value === req.body.new_password)
            ]

        case "address":
            return [
                body('type', 'Address Type is Required').not().isEmpty(),
                body('name', 'Fullname is Required').not().isEmpty(),
                body('mobile', 'Mobile is Required').not().isEmpty(),
                body('address', 'Address is Required').not().isEmpty(),
                body('city', 'City is Required').not().isEmpty(),
                body('state', 'State is Required').not().isEmpty(),
                body('pincode', 'Pincode is Required').not().isEmpty(),
            ]

        case "forgotpassword":
            return [
                body('mobile', 'Mobile Number is Required').not().isEmpty().isLength({ min: 10, max: 10 }),
            ]

        case "updatePasswordVerification":
            return [
                body('new_password', 'Password is Required').not().isEmpty().isLength({ min: 8 }),
                body('conf_password', 'Confirm Password is Required').not().custom((value, { req }) => value === req.body.new_password),
                body('mobile', 'Mobile Number is Required').not().isEmpty().isLength({ min: 10, max: 10 }),
                body('verification_code', 'Verification Code is Required').not().isEmpty().isLength({ min: 4, max: 4 }),
            ]

        case "forgotPasswordVerification":
            return [
                body('mobile', 'Mobile Number is Required').not().isEmpty().isLength({ min: 10, max: 10 }),
                body('verification_code', 'Verification Code is Required').not().isEmpty().isLength({ min: 4, max: 4 }),
            ]

        case "addtocart":
            return [
                body('id', 'Product Id is Required').not().isEmpty(),
                body('title', 'Product Title is Required').not().isEmpty(),
                body('price', 'Product Price is Required').not().isEmpty(),
                body('quantity', 'Product Quantity is Required').not().isEmpty(),
                body('image', 'Product Image is Required').not().isEmpty(),
            ]
    }
}

// views start 
exports.home = async (req, res) => {
    const model = new User()
    let [ourProductsData] = await model.ourProducts()
    let [bestSellerProducts] = await model.bestSellerProducts()
    var ourProducts = [];
    var cart = req.session.cart
    ourProductsData.map((item, index) => {
        var inCart = cart ? cart.filter((ele) => item.id == ele.id) : []
        ourProducts[index] = item
        ourProducts[index].inCart = cart ? inCart.length != 0 : false
        ourProducts[index].quantity = inCart.length != 0 ? inCart[0].quantity : 0
    });
    var bestSeller = [];
    bestSellerProducts.map((item, index) => {
        var inCart = cart ? cart.filter((ele) => item.id == ele.id) : []
        bestSeller[index] = item
        bestSeller[index].inCart = cart ? inCart.length != 0 : false
        bestSeller[index].quantity = inCart.length != 0 ? inCart[0].quantity : 0
    });
    let data = {
        title: 'Darwin Pharmaceutical',
        session: req.session,
        page_name: 'home',
        ourProducts,
        bestSeller,
        cart,
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    return res.render('user/index', data);
}

exports.about = (req, res) => {
    let data = {
        title: 'Darwin Pharmaceutical',
        session: req.session,
        page_name: 'about',
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    return res.render('user/about-us', data)
}

exports.products = async (req, res) => {
    const param = req.params.category
    const model = new User()
    const [allProducts] = await model.getAllProductsByCategory(param)
    if (allProducts.length == 0) return res.redirect('/')
    var cart = req.session.cart
    let products = []
    allProducts.map((item, index) => {
        var inCart = cart ? cart.filter((ele) => item.id == ele.id) : []
        products[index] = item
        products[index].inCart = cart ? inCart.length != 0 : false
        products[index].quantity = inCart.length != 0 ? inCart[0].quantity : 0
    });
    let data = {
        title: 'Darwin Pharmaceutical',
        session: req.session,
        page_name: 'products',
        cartLength: req.session.cart ? req.session.cart.length : 0,
        products,
        productsLength: products.length
    };
    return res.render('user/product/products', data)
}

exports.contactus = (req, res) => {
    let data = {
        title: 'Darwin Pharmaceutical',
        session: req.session,
        page_name: 'contact',
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    return res.render('user/contact-us', data)
}

exports.login = (req, res) => {
    let data = {
        title: 'Login | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'auth',
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    return res.render('user/auth/login', data)
}

exports.forgotpassword = (req, res) => {
    let data = {
        title: 'Forgot Password | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'forgotpassword',
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    res.render('user/auth/forgot_password', data)
}

exports.profile = async (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')

    const model = new User()
    const [user] = await model.checkUserExistsByID(req.session.user_id)

    if (user.length === 0) return res.redirect('/logout')

    let data = {
        title: 'Profile | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'profile',
        cartLength: req.session.cart ? req.session.cart.length : 0,
        user: user[0]
    };
    res.render('user/profile/profile', data)
}

exports.changePassword = (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')
    let data = {
        title: 'Change Password | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'changepassword',
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    res.render('user/profile/change_password', data)
}

exports.address = async (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')
    const model = new User()

    const [row] = await model.address(req.session.user_id)
    let data = {
        title: 'Address | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'address',
        hasAddress: row.length > 0,
        address: row,
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    res.render('user/profile/address', data)
}

exports.orders = async (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')
    const model = new User()
    const [ordersData] = await model.getOrdersByUserID(req.session.user_id);
    let orders = []

    await Promise.all(ordersData.map(async (item, index) => {
        let products = []
        await Promise.all(JSON.parse(item.details).products.map(async (ele, i) => {
            const [singleProduct] = await model.getProductByPcode(ele.p_code)
            if (singleProduct.length !== 0)
                products.push({ ...ele, thumbnail: singleProduct[0].thumbnail, title: singleProduct[0].title })
        }))
        const details = JSON.parse(item.details)
        item.details = JSON.stringify({ ...details, products })
        let date = new Date(item.created_at)
        item.created_at = date.toLocaleDateString("en-US")
        orders.push(item)
    }))

    let data = {
        title: 'Orders | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'orders',
        orders,
        ordersLength: orders.length,
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    res.render('user/profile/orders', data)
}

exports.cart = (req, res) => {
    let data = {
        title: 'Cart | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'cart',
        cart: req.session.cart,
        cartLength: req.session.cart ? req.session.cart.length : 0,
        total: req.session.total ? req.session.total : 0,
        shipping: 0,
    };
    return res.render('user/cart/cart', data)
}

exports.details = async (req, res) => {
    const model = new User()
    const p_code = req.params.p_code
    const [details] = await model.getProductByPcode(p_code)
    const [relatedPro] = await model.getRelatedProducts()
    const cart = new Cart(req.session.cart ? req.session.cart : [])
    req.session.cart = cart.getCart()
    if (details.length === 0) return res.redirect('/')
    var inCart = await req.session.cart.filter((ele) => details[0].id == ele.id)
    details[0].inCart = req.session.cart ? inCart.length != 0 : false
    details[0].quantity = inCart.length != 0 ? inCart[0].quantity : 0
    if (details[0].display_price == 0)
        details[0].display_price = 1;
    details[0].percent = (100 - Math.round(details[0].selling_price * 100 / details[0].display_price));
    let relatedProducts = [];
    await relatedPro.forEach(async (element, index) => {
        var inCart = req.session.cart ? req.session.cart.filter((ele) => element.id == ele.id) : []
        relatedProducts[index] = element
        relatedProducts[index].inCart = req.session.cart ? inCart.length != 0 : false
        relatedProducts[index].quantity = inCart.length != 0 ? inCart[0].quantity : 0
    })
    let cartItem
    if (details[0].inCart) {
        const cart = req.session.cart
        const index = cart.findIndex(({ id }) => id == details[0].id);
        cartItem = cart[index]
    }
    let data = {
        title: `${details.title} | Darwin Pharmaceutical`,
        session: req.session,
        page_name: 'details',
        details: details[0],
        relatedProducts,
        relatedProductsLength: relatedProducts.length,
        cartLength: req.session.cart ? req.session.cart.length : 0,
        cartItem
    }
    return res.render('user/product/details', data)
}

exports.checkout = async (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')

    if (!req.session.cart) return res.redirect('/')

    const model = new User();
    const cart = new Cart(req.session.cart ? req.session.cart : [])
    let allCartItem = cart.getCart()
    let dbProducts = [];
    let total = 0
    for await (const element of allCartItem) {
        const [product] = await model.getProductByIDCheckout(element.id)
        if (product.length > 0) {
            product[0].quantity = element.quantity
            dbProducts.push(product[0])
            total += parseInt(product[0].selling_price) * parseInt(element.quantity)
        }
    }
    // get address
    let [address] = await model.address(req.session.user_id)
    // razorpay
    let createReceipt = (Math.random() + 1).toString(36).substring(7)
    let processing_fee = Math.round((total * 3) / 100)
    var options = {
        amount: (processing_fee + total) * 100,  // amount in the smallest currency unit
        currency: "INR",
        receipt: `order_${createReceipt}_id`,
        payment_capture: true,
    };

    const [user] = await model.checkUserExistsByID(req.session.user_id)
    if (user.length === 0) return res.redirect('/logout')
    const userObj = {
        name: user[0].fullname,
        contact: user[0].mobile,
        email: user[0].email
    }
    // set db products in session 
    req.session.dbProducts = dbProducts

    instance.orders.create(options, function (err, order) {
        if (err) return res.redirect("/checkout")
        logs(req.session.user_id, `Checkout Page - Razorpay Order - ${JSON.stringify(order)} - Cart - ${JSON.stringify(req.session.dbProducts)} - Processing Fee - ${processing_fee} - ProductTotal - ${total}`)
        let data = {
            title: 'Checkout | Darwin Pharmaceutical',
            session: req.session,
            page_name: 'checkout',
            cart: dbProducts,
            cartLength: dbProducts.length,
            total: options.amount / 100,
            processing_fee,
            shipping: 0,
            razorpay: order,
            user: userObj,
            address: address,
            addressLength: address.length
        };
        res.render('user/checkout/checkout', data)
    });
}

exports.success = async (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')
    const model = new User()

    const order_id = req.params.order_id

    const [row] = await model.getOrderByID(order_id, req.session.user_id)
    let data = {
        title: 'Payment Success | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'success',
        cartLength: req.session.cart ? req.session.cart.length : 0,
        data: row[0]
    };
    res.render('user/checkout/success', data)
}

exports.error = async (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')

    let data = {
        title: 'Payment Failed | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'error',
        cartLength: req.session.cart ? req.session.cart.length : 0
    };
    res.render('user/checkout/error', data)
}

exports.invoice = async (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')
    const model = new User()
    const order_id = req.params.order_id
    const user_id = req.session.user_id
    const [invoiceArray] = await model.invoice(order_id, user_id);
    let invoice = invoiceArray[0]
    let products = []
    await Promise.all(JSON.parse(invoiceArray[0].details).products.map(async (item, key) => {
        const [singleProduct] = await model.getProductByPcode(item.p_code);
        products.push({ ...item, title: singleProduct[0].title })
    }))
    let detailsParse = JSON.parse(invoiceArray[0].details)
    detailsParse.products = products
    invoice.details = JSON.stringify(detailsParse)
    let date = new Date(invoice.created_at)
    invoice.created_at = date.toLocaleDateString("en-US")
    // logo path 
    var img = `${req.protocol}://${req.get('host')}/images/logo.png`
    invoice.img = img
    let data = {
        title: 'Invoice | Darwin Pharmaceutical',
        session: req.session,
        page_name: 'error',
        cartLength: req.session.cart ? req.session.cart.length : 0,
        invoice
    };
    res.render('user/profile/invoice', data)
}
// views end

// functionality starts

exports.validateLogin = async (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    const { mobile, password } = req.body

    const user = new User()

    user.validateLogin(mobile).then(async ([row]) => {

        if (row.length == 0) {
            return res.json({ error: [{ msg: 'User not found' }] })
        }
        const validPassword = await bcrypt.compare(password, row[0].password);
        if (!validPassword) {
            return res.json({ error: [{ msg: 'Password is incorrect' }] })
        }
        req.session.user_logged_in = true
        req.session.user_id = row[0].id
        req.session.fullname = row[0].fullname
        req.session.email = row[0].email
        req.session.save()
        logs(req.session.user_id, 'Logged In')
        return res.json({ success: [{ msg: 'Login success' }] })

    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    })
}

exports.logout = (req, res) => {
    logs(req.session.user_id, 'Logged Out')
    req.session.destroy();
    res.clearCookie('connect.sid');
    return res.redirect('/');
}

exports.registerFunctionality = (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    const data = req.body

    const user = new User()

    user.checkUserExists(data.mobile).then(async ([row]) => {
        if (row.length > 0) {
            return res.json({ error: [{ msg: 'User Already Exists' }] })
        }

        const salt = await bcrypt.genSalt(10);
        data.password = await bcrypt.hash(data.password, salt);

        user.register(data).then(([row]) => {
            if (row.affectedRows === 1) {
                return res.json({ success: [{ msg: 'Registration successful' }] })
            } else {
                return res.json({ error: [{ msg: 'Please try again' }] })
            }
        }).catch(err => {
            return res.json({ error: [{ msg: 'Something went wrong' }] })
        })
    }).catch((err) => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    })
}

exports.contact = (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    const { name, email, mobile, product, message } = req.body

    const model = new User()

    model.contact(req.body).then(async ([row]) => {
        if (row.affectedRows === 1) {
            // Mail Data
            let receivers = [];
            process.env.mail_receiver.split(",").forEach(element => {
                receivers.push(element);
            });

            const mailData = {
                from: process.env.mail_email,  // sender address
                to: receivers,   // list of receivers
                subject: 'Pharmaceutical Product Enquiry',
                html: `Name : ${name} <br> Email : ${email} <br> Product : ${product} <br> Mobile : ${mobile} <br> Message : ${message} <br>`,
            };
            // Send Mail
            try {
                const mailer = new Mailer();
                await mailer.sendMail(mailData)
                return res.json({ success: [{ msg: 'Enquiry Sent Successfully' }] })
            } catch (error) {
                return res.json({ error: [{ msg: 'Please Try Again' }] })
            }
        } else {
            return res.json({ error: [{ msg: 'Please try again' }] })
        }
    }).catch((err) => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    })
}

exports.updateProfile = (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    if (!req.session.user_logged_in) return res.json({ error: [{ msg: 'Please Login in Again' }] })

    const model = new User()

    model.updateProfile(req.body, req.session.user_id).then(([row]) => {
        if (row.affectedRows === 1) {
            req.session.fullname = req.body.name
            logs(req.session.user_id, 'Profile Updated')
            return res.json({ success: [{ msg: 'Profile Updated Successfully' }] })
        } else {
            return res.json({ error: [{ msg: 'Please try again' }] })
        }
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    })
}

exports.changeExistingPassword = async (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    if (!req.session.user_logged_in) return res.json({ error: [{ msg: 'Please Login in Again' }] })

    const model = new User()

    let user_id = req.session.user_id
    let password = req.body.password

    model.checkUserExistsByID(user_id).then(async ([row]) => {
        if (row.length == 0) return res.json({ error: [{ msg: 'User not exists' }] })
        const validPassword = await bcrypt.compare(password, row[0].password);
        if (!validPassword) {
            return res.json({ error: [{ msg: 'Current Password is Incorrect' }] })
        }
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    });

    const salt = await bcrypt.genSalt(10);
    let newPassword = await bcrypt.hash(req.body.new_password, salt);

    model.changeExistingPassword(newPassword, user_id).then(([row]) => {
        if (row.affectedRows === 1) {
            req.session.destroy();
            logs(req.session.user_id, 'Password Changed')
            return res.json({ success: [{ msg: 'Password Changed Successfully' }] })
        } else {
            return res.json({ error: [{ msg: 'Please try again' }] })
        }
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    })
}

exports.addAddress = (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    if (!req.session.user_logged_in) return res.json({ error: [{ msg: 'Please Login in Again' }] })

    const model = new User()

    model.addAddress(req.body, req.session.user_id).then(([row]) => {
        if (row.affectedRows === 1) {
            return res.json({ success: [{ msg: 'Address Added Successfully' }] })
        } else {
            return res.json({ error: [{ msg: 'Please try again' }] })
        }
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    });
}

exports.updateAddress = (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    if (!req.session.user_logged_in) return res.json({ error: [{ msg: 'Please Login in Again' }] })

    const model = new User()

    model.updateAddress(req.body, req.session.user_id).then(([row]) => {
        if (row.affectedRows === 1) {
            logs(req.session.user_id, `Address Updated - Old Address -> ${JSON.stringify(req.body)}`)
            return res.json({ success: [{ msg: 'Address Updated Successfully' }] })
        } else {
            return res.json({ error: [{ msg: 'Please try again' }] })
        }
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    });
}

exports.deleteAddress = (req, res) => {
    const model = new User()

    if (!req.session.user_logged_in) return res.json({ error: [{ msg: 'Please Login in Again' }] })

    model.deleteAddress(req.body.id).then(([row]) => {
        if (row.affectedRows === 1) {
            logs(req.session.user_id, `Address Deleted - addressID -> ${req.body.id}`)
            return res.json({ success: [{ msg: 'Address Deleted Successfully' }] })
        } else {
            return res.json({ error: [{ msg: 'Please try again' }] })
        }
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    });
}

exports.forgotPasswordSendMail = async (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    const model = new User()

    let user = [];
    let mobile = req.body.mobile

    await model.checkUserExists(mobile).then(([row]) => {
        user = row;
    }).catch(err => {
        return res.json({ error: [{ msg: 'Please Try Again' }] })
    })

    if (user.length === 0) return res.json({ error: [{ msg: 'Mobile Number not found' }] })

    let verificationCode = Math.floor(1000 + Math.random() * 9999);

    model.saveVerificationCode(mobile, verificationCode).then(async ([row]) => {
        if (row.affectedRows === 1) {
            // Mail Data
            const mailData = {
                from: process.env.mail_email,  // sender address
                to: user[0].email,   // list of receivers
                subject: 'Pharmaceutical Verification Code',
                html: `
                Need to reset your password?
                <br>
                Use your verification code!
                <br>
                [${verificationCode}]
                <br>
                If you did not forget your password, you can ignore this email.
                `,
            };
            // Send Mail
            try {
                const mailer = new Mailer();
                await mailer.sendMail(mailData)
                return res.json({ success: [{ msg: 'Email Sent Successfully, Please check your email' }] })
            } catch (error) {
                return res.json({ error: [{ msg: 'Please Try Again' }] })
            }
        } else {
            return res.json({ error: [{ msg: 'Please try again' }] })
        }
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    })
}

exports.forgotPasswordVerification = (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    const model = new User()

    let mobile = req.body.mobile
    let verification_code = req.body.verification_code

    model.checkVerificationCode(mobile, verification_code).then(([row]) => {
        if (row.length === 0) return res.json({ error: [{ msg: 'Verification Code is Incorrect' }] })
        return res.json({ success: [{ msg: 'Verification Success' }] })
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    })
}

exports.updatePasswordVerification = async (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    const model = new User()

    let mobile = req.body.mobile
    let verification_code = req.body.verification_code

    const salt = await bcrypt.genSalt(10);
    const password = await bcrypt.hash(req.body.new_password, salt);

    const [response] = await model.updatePassword(mobile, verification_code, password)
    if (response.affectedRows === 1)
        return res.json({ success: [{ msg: 'Password Changed Successfully' }] })
    else
        return res.json({ error: [{ msg: 'Please Try Again' }] })
}

exports.addToCart = async (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    let id = req.body.id
    let title = req.body.title
    let price = req.body.price
    let quantity = parseInt(req.body.quantity)
    let image = req.body.image
    let type = req.body.type

    const item = new CartItem(id, title, price, quantity, image);
    const cart = new Cart(req.session.cart ? req.session.cart : []);

    if (type && type == 'buynow') {
        var getCart = await cart.buyNow(item);
    } else {
        var getCart = await cart.addToCart(item);
    }

    req.session.cart = getCart;
    req.session.noOfProducts = getCart.length;
    req.session.total = cart.total;

    req.session.save((err) => {
        if (err) {
            return res.json({ error: [{ msg: 'Please try again' }] })
        } else {
            return res.json({ success: [{ msg: 'Added to cart', data: req.session.noOfProducts }] })
        }
    })

}

exports.removeFromCart = async (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    let id = req.body.id
    let title = req.body.title
    let price = req.body.price
    let quantity = parseInt(req.body.quantity)
    let image = req.body.image

    const item = new CartItem(id, title, price, quantity, image);
    const cart = new Cart(req.session.cart ? req.session.cart : []);
    const getCart = await cart.removeFromCart(item);
    req.session.cart = getCart;
    req.session.noOfProducts = getCart.length;
    req.session.total = cart.total;
    req.session.save((err) => {
        if (err) {
            return res.json({ error: [{ msg: 'Please try again' }] })
        } else {
            return res.json({ success: [{ msg: 'Removed from cart', data: req.session.noOfProducts }] })
        }
    })
}

exports.removeCartQuantity = async (req, res) => {
    const errors = validationResult(req)

    if (!errors.isEmpty()) return res.json({ error: errors.errors })

    let id = req.body.id
    let title = req.body.title
    let price = req.body.price
    let quantity = parseInt(req.body.quantity)
    let image = req.body.image

    const item = new CartItem(id, title, price, quantity, image);
    const cart = new Cart(req.session.cart ? req.session.cart : []);
    const getCart = await cart.removeQuantityFromCart(item);
    req.session.cart = getCart
    req.session.noOfProducts = getCart.length;
    req.session.total = cart.total;
    req.session.save((err) => {
        if (err) {
            return res.json({ error: [{ msg: 'Please try again' }] })
        } else {
            return res.json({ success: [{ msg: 'Quantity Removed from cart', data: req.session.noOfProducts }] })
        }
    })
}

exports.clearCart = (req, res) => {
    const cart = new Cart(req.session.cart ? req.session.cart : []);
    cart.cartItems = [];
    cart.total = 0;
    req.session.cart = undefined
    req.session.total = undefined
    return res.json({ success: [{ msg: 'Cart Cleared' }] })
}

exports.validateOrder = (req, res) => {
    const razorpay_order_id = req.body.razorpay_order_id
    const razorpay_payment_id = req.body.razorpay_payment_id
    const razorpay_signature = req.body.razorpay_signature

    // verify payment
    let body = razorpay_order_id + "|" + razorpay_payment_id;

    var crypto = require("crypto");
    var expectedSignature = crypto.createHmac('sha256', process.env.razorpay_key_secret).update(body.toString()).digest('hex');
    var response = { error: [{ msg: 'Payment Not Verified' }] }
    if (expectedSignature === razorpay_signature)
        response = { success: [{ msg: 'Payment Verified' }] }

    return res.json(response);
}

const sendOrderEmail = async (email, order_id, user_id) => {
    const model = new User();
    const [order] = await model.getOrderByID(order_id, user_id)
    let details = JSON.parse(order[0].details)
    let count = details.products.length
    let price = 0
    let gst = 0
    details.products.forEach(element => {
        price += element.product_price
        gst += element.gst
    })
    let processing_fee = order[0].processing_fee
    let shipping_charges = order[0].shipping_charges
    let address = details.address
    let total = price + gst + processing_fee + shipping_charges
    let data = {
        count, price, gst, address, processing_fee, order_id, shipping_charges, total
    }
    const ejs = require('ejs')
    var filename = path.join(__dirname, '..', 'views', 'user', 'checkout', 'email.ejs')
    const html = await ejs.renderFile(filename, data);
    // Send Mail
    const mailData = {
        from: process.env.mail_email,  // sender address
        to: email,   // list of receivers
        subject: 'Pharmaceutical Order Placed Successfully',
        html,
    };
    // Send Mail
    try {
        const mailer = new Mailer();
        await mailer.sendMail(mailData)
    } catch (error) {
        console.log(error);
    }
}

exports.placeOrder = async (req, res) => {
    const razorpay_order_id = req.body.razorpay_order_id
    const razorpay_payment_id = req.body.razorpay_payment_id
    const model = new User()
    let details = {}
    let products = []
    let totalGst = 0
    let total = 0
    let dbProducts = req.session.dbProducts
    // make details product json
    for await (const element of dbProducts) {
        let productPrice = Math.round((element.selling_price * element.quantity) / (element.gst + 100) * 100)
        let productGst = Math.round((element.selling_price * element.quantity - productPrice))
        totalGst += productGst
        total += (element.selling_price * element.quantity)
        let productData = {
            p_code: element.p_code,
            quantity: element.quantity,
            selling_price: element.selling_price,
            product_price: productPrice,
            gst: Math.round((element.selling_price * element.quantity - productPrice)),
            status: 1,
        }
        products.push(productData)
    }
    // add product json to details array
    details['products'] = products;
    //fetch address
    let [address] = await model.addressByID(req.body.address)
    // add address json to details 
    details['address'] = address[0]
    // fetch payment details
    const payment = await instance.payments.fetch(razorpay_payment_id);
    // add payment json to details array
    details['payment'] = payment
    // check orderid in database 
    let order_id
    let orders = []
    do {
        order_id = `order_${Math.floor(Math.random() * (1000000000 - 9999999999 + 1) + 9999999999)}`
        let [dataOrders] = await model.checkOrderID(order_id)
        orders = dataOrders
    }
    while (orders.length != 0);
    const processing_fee = (total * 3) / 100
    const data = {
        razorpay_order_id: razorpay_order_id,
        order_id,
        user_id: req.session.user_id,
        details: JSON.stringify(details),
        shipping_charges: 0,
        gst: totalGst,
        processing_fee,
        final_price: total + processing_fee,
        created_at: new Date(),
        status: 1
    }
    // place order
    model.placeOrder(data).then(([row]) => {
        if (row.affectedRows === 1) {
            req.session.dbProducts = [];
            req.session.cart = undefined
            req.session.total = undefined
            sendOrderEmail(req.session.email, data.order_id, req.session.user_id)
            return res.json({ success: [{ msg: 'Order Placed Successfully' }], data: { order_id: data.order_id } })
        } else {
            return res.json({ error: [{ msg: 'Please try again' }] })
        }
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong. Please try again' }] })
    })
}

exports.invoiceDownload = async (req, res) => {
    if (!req.session.user_logged_in) return res.redirect('/auth')
    const model = new User()
    const order_id = req.params.order_id
    const user_id = req.session.user_id
    const [invoiceArray] = await model.invoice(order_id, user_id);
    let invoice = invoiceArray[0]
    let products = []
    await Promise.all(JSON.parse(invoiceArray[0].details).products.map(async (item, key) => {
        const [singleProduct] = await model.getProductByPcode(item.p_code);
        products.push({ ...item, title: singleProduct[0].title })
    }))
    let detailsParse = JSON.parse(invoiceArray[0].details)
    detailsParse.products = products
    invoice.details = JSON.stringify(detailsParse)
    let date = new Date(invoice.created_at)
    invoice.created_at = date.toLocaleDateString("en-US")
    // logo path 
    var img = `${req.protocol}://${req.get('host')}/images/logo.png`
    invoice.img = img
    let data = {
        invoice
    };
    let pdf = require("html-pdf");
    const ejs = require('ejs')
    var filename = path.join(__dirname, '..', 'views', 'user', 'profile', 'invoice.ejs')
    const html = await ejs.renderFile(filename, data);
    pdf.create(html, {}).toStream(function (err, stream) {
        if (err) {
            return res.json({ error: [{ msg: 'Something went wrong. Please try again', err }] })
        } else {
            // res.set('Content-type', 'application/pdf');
            stream.pipe(res)

            // return stream.pipe(fs.createWriteStream(`${order_id}.pdf`));
        }
    });
    // var pdf = await createPdf(filePath, data, order_id);
    // // res.setHeader('Content-Type', 'application/pdf');
    // console.log(pdf);
    // res.setHeader(
    //     "Content-Disposition",
    //     `inline; filename=${order_id}.pdf`
    // );
    // // res.send(pdf);
    // // res.type('pdf');
    // res.end(pdf, 'binary');
}

exports.getCartTotal = async (req, res) => {
    const cart = new Cart(req.session.cart ? req.session.cart : [])
    await cart.calculateTotal()
    var total = cart.total
    return res.json({ total })
}

exports.trackOrder = (req, res) => {
    let orderId = req.body.orderId
    let userId = req.session.user_id
    const model = new User();
    model.trackOrder(orderId, userId).then(async ([row]) => {
        if (row.tracking) {
            const trackingResponse = await axios.get(`https://crm.shipdelight.com/index.php/api/detailed_status/trackAwb?awb=${row.tracking}`);
            if (trackingResponse.data.data && trackingResponse.data.data.error) {
                return res.json({ error: [{ msg: trackingResponse.data.data.response.error_id }] })
            }
            return res.json({ success: [{ msg: 'Tracking Found', data: trackingResponse.data }] })
        } else
            return res.json({ error: [{ msg: 'Item not shipped yet.' }] })
    }).catch(err => {
        return res.json({ error: [{ msg: 'Something went wrong' }] })
    })

}