import { v } from 'convex/values';
import { mutation, query, action, internalMutation } from './_generated/server';
import { encryptSMTPPassword } from './auth/utils';
import { registrarAtividade } from './logsAtividades';
import { api, internal } from './_generated/api';

/**
 * Obter configuração de email ativa (senha mascarada)
 */
export const obterConfigEmail = query({
	args: {},
	handler: async (ctx) => {
		const config = await ctx.db
			.query('configuracaoEmail')
			.withIndex('by_ativo', (q) => q.eq('ativo', true))
			.first();

		if (!config) {
			return null;
		}

		// Retornar config com senha mascarada
		return {
			_id: config._id,
			servidor: config.servidor,
			porta: config.porta,
			usuario: config.usuario,
			senhaHash: '********', // Mascarar senha
			emailRemetente: config.emailRemetente,
			nomeRemetente: config.nomeRemetente,
			usarSSL: config.usarSSL,
			usarTLS: config.usarTLS,
			ativo: config.ativo,
			testadoEm: config.testadoEm,
			atualizadoEm: config.atualizadoEm
		};
	}
});

/**
 * Salvar configuração de email (apenas TI_MASTER)
 */
export const salvarConfigEmail = mutation({
	args: {
		servidor: v.string(),
		porta: v.number(),
		usuario: v.string(),
		senha: v.string(),
		emailRemetente: v.string(),
		nomeRemetente: v.string(),
		usarSSL: v.boolean(),
		usarTLS: v.boolean(),
		configuradoPorId: v.id('usuarios')
	},
	returns: v.union(
		v.object({ sucesso: v.literal(true), configId: v.id('configuracaoEmail') }),
		v.object({ sucesso: v.literal(false), erro: v.string() })
	),
	handler: async (ctx, args) => {
		// Validar email
		const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
		if (!emailRegex.test(args.emailRemetente)) {
			return { sucesso: false as const, erro: 'Email remetente inválido' };
		}

		// Validar porta
		if (args.porta < 1 || args.porta > 65535) {
			return { sucesso: false as const, erro: 'Porta deve ser um número entre 1 e 65535' };
		}

		// Buscar config ativa anterior para manter senha se não fornecida
		const configAtiva = await ctx.db
			.query('configuracaoEmail')
			.withIndex('by_ativo', (q) => q.eq('ativo', true))
			.first();

		// Determinar senhaHash: usar nova senha se fornecida, senão manter a atual
		let senhaHash: string;
		if (args.senha && args.senha.trim().length > 0) {
			// Nova senha fornecida, criptografar usando criptografia reversível (AES)
			senhaHash = await encryptSMTPPassword(args.senha);
		} else if (configAtiva) {
			// Senha não fornecida, manter a atual (já criptografada)
			senhaHash = configAtiva.senhaHash;
		} else {
			// Sem senha e sem config existente - erro
			return { sucesso: false as const, erro: 'Senha é obrigatória para nova configuração' };
		}

		// Desativar config anterior
		const configsAntigas = await ctx.db
			.query('configuracaoEmail')
			.withIndex('by_ativo', (q) => q.eq('ativo', true))
			.collect();

		for (const config of configsAntigas) {
			await ctx.db.patch(config._id, { ativo: false });
		}

		// Criar nova config
		const configId = await ctx.db.insert('configuracaoEmail', {
			servidor: args.servidor,
			porta: args.porta,
			usuario: args.usuario,
			senhaHash,
			emailRemetente: args.emailRemetente,
			nomeRemetente: args.nomeRemetente,
			usarSSL: args.usarSSL,
			usarTLS: args.usarTLS,
			ativo: true,
			configuradoPor: args.configuradoPorId,
			atualizadoEm: Date.now()
		});

		// Log de atividade
		await registrarAtividade(
			ctx,
			args.configuradoPorId,
			'configurar',
			'email',
			JSON.stringify({ servidor: args.servidor, porta: args.porta }),
			configId
		);

		return { sucesso: true as const, configId };
	}
});

/**
 * Mutation interna para atualizar testadoEm
 */
export const atualizarTestadoEm = internalMutation({
	args: {
		configId: v.id('configuracaoEmail')
	},
	returns: v.null(),
	handler: async (ctx, args) => {
		await ctx.db.patch(args.configId, {
			testadoEm: Date.now()
		});
		return null;
	}
});

/**
 * Testar conexão SMTP (action que chama action real)
 */
export const testarConexaoSMTP = action({
	args: {
		servidor: v.string(),
		porta: v.number(),
		usuario: v.string(),
		senha: v.string(),
		usarSSL: v.boolean(),
		usarTLS: v.boolean()
	},
	returns: v.union(
		v.object({ sucesso: v.literal(true) }),
		v.object({ sucesso: v.literal(false), erro: v.string() })
	),
	handler: async (ctx, args): Promise<{ sucesso: true } | { sucesso: false; erro: string }> => {
		// Validações básicas
		if (!args.servidor || args.servidor.trim().length === 0) {
			return { sucesso: false as const, erro: 'Servidor SMTP não pode estar vazio' };
		}

		if (!args.porta || args.porta < 1 || args.porta > 65535) {
			return { sucesso: false as const, erro: 'Porta inválida. Deve ser entre 1 e 65535' };
		}

		if (!args.usuario || args.usuario.trim().length === 0) {
			return { sucesso: false as const, erro: 'Usuário não pode estar vazio' };
		}

		if (!args.senha || args.senha.trim().length === 0) {
			return { sucesso: false as const, erro: 'Senha não pode estar vazia' };
		}

		// Validação de SSL/TLS mutuamente exclusivos
		if (args.usarSSL && args.usarTLS) {
			return {
				sucesso: false as const,
				erro: 'SSL e TLS não podem estar habilitados simultaneamente'
			};
		}

		// Chamar action de teste real (que usa nodemailer)
		try {
			const resultado: { sucesso: true } | { sucesso: false; erro: string } = await ctx.runAction(
				api.actions.smtp.testarConexao,
				{
					servidor: args.servidor,
					porta: args.porta,
					usuario: args.usuario,
					senha: args.senha,
					usarSSL: args.usarSSL,
					usarTLS: args.usarTLS
				}
			);

			// Se o teste foi bem-sucedido e há uma config ativa, atualizar testadoEm
			if (resultado.sucesso) {
				const configAtiva = await ctx.runQuery(api.configuracaoEmail.obterConfigEmail, {});

				if (configAtiva) {
					await ctx.runMutation(internal.configuracaoEmail.atualizarTestadoEm, {
						configId: configAtiva._id
					});
				}
			}

			return resultado;
		} catch (error: unknown) {
			const errorMessage = error instanceof Error ? error.message : String(error);
			return {
				sucesso: false as const,
				erro: errorMessage || 'Erro ao conectar com o servidor SMTP'
			};
		}
	}
});

/**
 * Marcar que a configuração foi testada com sucesso
 */
export const marcarConfigTestada = mutation({
	args: {
		configId: v.id('configuracaoEmail')
	},
	handler: async (ctx, args) => {
		await ctx.db.patch(args.configId, {
			testadoEm: Date.now()
		});
	}
});
