import { NextRequestWithAuth, withAuth } from "next-auth/middleware";
import { ability, authOptions } from "@/config/authConfig";
import { NextFetchEvent, NextResponse } from "next/server";
import { getToken } from "next-auth/jwt";

// abilities
export const [
  VIEW_USER,
  MAINTAIN_USER,
  MAINTAIN_TIMESHEET,
  VIEW_TASK_TEMPLATE,
  VIEW_GROUP,
  VIEW_MASTERDATA,
  MAINTAIN_MASTERDATA,
  VIEW_DASHBOARD_SELF,
  VIEW_DASHBOARD_ALL,
  IMPORT_INVOICE,
  MAINTAIN_GROUP,
  GENERATE_REPORTS,
  VIEW_STAFF_PROFILE,
  IMPORT_RECEIPT,
  MAINTAIN_TASK_TEMPLATE,
  MAINTAIN_TIMESHEET_7DAYS,
  VIEW_PROJECT,
  MAINTAIN_PROJECT,
] = [
  'VIEW_USER',
  'MAINTAIN_USER',
  'MAINTAIN_TIMESHEET',
  'VIEW_TASK_TEMPLATE',
  'VIEW_GROUP',
  'VIEW_MASTERDATA',
  'MAINTAIN_MASTERDATA',
  'VIEW_DASHBOARD_SELF',
  'VIEW_DASHBOARD_ALL',
  'IMPORT_INVOICE',
  'MAINTAIN_GROUP',
  'GENERATE_REPORTS',
  'VIEW_STAFF_PROFILE',
  'IMPORT_RECEIPT',
  'MAINTAIN_TASK_TEMPLATE',
  'MAINTAIN_TIMESHEET_7DAYS',
  'VIEW_PROJECT',
  'MAINTAIN_PROJECT'
]

const PRIVATE_ROUTES = [
  "/analytics",
  "/dashboard",
  "/home",
  "/invoice",
  "/projects",
  "/tasks",
  "/settings",
  "/staffReimbursement",
];
const LANG_QUERY_PARAM = "lang";

export default async function middleware(
  req: NextRequestWithAuth,
  event: NextFetchEvent,
) {
  const langPref = req.nextUrl.searchParams.get(LANG_QUERY_PARAM);
  const token = await getToken({ req: req, secret: process.env.SECRET });
  if (langPref) {
    // Redirect to same url without the lang query param + set cookies
    const newUrl = new URL(req.nextUrl);
    newUrl.searchParams.delete(LANG_QUERY_PARAM);
    const response = NextResponse.redirect(newUrl);
    response.cookies.set("i18next", langPref);
    return response;
  }

  const authMiddleware = withAuth({
    pages: authOptions.pages,
    callbacks: {
      authorized: ({req, token}) => {
        let isAuth = Boolean(token);
        if (!Boolean(token)) {
          return Boolean(token)
        }
        const abilities = (token!.abilities as ability[]).map((item: ability) => item.actionSubjectCombo);
        if (req.nextUrl.pathname.startsWith('/settings')) {
          isAuth = [VIEW_MASTERDATA, MAINTAIN_MASTERDATA].some((ability) => abilities.includes(ability));
        } 
        if (req.nextUrl.pathname.startsWith('/settings/user')) {
          isAuth = [MAINTAIN_USER, VIEW_USER].some((ability) => abilities.includes(ability));
        }
        if (req.nextUrl.pathname.startsWith('/settings/staff/user')) {
          isAuth = [MAINTAIN_USER, VIEW_USER].some((ability) => abilities.includes(ability));
        }
        if (req.nextUrl.pathname.startsWith('/analytics')) {
          isAuth = [GENERATE_REPORTS].some((ability) => abilities.includes(ability));
        }
        if (req.nextUrl.pathname.startsWith('/settings/staff/edit')) {
          isAuth = [VIEW_STAFF_PROFILE].some((ability) => abilities.includes(ability));
        }
        return isAuth
      }
    }
  });

  // Matcher for using the auth middleware
  return PRIVATE_ROUTES.some((route) => req.nextUrl.pathname.startsWith(route))
    ? await authMiddleware(req, event) // Let auth middleware handle response
    : NextResponse.next(); // Return normal response
}
