import accounts from "./accounts.json" with { type: "json" };
import session from "express-session";
import express, { Request, Response } from "express";
import process from "node:process";
import { fromFileUrl } from "@std/path";
import { dirname } from "@std/path";
import path from "node:path";
import { PrismaClient } from "./generated/client.ts";
import { authMiddleware } from "./auth.ts";

const prisma = new PrismaClient();
const __dirname = dirname(fromFileUrl(import.meta.url));
const app = express();
const port = process.env.PORT || 3000;
app.use(express.json());

app.use(express.static(path.join(__dirname, "public")));

app.use(express.urlencoded({ extended: true }));
app.use(
    session({
        secret: process.env.SESSION_SECRET ||
            "your-secret-key-change-in-production",
        resave: false,
        saveUninitialized: false,
        name: "cookie_gt",
        cookie: {
            maxAge: 5 * 60 * 1000, // 5 minutes
            secure: process.env.NODE_ENV === "production",
            httpOnly: true,
        },
    }),
);

const students = await prisma.student.findMany();

app.get("/students", async (_req: Request, res: Response) => {
  const students = await prisma.student.findMany();
  res.json(students);
});

app.get("/students/:id", async (req: Request, res: Response) => {
  const id = parseInt(req.params.id);
  const student = await prisma.student.findUnique({
    where: { id }
  });
  if (!student) {
    return res.status(404).json({ error: "Student not found" });
  }
  res.json(student);
});

app.post("/students", async (req: Request, res: Response) => {
  const { name, course } = req.body;
  if (!name || !course) {
    return res.status(400).json({ error: "Name and course are required!" });
  }
  const newStudent = await prisma.student.create({
    data: { name, course }
  });
  res.status(201).json(newStudent);
});

app.put("/students/:id", async (req: Request, res: Response) => {
  const id = parseInt(req.params.id);
  const { name, course } = req.body;
  if (!name || !course) {
    return res.status(400).json({ error: "Name and course are required!" });
  }
  try {
    const updatedStudent = await prisma.student.update({
      where: { id },
      data: { name, course }
    });
    res.json(updatedStudent);
  } catch {
    return res.status(404).json({ error: "Student not found" });
  }
});

app.patch("/students/:id", async (req: Request, res: Response) => {
  const id = parseInt(req.params.id);
  const { name, course } = req.body;

  const data: { name?: string; course?: string } = {};

  if (name !== undefined) data.name = name;
  if (course !== undefined) data.course = course;

  try {
    const updatedStudent = await prisma.student.update({
      where: { id },
      data
    });

    res.json(updatedStudent);
  } catch {
    return res.status(404).json({ error: "Student not found" });
  }
});

app.delete("/students/:id", authMiddleware, async (req: Request, res: Response) => {
  const id = parseInt(req.params.id);

  try {
    await prisma.student.delete({
      where: { id }
    });

    return res.status(204).send(); // No Content
  } catch {
    return res.status(404).json({ error: "Student not found" });
  }
});

app.post("/login", (req: Request, res: Response) => {
    const { username, password } = req.body;

    const account = accounts.find(
        (acc) => acc.username === username && acc.password === password,
    );

    if (account) {
        req.session.user = { username: account.username };
        return res.json({ message: "Login successful" });
    }

    res.status(401).json({ error: "Invalid credentials" });
});

app.get("/loginstatus", (req: Request, res: Response) => {
    if (req.session.user) {
        return res.json({ loggedIn: true, user: req.session.user });
    }
    res.json({ loggedIn: false });
});

app.get("/safe", authMiddleware, (req: Request, res: Response) => {
    res.json({ message: "This is a safe route", user: req.session.user });
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});