const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const bcrypt = require("bcrypt");
const session = require("express-session");
const db = require("./db");
const User = require("./models/user.model");
const News = require("./models/news.model");

const app = express();
const port = process.env.PORT || 3000;

// Middleware
app.use(
  cors({
    origin: "http://localhost:3000",
    credentials: true,
  }),
);
app.use(bodyParser.json());
app.use(cookieParser());

// Session setup
app.use(
  session({
    secret: "your-secret-key",
    resave: false,
    saveUninitialized: true,
    cookie: {
      sameSite: "none",
      secure: true,
    },
  }),
);

{
  /*********************************************************************/
}

app.post("/signup", async (req, res) => {
  try {
    const { username, password } = req.body;

    // Check if the username already exists
    const existingUser = await User.findOne({ username });
    if (existingUser) {
      return res.status(400).json({ error: "exists" });
    }

    // Hash the password
    const hashedPassword = await bcrypt.hash(password, 10);

    // Create a new user and save to the database
    const user = new User({ username, password: hashedPassword });
    await user.save();

    res.status(201).json({ message: "User created successfully" });
  } catch (error) {
    if (error.code === 11000 && error.keyValue && error.keyValue.username) {
      // Duplicate key error, indicating that the username already exists
      return res.status(400).json({ error: "exists" });
    }
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

app.post("/signin", async (req, res) => {
  try {
    const { username, password } = req.body;

    const user = await User.findOne({ username });

    if (!user || !(await bcrypt.compare(password, user.password))) {
      return res.status(401).json({ error: "Authentication failed" });
    }

    req.session.user = user;

    res.json({ message: "Authentication successful", redirect: "/home" });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

app.get("/checkLoggedIn", (req, res) => {
  if (req.session.user) {
    res
      .status(200)
      .json({ loggedIn: true, username: req.session.user.username });
  } else {
    res.status(401).json({ loggedIn: false });
  }
});

{
  /*********************************************************************/
}

// Helper function to validate URL format
function isValidURL(url) {
  // Basic URL format check (you might want to use a more sophisticated check)
  const urlPattern =
    /^(https?:\/\/)?(www\.)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}(\/\S*)?$/;
  return urlPattern.test(url);
}

// Fetch list of news articles
app.get("/news/all", async (req, res) => {
  try {
    const newsList = await News.find();
    res.status(200).json({ news: newsList });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred while fetching news" });
  }
});

// Check if a URL is unique
app.post("/news/add", async (req, res) => {
  try {
    const { userId, url, title } = req.body;

    // Check if the URL is unique
    const existingNews = await News.findOne({ url });
    if (existingNews) {
      return res.status(400).json({ error: "URL already exists" });
    }

    const news = new News({
      userId,
      url,
      title,
      likes: 0,
      dislikes: 0,
      comments: [],
    });
    await news.save();

    res.status(201).json({ message: "TraiteReponseNews added successfully" });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

// Check URL format route
app.get("/news/checkUrlFormat/:url", (req, res) => {
  const { url } = req.params;

  // Validate URL format (this is a basic check)
  if (!isValidURL(url)) {
    return res.status(400).json({ validFormat: false });
  }

  res.status(200).json({ validFormat: true });
});

// Check URL uniqueness route
app.get("/news/checkUrl/:url", async (req, res) => {
  const { url } = req.params;

  try {
    const existingNews = await News.findOne({ url });
    const isUnique = !existingNews;

    res.status(200).json({ unique: isUnique });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

// Add Comment route
app.post("/news/addComment/:id", async (req, res) => {
  const { id } = req.params;
  const { auteur, commentaire } = req.body;

  try {
    const news = await News.findById(id);

    if (!news) {
      return res
        .status(404)
        .json({ error: "TraiteReponseNews article not found" });
    }

    news.comments.push({
      date: new Date(),
      auteur,
      commentaire,
    });

    await news.save();

    res.status(200).json({ message: "Comment added successfully" });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

// API route to like news article
// Like a news article
app.post("/news/like/:id", async (req, res) => {
  const { id } = req.params;
  const { loggedInUsername } = req.body;

  try {
    const news = await News.findById(id);

    if (!news) {
      return res.status(404).json({ error: "News article not found" });
    }

    const user = await User.findOne({ username: loggedInUsername });

    if (!user) {
      return res.status(404).json({ error: "User not found" });
    }

    if (user.likedNews.includes(id)) {
      return res
        .status(400)
        .json({ error: "User has already liked this article" });
    }

    if (user.dislikedNews.includes(id)) {
      // Remove from dislikedNews array
      user.dislikedNews.pull(id);
      await user.save();
      news.dislikes -= 1;
    }

    user.likedNews.push(id);
    await user.save();
    news.likes += 1;
    await news.save();

    res.status(200).json({ message: "News article liked successfully" });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

// Dislike a news article
app.post("/news/dislike/:id", async (req, res) => {
  const { id } = req.params;
  const { loggedInUsername } = req.body;

  try {
    const news = await News.findById(id);

    if (!news) {
      return res.status(404).json({ error: "News article not found" });
    }

    const user = await User.findOne({ username: loggedInUsername });

    if (!user) {
      return res.status(404).json({ error: "User not found" });
    }

    if (user.dislikedNews.includes(id)) {
      return res
        .status(400)
        .json({ error: "User has already disliked this article" });
    }

    if (user.likedNews.includes(id)) {
      // Remove from likedNews array
      user.likedNews.pull(id);
      await user.save();
      news.likes -= 1;
    }

    user.dislikedNews.push(id);
    await user.save();
    news.dislikes += 1;
    await news.save();

    res.status(200).json({ message: "News article disliked successfully" });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

{
  /*********************************************************************/
}
app.post("/addFriend/:username", async (req, res) => {
  try {
    const { username } = req.params;
    const { friendUsername } = req.body;

    const loggedInUser = await User.findOne({ username });

    if (!loggedInUser) {
      return res.status(404).json({ error: "User not found" });
    }

    if (loggedInUser.friends.includes(friendUsername)) {
      return res.status(400).json({ error: "Friend already exists" });
    }

    loggedInUser.friends.push(friendUsername);
    await loggedInUser.save();

    res.status(200).json({ message: "Friend added successfully" });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

// Friends endpoint
app.get("/friends/:username", async (req, res) => {
  const { username } = req.params;

  try {
    const user = await User.findOne({ username });

    if (!user) {
      return res.status(404).json({ error: "User not found" });
    }

    // Return the friends array from the user document
    res.status(200).json({ friends: user.friends });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Server error" });
  }
});

app.get("/users", async (req, res) => {
  try {
    const users = await User.find({}, "username");
    res.status(200).json(users);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "An error occurred" });
  }
});

app.get("/likedNews/:username", async (req, res) => {
  const { username } = req.params;

  // Validate and sanitize page parameter
  const page = parseInt(req.query.page) || 1;

  try {
    // Find user by username
    const user = await User.findOne({ username })
      .populate("likedNews") // Populate reference
      .exec();

    if (!user) {
      return res.status(404).json({ message: "User not found" });
    }

    // Pagination variables
    const pageSize = 3;
    const skip = pageSize * (page - 1);

    // Slice likedNews array
    const likedNews = user.likedNews.slice(skip, skip + pageSize);

    // Total count
    const total = user.likedNews.length;

    // Calculate total pages
    const totalPages = Math.ceil(total / pageSize);

    res.json({
      likedNews,
      total,
      totalPages,
      currentPage: page,
    });
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});


const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({
  username: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  friends: [{ type: String }],
  likedNews: [{ type: mongoose.Schema.Types.ObjectId, ref: "News" }],
  dislikedNews: [{ type: mongoose.Schema.Types.ObjectId, ref: "News" }],
});

const User = mongoose.model("User", userSchema);

module.exports = User;



const mongoose = require("mongoose");

const newsSchema = new mongoose.Schema({
  userId: {
    type: String,
    required: true,
  },
  url: {
    type: String,
    required: true,
    unique: true,
  },
  title: {
    type: String,
    required: true,
  },
  likes: {
    type: Number,
    default: 0,
  },
  dislikes: {
    type: Number,
    default: 0,
  },
  comments: {
    type: [
      {
        date: {
          type: Date,
          required: true,
        },
        auteur: {
          type: String,
          required: true,
        },
        commentaire: {
          type: String,
          required: true,
        },
      },
    ],
    default: [],
  },
});

// Virtual field to calculate the score (likes - dislikes)
newsSchema.virtual("score").get(function () {
  return this.likes - this.dislikes;
});

newsSchema.set("toJSON", { virtuals: true });

const News = mongoose.model("News", newsSchema);

module.exports = News;




const mongoose = require("mongoose");

mongoose.connect(
  "mongodb+srv://moussa:<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>/mongoglcc",
  {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  },
);

const db = mongoose.connection;

db.on("error", console.error.bind(console, "MongoDB connection error:"));

module.exports = db;



transform it into express