'use strict';

const path = require('path');
const config = require('config');
const express = require('express');
const Router = require('express-promise-router');
const bodyParser = require('body-parser');
const session = require('express-session');
const KnexSessionStore = require('connect-session-knex')(session);
const nanoid = require('nanoid');

const logger = require('../logger')(__filename);
const knex = require('../knex');
const errorHandler = require('./error');

const pg = require('./postgraphile');

const {
	login,
	logout,
	signup,
	fetchMe,
} = require('./auth');

const {
	fetchScene,
	fetchScenes,
	fetchScenePoster,
} = require('./releases');

const {
	fetchActor,
	fetchActors,
} = require('./actors');

const {
	fetchEntity,
	fetchEntities,
} = require('./entities');

const {
	fetchTag,
	fetchTags,
} = require('./tags');

const {
	createStash,
	stashActor,
	stashScene,
	stashMovie,
	unstashActor,
	unstashScene,
	unstashMovie,
	updateStash,
} = require('./stashes');

async function initServer() {
	const app = express();
	const router = Router();
	const store = new KnexSessionStore({ knex });

	app.set('view engine', 'ejs');

	router.use('/media', express.static(config.media.path));
	router.use(express.static('public'));

	router.use('/img', (req, res) => {
		res.status(404).send();
	});

	router.use(bodyParser.json({ strict: false }));
	router.use(session({ ...config.web.session, store }));

	router.use(pg);

	router.use((req, res, next) => {
		req.session.safeId = req.session.safeId || nanoid();

		next();
	});

	router.get('/api/session', fetchMe);
	router.post('/api/session', login);
	router.delete('/api/session', logout);

	router.post('/api/users', signup);

	router.post('/api/stashes', createStash);
	router.patch('/api/stashes/:stashId', updateStash);

	router.post('/api/stashes/:stashId/actors', stashActor);
	router.post('/api/stashes/:stashId/scenes', stashScene);
	router.post('/api/stashes/:stashId/movies', stashMovie);

	router.delete('/api/stashes/:stashId/actors/:actorId', unstashActor);
	router.delete('/api/stashes/:stashId/scenes/:sceneId', unstashScene);
	router.delete('/api/stashes/:stashId/movies/:movieId', unstashMovie);

	router.get('/api/scenes', fetchScenes);
	router.get('/api/scenes/:releaseId', fetchScene);
	router.get('/api/scenes/:releaseId/poster', fetchScenePoster);

	// router.get('/api/movies', fetchMovies);
	// router.get('/api/movies/:releaseId', fetchMovie);

	router.get('/api/actors', fetchActors);
	router.get('/api/actors/:actorId', fetchActor);

	router.get('/api/entities', async (req, res) => fetchEntities(req, res, null));
	router.get('/api/entities/:entityId', async (req, res) => fetchEntity(req, res, null));

	router.get('/api/channels', async (req, res) => fetchEntities(req, res, 'channel'));
	router.get('/api/channels/:entityId', async (req, res) => fetchEntity(req, res, 'channel'));

	router.get('/api/networks', async (req, res) => fetchEntities(req, res, 'network'));
	router.get('/api/networks/:entityId', async (req, res) => fetchEntity(req, res, 'network'));

	router.get('/api/studios', async (req, res) => fetchEntities(req, res, 'studio'));
	router.get('/api/studios/:entityId', async (req, res) => fetchEntity(req, res, 'studio'));

	router.get('/api/tags', fetchTags);
	router.get('/api/tags/:tagId', fetchTag);

	router.get('*', (req, res) => {
		res.render(path.join(__dirname, '../../assets/index.ejs'), {
			env: JSON.stringify({
				sfw: !!req.headers.sfw || Object.prototype.hasOwnProperty.call(req.query, 'sfw'),
				auth: config.auth.enabled,
				sessionId: req.session.safeId,
			}),
		});
	});

	router.use(errorHandler);
	app.use(router);

	const server = app.listen(config.web.port, config.web.host, () => {
		const { address, port } = server.address();

		logger.info(`Web server listening on ${address}:${port}`);
	});
}

module.exports = initServer;