import lurid from '@andyburke/lurid';
import parse_body from '../../../utils/bodyparser.ts';
import { get_session, get_user, require_user } from '../../../utils/prechecks.ts';
import * as CANNED_RESPONSES from '../../../utils/canned_responses.ts';
import { PRECHECK_TABLE } from '../../../utils/prechecks.ts';
import { CHANNEL, CHANNELS } from '../../../models/channel.ts';

export const PRECHECKS: PRECHECK_TABLE = {};

// GET /api/channels - get channels
PRECHECKS.GET = [get_session, get_user, require_user, (_req: Request, meta: Record<string, any>): Response | undefined => {
	const can_read_channels = meta.user.permissions.includes('channels.read');

	if (!can_read_channels) {
		return CANNED_RESPONSES.permission_denied();
	}
}];
export async function GET(_req: Request, meta: Record<string, any>): Promise<Response> {
	const limit = Math.min(parseInt(meta.query.limit ?? '100'), 100);
	const channels = (await CHANNELS.all({
		limit
	})).map((channel_entry) => channel_entry.load());

	return Response.json(channels, {
		status: 200
	});
}

// POST /api/channels - Create a channel
PRECHECKS.POST = [get_session, get_user, require_user, (_req: Request, meta: Record<string, any>): Response | undefined => {
	const can_create_channels = meta.user.permissions.includes('channels.create');

	if (!can_create_channels) {
		return CANNED_RESPONSES.permission_denied();
	}
}];
export async function POST(req: Request, meta: Record<string, any>): Promise<Response> {
	try {
		const now = new Date().toISOString();

		const body = await parse_body(req);

		if (typeof body.name !== 'string' || body.name.length === 0) {
			return Response.json({
				error: {
					cause: 'missing_channel_name',
					message: 'You must specify a unique name for a channel.'
				}
			}, {
				status: 400
			});
		}

		if (body.name.length > 64) {
			return Response.json({
				error: {
					cause: 'invalid_channel_name',
					message: 'channel names must be 64 characters or fewer.'
				}
			}, {
				status: 400
			});
		}

		const normalized_name = body.name.toLowerCase();

		const existing_channel = (await CHANNELS.find({
			name: normalized_name
		})).shift();
		if (existing_channel) {
			return Response.json({
				error: {
					cause: 'channel_name_conflict',
					message: 'There is already a channel with this name.'
				}
			}, {
				status: 400
			});
		}

		const channel: CHANNEL = {
			...body,
			id: lurid(),
			creator_id: meta.user.id,
			permissions: {
				read: (body.permissions?.read ?? []),
				write: (body.permissions?.write ?? [meta.user.id]),
				events: {
					read: (body.permissions?.events?.read ?? []),
					write: (body.permissions?.events?.write ?? [])
				}
			},
			timestamps: {
				created: now,
				updated: now,
				archived: undefined
			}
		};

		await CHANNELS.create(channel);

		return Response.json(channel, {
			status: 201
		});
	} catch (error) {
		return Response.json({
			error: {
				message: (error as Error).message ?? 'Unknown Error!',
				cause: (error as Error).cause ?? 'unknown'
			}
		}, { status: 500 });
	}
}
