import { createLogger, format, transports } from 'winston';
import Transport, { TransportStreamOptions } from 'winston-transport';
import type { LogEntry } from 'winston';
import { PrismaClient } from '@prisma/client';

class CustomPrismaTransport extends Transport {
	constructor(opts: TransportStreamOptions) {
		super(opts);
	}

	prisma = new PrismaClient();

	// this functions run when something is logged so here's where you can add you custom logic to do stuff when something is logged.
	log(info: LogEntry, callback: any) {
		// make sure you installed `@types/node` or this will give a typerror
		// this is the basic default behavior don't forget to add this.
		const { level, message, type, typeId, ...meta } = info;

		this.prisma['log']
			.create({
				data: {
					level,
					message,
					timestamp: new Date(),
					meta,
					type,
					typeId,
				},
			})
			.then(() => {
				setImmediate(() => {
					this.emit('logged', info);
				});
				// return callback && callback(undefined, true);
			})
			.catch((err) => {
				setImmediate(() => {
					this.emit('error', err);
				});
				return callback && callback(err, null);
			});

		// don't forget this one
		callback();
	}
}

const devLogger = {
	format: format.combine(format.timestamp(), format.errors({ stack: true }), format.json()),
	transports: [new CustomPrismaTransport({}), new transports.Console()],
};

const prodLogger = {
	format: format.combine(format.timestamp(), format.errors({ stack: true }), format.json()),
	transports: [new CustomPrismaTransport({}), new transports.Console()],
};

export const logger = createLogger(process.env.NODE_ENV === 'prod' ? prodLogger : devLogger);
