<?php
/**
 * Plugin Name: Formação/Evento - Taxonomias automáticas (Ano/Mês)
 * Description: Cria e atribui automaticamente os termos de ano e mês (pt-PT) nas taxonomias
 *              correspondentes, com base num campo ACF de data, para os post-types "formacao"
 *              e "evento". Formato de data e taxonomias configuráveis por post-type em
 *              lemondot_config_ano_mes().
 * Version: 1.2
 */

defined( 'ABSPATH' ) || exit;

/**
 * Escreve num ficheiro de log próprio (independente das definições de
 * WP_DEBUG_LOG/php.ini), para garantir que conseguimos ver o que se passa
 * mesmo em hospedagens que não escrevem no wp-content/debug.log.
 */
function lemondot_log( $mensagem ) {
	$linha = '[' . gmdate( 'Y-m-d H:i:s' ) . '] ' . $mensagem . "\n";
	error_log( $linha, 3, WP_CONTENT_DIR . '/lemondot-formacao-debug.log' );
}

/**
 * Garante que o termo existe na taxonomia (cria-o se necessário) e devolve o term_id.
 * Regista cada passo no log para diagnóstico.
 */
function lemondot_garantir_termo_id( $nome, $taxonomia ) {

	if ( ! taxonomy_exists( $taxonomia ) ) {
		lemondot_log( "ERRO: taxonomia '{$taxonomia}' não está registada." );
		return false;
	}

	$existente = get_term_by( 'name', $nome, $taxonomia );

	if ( $existente instanceof WP_Term ) {
		lemondot_log( "Termo '{$nome}' já existe em '{$taxonomia}' com ID {$existente->term_id}." );
		return (int) $existente->term_id;
	}

	lemondot_log( "Termo '{$nome}' não existe em '{$taxonomia}'. A tentar criar com wp_insert_term()..." );

	$inserido = wp_insert_term( $nome, $taxonomia );

	if ( is_wp_error( $inserido ) ) {
		// Se o erro for "já existe", tenta obter o ID mesmo assim.
		if ( 'term_exists' === $inserido->get_error_code() ) {
			$id_existente = $inserido->get_error_data( 'term_exists' );
			lemondot_log( "wp_insert_term devolveu 'term_exists', ID = " . var_export( $id_existente, true ) );
			if ( $id_existente ) {
				return (int) $id_existente;
			}
		}

		lemondot_log( "ERRO ao criar termo '{$nome}' em '{$taxonomia}': " . $inserido->get_error_message() );
		return false;
	}

	lemondot_log( "Termo '{$nome}' criado em '{$taxonomia}' com ID {$inserido['term_id']}." );

	return (int) $inserido['term_id'];
}

/**
 * Nomes dos meses por extenso, em pt-PT.
 */
function lemondot_meses_pt() {
	return array(
		1  => 'Janeiro',
		2  => 'Fevereiro',
		3  => 'Março',
		4  => 'Abril',
		5  => 'Maio',
		6  => 'Junho',
		7  => 'Julho',
		8  => 'Agosto',
		9  => 'Setembro',
		10 => 'Outubro',
		11 => 'Novembro',
		12 => 'Dezembro',
	);
}

/**
 * Normaliza texto para comparação (minúsculas, sem acentos, sem espaços a mais).
 */
function lemondot_normalizar_texto( $texto ) {
	$texto = mb_strtolower( trim( $texto ), 'UTF-8' );
	if ( function_exists( 'remove_accents' ) ) {
		$texto = remove_accents( $texto );
	}
	return $texto;
}

/**
 * Devolve o número do mês (1-12) a partir do nome em português (com ou sem acentos).
 */
function lemondot_numero_mes_pt( $nome_mes ) {
	$alvo = lemondot_normalizar_texto( $nome_mes );

	foreach ( lemondot_meses_pt() as $numero => $nome ) {
		if ( lemondot_normalizar_texto( $nome ) === $alvo ) {
			return $numero;
		}
	}

	return false;
}

/**
 * O ACF está a devolver a data com o mês por extenso em português (ex: "9 Setembro, 2026"),
 * e DateTime::createFromFormat() não consegue interpretar nomes de meses em português
 * (o especificador "F" só reconhece nomes em inglês). Por isso, esta função interpreta
 * a data manualmente: dia, nome do mês em português, e ano.
 */
function lemondot_parse_data_pt( $valor ) {
	if ( ! preg_match( '/^\s*(\d{1,2})\s+([^\d,]+?)\s*,\s*(\d{4})\s*$/u', $valor, $partes ) ) {
		return false;
	}

	$dia        = (int) $partes[1];
	$mes_numero = lemondot_numero_mes_pt( $partes[2] );
	$ano        = (int) $partes[3];

	if ( ! $mes_numero ) {
		return false;
	}

	$data = DateTime::createFromFormat( 'Y-n-j', "{$ano}-{$mes_numero}-{$dia}" );

	return $data instanceof DateTime ? $data : false;
}

/**
 * Configuração: para cada post-type, o slug do campo ACF de data (formato d/m/Y)
 * e os slugs das taxonomias de ano e mês.
 * Para adicionar outro post-type no futuro, basta acrescentar uma entrada aqui.
 */
function lemondot_config_ano_mes() {
	return array(
		'formacao' => array(
			'campo_data'   => 'datainicio_formacao',
			'formato_data' => 'j F, Y',
			'tax_ano'      => 'ano_formacao',
			'tax_mes'      => 'mes_formacao',
		),
		'evento'   => array(
			'campo_data'   => 'data_evento',
			'formato_data' => 'j F, Y',
			'tax_ano'      => 'ano_evento',
			'tax_mes'      => 'mes_evento',
		),
	);
}

add_action( 'acf/save_post', 'lemondot_definir_ano_mes', 20 );

function lemondot_definir_ano_mes( $post_id ) {

	// Ignora chamadas do ACF que não sejam de um post normal (ex: páginas de opções).
	if ( ! is_numeric( $post_id ) ) {
		return;
	}

	$post_type = get_post_type( $post_id );
	$config    = lemondot_config_ano_mes();

	// Só atua nos post-types configurados.
	if ( ! isset( $config[ $post_type ] ) ) {
		return;
	}

	$campo_data   = $config[ $post_type ]['campo_data'];
	$formato_data = $config[ $post_type ]['formato_data'];
	$tax_ano      = $config[ $post_type ]['tax_ano'];
	$tax_mes      = $config[ $post_type ]['tax_mes'];

	// Ignora autosaves e revisões.
	if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
		return;
	}

	lemondot_log( "--- Post {$post_id} ({$post_type}): a correr lemondot_definir_ano_mes ---" );

	// Obtém o valor do campo ACF (já gravado nesta fase, prioridade 20).
	$data_valor = get_field( $campo_data, $post_id );

	lemondot_log( "Post {$post_id}: valor bruto de {$campo_data} = " . var_export( $data_valor, true ) );

	if ( empty( $data_valor ) ) {
		lemondot_log( "Post {$post_id}: valor vazio, a sair." );
		return;
	}

	// Tenta primeiro interpretar como "dia Mês, Ano" com o mês por extenso em português
	// (é o que o ACF está a devolver, ex: "9 Setembro, 2026").
	$data = lemondot_parse_data_pt( $data_valor );

	// Caso não resulte, tenta o formato configurado diretamente (ex: para datas puramente numéricas).
	if ( ! $data ) {
		$data = DateTime::createFromFormat( $formato_data, $data_valor );
	}

	if ( ! $data instanceof DateTime ) {
		$erros = DateTime::getLastErrors();
		lemondot_log( "Post {$post_id}: falha ao converter data '{$data_valor}' (formato configurado: '{$formato_data}'). Erros: " . var_export( $erros, true ) );
		return;
	}

	// --- Taxonomia de ano ---
	$ano = $data->format( 'Y' );

	$ano_id = lemondot_garantir_termo_id( $ano, $tax_ano );

	if ( $ano_id ) {
		$resultado_ano = wp_set_post_terms( $post_id, array( $ano_id ), $tax_ano, false );
		lemondot_log( "Post {$post_id}: atribuição ano (ID {$ano_id}) em '{$tax_ano}' -> " . var_export( $resultado_ano, true ) );
	}

	// --- Taxonomia de mês (nome por extenso, pt-PT) ---
	$mes_numero = (int) $data->format( 'n' );
	$mes_nome   = lemondot_meses_pt()[ $mes_numero ];

	lemondot_log( "Post {$post_id}: mes_numero = {$mes_numero} | mes_nome = {$mes_nome}" );

	$mes_id = lemondot_garantir_termo_id( $mes_nome, $tax_mes );

	if ( $mes_id ) {
		$resultado_mes = wp_set_post_terms( $post_id, array( $mes_id ), $tax_mes, false );
		lemondot_log( "Post {$post_id}: atribuição mês (ID {$mes_id}) em '{$tax_mes}' -> " . var_export( $resultado_mes, true ) );
	}
}

/**
 * Ordena os termos das taxonomias de mês pela sequência do ano (Janeiro -> Dezembro)
 * em vez de ordem alfabética. Afeta qualquer get_terms() para estas taxonomias
 * (filtros de página, widgets, etc.), independentemente de quem faz a chamada.
 */
add_filter( 'terms_clauses', 'lemondot_ordenar_termos_mes', 10, 3 );

function lemondot_ordenar_termos_mes( $clauses, $taxonomies, $args ) {
	global $wpdb;

	$taxonomias_de_mes = array( 'mes_formacao', 'mes_evento' );

	// Só altera a ordenação se a consulta for exclusivamente a uma destas taxonomias de mês.
	if ( 1 !== count( $taxonomies ) || ! in_array( $taxonomies[0], $taxonomias_de_mes, true ) ) {
		return $clauses;
	}

	$ordem = array(
		'janeiro'   => 1,
		'fevereiro' => 2,
		'marco'     => 3,
		'abril'     => 4,
		'maio'      => 5,
		'junho'     => 6,
		'julho'     => 7,
		'agosto'    => 8,
		'setembro'  => 9,
		'outubro'   => 10,
		'novembro'  => 11,
		'dezembro'  => 12,
	);

	$case = 'CASE t.slug ';
	foreach ( $ordem as $slug => $numero ) {
		$case .= $wpdb->prepare( 'WHEN %s THEN %d ', $slug, $numero );
	}
	$case .= 'ELSE 99 END';

	$clauses['orderby'] = "ORDER BY {$case}";
	$clauses['order']   = '';

	return $clauses;
}
