import { mutation, query } from './_generated/server';
import { v } from 'convex/values';
import { situacaoContrato } from './tables/contratos';
import { getCurrentUserFunction } from './auth';
import { internal } from './_generated/api';

export const listar = query({
	args: {
		responsavelId: v.optional(v.id('funcionarios')),
		dataInicio: v.optional(v.string()),
		dataFim: v.optional(v.string())
	},
	handler: async (ctx, args) => {
		await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
			recurso: 'contratos',
			acao: 'listar'
		});

		let q = ctx.db.query('contratos');

		if (args.responsavelId) {
			q = q.withIndex('by_responsavel', (q) =>
				q.eq('responsavelId', args.responsavelId!)
			) as typeof q;
		}

		const contratos = await q.collect();

		// Filtros em memória para datas (já que Convex não tem filtro de range nativo eficiente combinado com outros índices sem setup complexo)
		// Se o volume for muito grande, ideal seria criar índices específicos ou usar search.
		let resultado = contratos;

		if (args.dataInicio) {
			resultado = resultado.filter((c) => c.dataInicioVigencia >= args.dataInicio!);
		}

		if (args.dataFim) {
			resultado = resultado.filter((c) => c.dataFimVigencia <= args.dataFim!);
		}

		// Enriquecer com dados relacionados
		const contratosEnriquecidos = await Promise.all(
			resultado.map(async (c) => {
				const contratada = await ctx.db.get(c.contratadaId);
				const responsavel = await ctx.db.get(c.responsavelId);
				return {
					...c,
					contratada,
					responsavel
				};
			})
		);

		return contratosEnriquecidos;
	}
});

export const obter = query({
	args: { id: v.id('contratos') },
	handler: async (ctx, args) => {
		await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
			recurso: 'contratos',
			acao: 'ver'
		});
		const contrato = await ctx.db.get(args.id);
		if (!contrato) return null;

		const contratada = await ctx.db.get(contrato.contratadaId);
		const responsavel = await ctx.db.get(contrato.responsavelId);

		return {
			...contrato,
			contratada,
			responsavel
		};
	}
});

export const criar = mutation({
	args: {
		contratadaId: v.id('empresas'),
		objeto: v.string(),
		numeroNotaEmpenho: v.string(),
		responsavelId: v.id('funcionarios'),
		departamento: v.string(),
		situacao: situacaoContrato,
		numeroProcessoLicitatorio: v.string(),
		modalidade: v.string(),
		numeroContrato: v.string(),
		anoContrato: v.number(),
		dataInicioVigencia: v.string(),
		dataFimVigencia: v.string(),
		nomeFiscal: v.string(),
		valorTotal: v.string(),
		dataAditivoPrazo: v.optional(v.string()),
		diasAvisoVencimento: v.number()
	},
	handler: async (ctx, args) => {
		await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
			recurso: 'contratos',
			acao: 'criar'
		});

		const usuario = await getCurrentUserFunction(ctx);
		if (!usuario) throw new Error('Não autenticado');

		const id = await ctx.db.insert('contratos', {
			...args,
			criadoPor: usuario._id,
			criadoEm: Date.now()
		});

		return id;
	}
});

export const editar = mutation({
	args: {
		id: v.id('contratos'),
		contratadaId: v.optional(v.id('empresas')),
		objeto: v.optional(v.string()),
		numeroNotaEmpenho: v.optional(v.string()),
		responsavelId: v.optional(v.id('funcionarios')),
		departamento: v.optional(v.string()),
		situacao: v.optional(situacaoContrato),
		numeroProcessoLicitatorio: v.optional(v.string()),
		modalidade: v.optional(v.string()),
		numeroContrato: v.optional(v.string()),
		anoContrato: v.optional(v.number()),
		dataInicioVigencia: v.optional(v.string()),
		dataFimVigencia: v.optional(v.string()),
		nomeFiscal: v.optional(v.string()),
		valorTotal: v.optional(v.string()),
		dataAditivoPrazo: v.optional(v.string()),
		diasAvisoVencimento: v.optional(v.number())
	},
	handler: async (ctx, args) => {
		await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
			recurso: 'contratos',
			acao: 'editar'
		});

		const { id, ...campos } = args;

		await ctx.db.patch(id, {
			...campos,
			atualizadoEm: Date.now()
		});
	}
});

export const excluir = mutation({
	args: { id: v.id('contratos') },
	handler: async (ctx, args) => {
		await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
			recurso: 'contratos',
			acao: 'excluir'
		});
		await ctx.db.delete(args.id);
	}
});

export const verificarVencimentos = query({
	args: {},
	handler: async (ctx) => {
		// Esta query pode ser usada por um componente de notificação ou cron job
		// Retorna contratos que estão próximos do vencimento baseados no diasAvisoVencimento

		const hoje = new Date();
		const hojeStr = hoje.toISOString().split('T')[0];

		// Buscar contratos ativos (em execução ou aguardando assinatura)
		const contratos = await ctx.db
			.query('contratos')
			.filter((q) =>
				q.or(
					q.eq(q.field('situacao'), 'em_execucao'),
					q.eq(q.field('situacao'), 'aguardando_assinatura')
				)
			)
			.collect();

		const proximosVencimento = contratos.filter((c) => {
			if (!c.dataFimVigencia) return false;

			const dataFim = new Date(c.dataFimVigencia);
			const dataAviso = new Date(dataFim);
			dataAviso.setDate(dataAviso.getDate() - c.diasAvisoVencimento);

			const dataAvisoStr = dataAviso.toISOString().split('T')[0];

			// Se hoje for maior ou igual a data de aviso e menor que a data fim
			return hojeStr >= dataAvisoStr && hojeStr <= c.dataFimVigencia;
		});

		return proximosVencimento;
	}
});
