import path from 'path';
import { fileURLToPath } from 'url';
import express from 'express';
import cors from 'cors';
import RateLimit from 'express-rate-limit';
import { Sequelize } from 'sequelize';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();

// enable frontend access
const frontendOrigin = process.env.FRONTEND_ORIGIN || 'http://localhost:8000';
const corsOptions = {
  origin: frontendOrigin,
  methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
};
app.use(cors(corsOptions));

// enable json middleware
app.use(express.json());

// enable rate limiter
const limiter = RateLimit({
  windowMs: 60 * 60 * 1000, // 1h
  max: 1000, // 1000 requests per hour
  message: 'Too many requests from this IP, please try again after an hour',
});
app.use(limiter);

// Specify the directory to serve static files
app.use(express.static(path.join(__dirname, 'public')));

// init sequalize
const databasePath = path.resolve(__dirname, 'database/database.sqlite');
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: databasePath,
  logging: false,
});

// "/"
import indexRoute from './routes/index.js';
app.use('/', indexRoute());

// "/health"
import healthIndexRoute from './routes/health/index.js';
app.use('/health', healthIndexRoute());

// "users"
import usersIndexRoute from './routes/users/index.js';
import usersFindRoute from './routes/users/find.js';
import usersSearchRoute from './routes/users/search.js';
import usersUpdateRoute from './routes/users/update.js';
import signUpRoute from './routes/users/signup.js';
import signInRoute from './routes/users/signin.js';
app.use('/users', usersIndexRoute(sequelize));
app.use('/users', usersFindRoute(sequelize));
app.use('/users', usersSearchRoute(sequelize));
app.use('/users', usersUpdateRoute(sequelize));
app.use('/users', signUpRoute(sequelize));
app.use('/users', signInRoute(sequelize));

// "/projects"
import projectsIndexRoute from './routes/projects/index.js';
import projectsShowRoute from './routes/projects/show.js';
import projectsNewRoute from './routes/projects/new.js';
import projectsEditRoute from './routes/projects/edit.js';
import projectsDeleteRoute from './routes/projects/delete.js';
app.use('/projects', projectsIndexRoute(sequelize));
app.use('/projects', projectsShowRoute(sequelize));
app.use('/projects', projectsNewRoute(sequelize));
app.use('/projects', projectsEditRoute(sequelize));
app.use('/projects', projectsDeleteRoute(sequelize));

// "/folders"
import foldersIndexRoute from './routes/folders/index.js';
import foldersNewRoute from './routes/folders/new.js';
import foldersEditRoute from './routes/folders/edit.js';
import foldersDeleteRoute from './routes/folders/delete.js';
app.use('/folders', foldersIndexRoute(sequelize));
app.use('/folders', foldersNewRoute(sequelize));
app.use('/folders', foldersEditRoute(sequelize));
app.use('/folders', foldersDeleteRoute(sequelize));

// "/cases"
import casesDownloadRoute from './routes/cases/download.js';
import casesMoveRoute from './routes/cases/move.js';
import casesIndexRoute from './routes/cases/index.js';
import casesIndexByProjectIdRoute from './routes/cases/indexByProjectId.js';
import casesShowRoute from './routes/cases/show.js';
import casesNewRoute from './routes/cases/new.js';
import casesEditRoute from './routes/cases/edit.js';
import casesDeleteRoute from './routes/cases/delete.js';
app.use('/cases', casesDownloadRoute(sequelize));
app.use('/cases', casesMoveRoute(sequelize));
app.use('/cases', casesIndexRoute(sequelize));
app.use('/cases', casesIndexByProjectIdRoute(sequelize));
app.use('/cases', casesShowRoute(sequelize));
app.use('/cases', casesNewRoute(sequelize));
app.use('/cases', casesEditRoute(sequelize));
app.use('/cases', casesDeleteRoute(sequelize));

// "/steps"
import stepsEditRoute from './routes/steps/edit.js';
app.use('/steps', stepsEditRoute(sequelize));

// "/attachments"
import attachmentsNewRoute from './routes/attachments/new.js';
import attachmentsDeleteRoute from './routes/attachments/delete.js';
import attachmentsDownloadRoute from './routes/attachments/download.js';
app.use('/attachments', attachmentsNewRoute(sequelize));
app.use('/attachments', attachmentsDeleteRoute(sequelize));
app.use('/attachments', attachmentsDownloadRoute(sequelize));

// "/runs"
import runsDownloadRoute from './routes/runs/download.js';
import runsIndexRoute from './routes/runs/index.js';
import runsShowRoute from './routes/runs/show.js';
import runsNewRoute from './routes/runs/new.js';
import runsEditRoute from './routes/runs/edit.js';
import runDeleteRoute from './routes/runs/delete.js';

app.use('/runs', runsDownloadRoute(sequelize));
app.use('/runs', runsIndexRoute(sequelize));
app.use('/runs', runsShowRoute(sequelize));
app.use('/runs', runsNewRoute(sequelize));
app.use('/runs', runsEditRoute(sequelize));
app.use('/runs', runDeleteRoute(sequelize));

// "/runcases"
import runCaseIndexRoute from './routes/runcases/index.js';
import runCaseEditRoute from './routes/runcases/edit.js';
app.use('/runcases', runCaseIndexRoute(sequelize));
app.use('/runcases', runCaseEditRoute(sequelize));

// "/members"
import membersIndexRoute from './routes/members/index.js';
import membersNewRoute from './routes/members/new.js';
import membersEditRoute from './routes/members/edit.js';
import membersDeleteRoute from './routes/members/delete.js';
import membersCheckRoute from './routes/members/check.js';
app.use('/members', membersIndexRoute(sequelize));
app.use('/members', membersNewRoute(sequelize));
app.use('/members', membersEditRoute(sequelize));
app.use('/members', membersDeleteRoute(sequelize));
app.use('/members', membersCheckRoute(sequelize));

// "/home"
import homeIndexRoute from './routes/home/index.js';
app.use('/home', homeIndexRoute(sequelize));

if (!process.env.SECRET_KEY) {
  console.log(
    "[Warning]: Default key is used for token generation. Please set the environment variable 'SECRET_KEY'`."
  );
}

// Export the app instead of starting the server
export default app;
