"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const cors_1 = __importDefault(require("cors"));
const dotenv_1 = __importDefault(require("dotenv"));
const nodemailer_1 = __importDefault(require("nodemailer"));
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
const bcryptjs_1 = __importDefault(require("bcryptjs"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const User_1 = require("./models/User");
const Inquiry_1 = require("./models/Inquiry");
const GalleryImage_1 = require("./models/GalleryImage");
const Review_1 = __importDefault(require("./models/Review"));
const Stat_1 = __importDefault(require("./models/Stat"));
const Blog_1 = __importDefault(require("./models/Blog"));
const Package_1 = __importDefault(require("./models/Package"));
const db_1 = __importDefault(require("./config/db"));
const auth_1 = require("./middleware/auth");
dotenv_1.default.config();
// Basic Express Server with CORS and Email Functionality for Contact Form
const app = (0, express_1.default)();
const PORT = process.env.PORT || 5000;
const EMAIL_USER = process.env.EMAIL_USER;
const EMAIL_PASS = process.env.EMAIL_PASS;
const RECEIVER_EMAIL = process.env.RECEIVER_EMAIL;
const JWT_SECRET = process.env.JWT_SECRET;
app.use((0, cors_1.default)());
app.use(express_1.default.json());
// Database Connection
(0, db_1.default)();
// Login Route
app.post("/api/admin/login", async (req, res) => {
    const { email, password } = req.body;
    try {
        const user = await User_1.User.findOne({ email }).select("+password");
        if (!user) {
            return res.status(401).json({ success: false, message: "Invalid credentials" });
        }
        const isMatch = await bcryptjs_1.default.compare(password, user.password);
        if (!isMatch) {
            return res.status(401).json({ success: false, message: "Invalid credentials" });
        }
        const token = jsonwebtoken_1.default.sign({ id: user._id }, JWT_SECRET, {
            expiresIn: "30d",
        });
        res.status(200).json({
            success: true,
            token,
            user: {
                id: user._id,
                email: user.email,
                role: user.role,
            },
        });
    }
    catch (error) {
        res.status(500).json({ success: false, message: "Server error" });
    }
});
// Email Transporter (Standard Gmail Config)
const transporter = nodemailer_1.default.createTransport({
    service: "gmail",
    auth: {
        user: EMAIL_USER,
        pass: EMAIL_PASS,
    },
});
// Inquiry Routes
app.get("/api/admin/inquiries", auth_1.protect, async (req, res) => {
    try {
        const inquiries = await Inquiry_1.Inquiry.find().sort({ createdAt: -1 });
        res.status(200).json({ success: true, count: inquiries.length, data: inquiries });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error fetching inquiries" });
    }
});
// Gallery Routes
app.get("/api/gallery", async (req, res) => {
    try {
        const images = await GalleryImage_1.GalleryImage.find().sort({ order: 1 });
        res.status(200).json({ success: true, data: images });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error fetching gallery" });
    }
});
app.get("/api/reviews", async (req, res) => {
    try {
        const reviews = await Review_1.default.find().sort({ order: 1 });
        res.status(200).json({ success: true, data: reviews });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error fetching reviews" });
    }
});
app.post("/api/admin/reviews", auth_1.protect, async (req, res) => {
    try {
        const { name, country, comment, rating, order } = req.body;
        const review = await Review_1.default.findOneAndUpdate({ order }, { name, country, comment, rating, order }, { upsert: true, new: true });
        res.status(200).json({ success: true, data: review });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error adding/updating review" });
    }
});
app.delete("/api/admin/reviews/:id", auth_1.protect, async (req, res) => {
    try {
        await Review_1.default.findByIdAndDelete(req.params.id);
        res.status(200).json({ success: true, message: "Review deleted" });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error deleting review" });
    }
});
// Statistics Routes
app.get("/api/stats", async (req, res) => {
    try {
        const stats = await Stat_1.default.find().sort({ order: 1 });
        res.status(200).json({ success: true, data: stats });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error fetching stats" });
    }
});
app.post("/api/admin/stats", auth_1.protect, async (req, res) => {
    try {
        const { label, value, order } = req.body;
        const stat = await Stat_1.default.findOneAndUpdate({ order }, { label, value, order }, { upsert: true, new: true });
        res.status(200).json({ success: true, data: stat });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error adding/updating stat" });
    }
});
// Blog Routes
app.get("/api/blogs", async (req, res) => {
    try {
        const blogs = await Blog_1.default.find().sort({ createdAt: -1 });
        res.status(200).json({ success: true, data: blogs });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error fetching blogs" });
    }
});
app.get("/api/blogs/:slug", async (req, res) => {
    try {
        const blog = await Blog_1.default.findOne({ slug: req.params.slug });
        if (!blog) {
            return res.status(404).json({ success: false, message: "Blog post not found" });
        }
        res.status(200).json({ success: true, data: blog });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error fetching blog post" });
    }
});
app.post("/api/admin/blogs", auth_1.protect, async (req, res) => {
    try {
        const { slug, image, date, title, excerpt, content } = req.body;
        const blog = await Blog_1.default.findOneAndUpdate({ slug }, { slug, image, date, title, excerpt, content }, { upsert: true, new: true });
        res.status(200).json({ success: true, data: blog });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error adding/updating blog" });
    }
});
app.delete("/api/admin/blogs/:id", auth_1.protect, async (req, res) => {
    try {
        await Blog_1.default.findByIdAndDelete(req.params.id);
        res.status(200).json({ success: true, message: "Blog deleted" });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error deleting blog" });
    }
});
// Package Routes
app.get("/api/packages", async (req, res) => {
    try {
        const packages = await Package_1.default.find().sort({ order: 1 });
        res.status(200).json({ success: true, data: packages });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error fetching packages" });
    }
});
app.post("/api/admin/packages", auth_1.protect, async (req, res) => {
    try {
        const { order, title, image, route, duration, price, difficulty, groupSize, highlights, includes, itinerary } = req.body;
        const pkg = await Package_1.default.findOneAndUpdate({ order }, { title, image, route, duration, price, difficulty, groupSize, highlights, includes, itinerary, order }, { upsert: true, new: true });
        res.status(200).json({ success: true, data: pkg });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error adding/updating package" });
    }
});
app.delete("/api/admin/packages/:id", auth_1.protect, async (req, res) => {
    try {
        const deletedPackage = await Package_1.default.findByIdAndDelete(req.params.id);
        if (!deletedPackage) {
            return res.status(404).json({ success: false, message: "Package not found" });
        }
        res.status(200).json({ success: true, message: "Package deleted" });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error deleting package" });
    }
});
app.post("/api/admin/gallery", auth_1.protect, async (req, res) => {
    try {
        const { url, order } = req.body;
        const image = await GalleryImage_1.GalleryImage.create({ url, order });
        res.status(201).json({ success: true, data: image });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error adding image" });
    }
});
app.patch("/api/admin/gallery/:id", auth_1.protect, async (req, res) => {
    try {
        const image = await GalleryImage_1.GalleryImage.findByIdAndUpdate(req.params.id, req.body, { new: true });
        res.status(200).json({ success: true, data: image });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error updating image" });
    }
});
app.delete("/api/admin/gallery/:id", auth_1.protect, async (req, res) => {
    try {
        await GalleryImage_1.GalleryImage.findByIdAndDelete(req.params.id);
        res.status(200).json({ success: true, message: "Image deleted" });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error deleting image" });
    }
});
app.patch("/api/admin/inquiries/:id", auth_1.protect, async (req, res) => {
    try {
        const inquiry = await Inquiry_1.Inquiry.findByIdAndUpdate(req.params.id, req.body, {
            new: true,
            runValidators: true,
        });
        if (!inquiry) {
            return res.status(404).json({ success: false, message: "Inquiry not found" });
        }
        res.status(200).json({ success: true, data: inquiry });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error updating inquiry" });
    }
});
app.delete("/api/admin/inquiries/:id", auth_1.protect, async (req, res) => {
    try {
        const inquiry = await Inquiry_1.Inquiry.findByIdAndDelete(req.params.id);
        if (!inquiry) {
            return res.status(404).json({ success: false, message: "Inquiry not found" });
        }
        res.status(200).json({ success: true, message: "Inquiry deleted" });
    }
    catch (err) {
        res.status(500).json({ success: false, message: "Error deleting inquiry" });
    }
});
app.get("/api/health", (req, res) => {
    res.json({ status: "ok", message: "Backend server is running smoothly" });
});
app.post("/api/contact", async (req, res) => {
    if (!EMAIL_USER || !EMAIL_PASS || !RECEIVER_EMAIL) {
        return res.status(503).json({
            error: "Email service is not configured. Please contact support.",
        });
    }
    const { name, email, message } = req.body;
    if (!name || !email || !message) {
        return res
            .status(400)
            .json({ error: "Please provide all required fields" });
    }
    // Email format validation (Regex)
    const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    if (!emailRegex.test(email)) {
        return res.status(400).json({ error: "Invalid email format" });
    }
    // Block common fake/test domains
    const blockedDomains = [
        "example.com",
        "test.com",
        "mailinator.com",
        "tempmail.com",
    ];
    const domain = email.split("@")[1]?.toLowerCase();
    if (blockedDomains.includes(domain)) {
        return res
            .status(400)
            .json({ error: "Please use a real personal or business email address." });
    }
    const mailOptions = {
        from: EMAIL_USER,
        to: RECEIVER_EMAIL,
        replyTo: email,
        subject: `New Contact Message from ${name}`,
        text: `
      Name: ${name}
      Email: ${email}
      Message: ${message}
    `,
        html: `
      <h2>New Contact Form Submission</h2>
      <p><strong>Name:</strong> ${name}</p>
      <p><strong>Email:</strong> ${email}</p>
      <p><strong>Message:</strong></p>
      <p>${message}</p>
    `,
    };
    try {
        // Save inquiry to DB first
        await Inquiry_1.Inquiry.create({ name, email, message });
        await transporter.sendMail(mailOptions);
        res
            .status(200)
            .json({ success: true, message: "Email sent and inquiry recorded!" });
    }
    catch (error) {
        console.error("Error sending email:", error);
        res
            .status(500)
            .json({ error: "Failed to send email. Please check server logs." });
    }
});
// ==========================================
// 1. STATIC FILES & REACT ROUTING CONFIGURATION
// ==========================================
// In development, you might be testing the build locally
// In production (cPanel), we use the production folder path
const isProduction = process.env.NODE_ENV === "production";
// Define both potential paths
const localClientPath = path_1.default.join(__dirname, "../../client/dist");
const prodClientPath = path_1.default.join(__dirname, "../dist"); // The cPanel path
// Let the environment determine the path
const envClientPath = isProduction ? prodClientPath : localClientPath;
// Fallback: If the environment-determined path doesn't exist, check the other one as a safety net
const clientDistPath = fs_1.default.existsSync(envClientPath)
    ? envClientPath
    : (isProduction ? localClientPath : prodClientPath);
app.use(express_1.default.static(clientDistPath));
// ==========================================
// 2. CATCH-ALL WILDCARD ROUTE FOR REACT ROUTING
// ==========================================
// IMPORTANT: This block MUST be placed AFTER all your API routes (/api/*).
// If placed before, it will intercept your API requests and return the React index.html instead of JSON.
// This route handles React Router's client-side routing. When a user refreshes a page (e.g., /about),
// the Express server won't find a file named 'about', so it falls back to serving the React app's index.html,
// allowing React Router to take over and render the correct component.
app.get("*", (req, res) => {
    res.sendFile(path_1.default.join(clientDistPath, "index.html"));
});
app.listen(PORT, () => {
    console.log(`Server is running at http://localhost:${PORT}`);
});
