<?php
/**
 * Portfolio settings screen and option contract.
 *
 * @package GustavoPortfolioCore
 */

defined( 'ABSPATH' ) || exit;

/**
 * Owns the shared option consumed by the portfolio theme.
 */
final class GSO_Portfolio_Settings {
	const OPTION_NAME = 'gustavoo_portfolio_settings';
	const OPTION_GROUP = 'gustavoo_portfolio_settings_group';
	const PAGE_SLUG = 'gso-portfolio-settings';

	/**
	 * Register hooks.
	 *
	 * @return void
	 */
	public static function init() {
		add_action( 'admin_menu', array( __CLASS__, 'add_settings_page' ), 20 );
		add_action( 'admin_init', array( __CLASS__, 'register_settings' ) );
		add_filter( 'plugin_action_links_' . plugin_basename( GSO_PORTFOLIO_CORE_FILE ), array( __CLASS__, 'plugin_action_links' ) );
	}

	/**
	 * Defaults based on the existing gustavoo.me content.
	 *
	 * @return array<string, mixed>
	 */
	public static function defaults() {
		return array(
			'hero_eyebrow'         => __( 'Desenvolvimento de ponta a ponta', 'gustavoo-portfolio-core' ),
			'hero_title'           => __( 'Transformo ideias em produtos digitais sólidos.', 'gustavoo-portfolio-core' ),
			'hero_description'     => __( 'Gustavo, Desenvolvedor Full Stack Sênior. Web, mobile, infraestrutura e automação para tirar projetos do papel e fazê-los crescer.', 'gustavoo-portfolio-core' ),
			'hero_primary_label'   => __( 'Ver projetos', 'gustavoo-portfolio-core' ),
			'hero_primary_url'     => '#projetos',
			'hero_secondary_label' => __( 'Fale comigo', 'gustavoo-portfolio-core' ),
			'hero_secondary_url'   => '#contato',
			'about_title'          => __( 'Responsabilidade técnica do planejamento à produção.', 'gustavoo-portfolio-core' ),
			'about_text'           => __( 'Mais do que escrever código, meu objetivo é garantir que seu projeto saia do papel e funcione exatamente como planejado. Assumo a responsabilidade técnica de ponta a ponta para que você foque no que importa: crescer.', 'gustavoo-portfolio-core' ),
			'about_secondary_text' => __( 'Já participei do desenvolvimento e lançamento de múltiplos projetos digitais, atuando da arquitetura técnica à divulgação e ao crescimento das plataformas. Essa combinação de visão técnica e entendimento de mercado orienta cada entrega.', 'gustavoo-portfolio-core' ),
			'contact_heading'      => __( 'Tem um projeto em mente?', 'gustavoo-portfolio-core' ),
			'contact_text'         => __( 'Conte o que você precisa construir ou melhorar. Responderei com os próximos passos para transformar a ideia em uma entrega concreta.', 'gustavoo-portfolio-core' ),
			'contact_form_id'      => 0,
			'newsletter_heading'   => __( 'Ideias úteis, direto na sua caixa de entrada.', 'gustavoo-portfolio-core' ),
			'newsletter_text'      => __( 'Receba conteúdos sobre desenvolvimento, produto, infraestrutura e automação. Sem ruído e sem spam.', 'gustavoo-portfolio-core' ),
			'newsletter_form_id'   => 0,
			'projects_title'       => __( 'Projetos selecionados', 'gustavoo-portfolio-core' ),
			'projects_text'        => __( 'Uma seleção de produtos, experiências e soluções que ajudei a colocar no mundo.', 'gustavoo-portfolio-core' ),
			'projects_limit'       => 6,
			'blog_title'           => __( 'Código, produto e bastidores', 'gustavoo-portfolio-core' ),
			'blog_text'            => __( 'Análises práticas sobre desenvolvimento, infraestrutura, automação e crescimento de produtos digitais.', 'gustavoo-portfolio-core' ),
			'blog_limit'           => 4,
			'email'                => 'contato@gustavoo.me',
			'whatsapp'             => '+55 31 99516-8069',
			'whatsapp_message'     => __( 'Olá! Gostaria de falar sobre um projeto.', 'gustavoo-portfolio-core' ),
			'github_url'           => 'https://github.com/gustavooth',
			'linkedin_url'         => '',
			'instagram_url'        => '',
			'availability_label'   => __( 'Disponível para novos projetos', 'gustavoo-portfolio-core' ),
		);
	}

	/**
	 * Add missing defaults without overwriting existing values.
	 *
	 * @return void
	 */
	public static function ensure_defaults() {
		$existing = get_option( self::OPTION_NAME, null );

		if ( null === $existing || ! is_array( $existing ) ) {
			add_option( self::OPTION_NAME, self::defaults(), '', false );
			return;
		}

		$merged = array_merge( self::defaults(), $existing );
		if ( $merged !== $existing ) {
			update_option( self::OPTION_NAME, $merged, false );
		}
	}

	/**
	 * Return settings merged with defaults.
	 *
	 * @return array<string, mixed>
	 */
	public static function get_settings() {
		$settings = get_option( self::OPTION_NAME, array() );

		return array_merge( self::defaults(), is_array( $settings ) ? $settings : array() );
	}

	/**
	 * Add the Settings submenu below Portfolio.
	 *
	 * @return void
	 */
	public static function add_settings_page() {
		add_submenu_page(
			'edit.php?post_type=' . GSO_Projects::POST_TYPE,
			__( 'Configurações do portfólio', 'gustavoo-portfolio-core' ),
			__( 'Configurações', 'gustavoo-portfolio-core' ),
			'manage_options',
			self::PAGE_SLUG,
			array( __CLASS__, 'render_settings_page' )
		);
	}

	/**
	 * Register the option, sections and fields.
	 *
	 * @return void
	 */
	public static function register_settings() {
		register_setting(
			self::OPTION_GROUP,
			self::OPTION_NAME,
			array(
				'type'              => 'array',
				'description'       => __( 'Configurações compartilhadas pelo tema Gustavo Portfolio.', 'gustavoo-portfolio-core' ),
				'sanitize_callback' => array( __CLASS__, 'sanitize_settings' ),
				'default'           => self::defaults(),
			)
		);

		$sections = self::sections();
		$fields   = self::fields();

		foreach ( $sections as $section_id => $section ) {
			add_settings_section(
				$section_id,
				$section['title'],
				array( __CLASS__, 'render_section_description' ),
				self::PAGE_SLUG,
				array( 'description' => $section['description'] )
			);
		}

		foreach ( $fields as $key => $field ) {
			add_settings_field(
				'gso-setting-' . str_replace( '_', '-', $key ),
				$field['label'],
				array( __CLASS__, 'render_field' ),
				self::PAGE_SLUG,
				$field['section'],
				array_merge( $field, array( 'key' => $key ) )
			);
		}
	}

	/**
	 * Settings page section definitions.
	 *
	 * @return array<string, array<string, string>>
	 */
	private static function sections() {
		return array(
			'gso-settings-hero'       => array(
				'title'       => __( 'Hero', 'gustavoo-portfolio-core' ),
				'description' => __( 'Mensagem principal e chamadas para ação da página inicial.', 'gustavoo-portfolio-core' ),
			),
			'gso-settings-about'      => array(
				'title'       => __( 'Sobre', 'gustavoo-portfolio-core' ),
				'description' => __( 'Apresentação profissional exibida na seção Sobre.', 'gustavoo-portfolio-core' ),
			),
			'gso-settings-content'    => array(
				'title'       => __( 'Projetos e blog', 'gustavoo-portfolio-core' ),
				'description' => __( 'Títulos, textos de apoio e limites das listagens da página inicial.', 'gustavoo-portfolio-core' ),
			),
			'gso-settings-contact'    => array(
				'title'       => __( 'Contato', 'gustavoo-portfolio-core' ),
				'description' => __( 'Canais diretos e formulário principal do Fluent Forms.', 'gustavoo-portfolio-core' ),
			),
			'gso-settings-newsletter' => array(
				'title'       => __( 'Newsletter', 'gustavoo-portfolio-core' ),
				'description' => __( 'Conteúdo e formulário usados pelo CTA e pelo widget de newsletter.', 'gustavoo-portfolio-core' ),
			),
			'gso-settings-social'     => array(
				'title'       => __( 'Redes sociais', 'gustavoo-portfolio-core' ),
				'description' => __( 'Perfis públicos exibidos no tema.', 'gustavoo-portfolio-core' ),
			),
		);
	}

	/**
	 * Settings field schema.
	 *
	 * @return array<string, array<string, mixed>>
	 */
	private static function fields() {
		return array(
			'hero_eyebrow'         => self::field( 'gso-settings-hero', __( 'Sobretítulo', 'gustavoo-portfolio-core' ), 'text' ),
			'hero_title'           => self::field( 'gso-settings-hero', __( 'Título', 'gustavoo-portfolio-core' ), 'text' ),
			'hero_description'     => self::field( 'gso-settings-hero', __( 'Descrição', 'gustavoo-portfolio-core' ), 'textarea' ),
			'hero_primary_label'   => self::field( 'gso-settings-hero', __( 'CTA principal — texto', 'gustavoo-portfolio-core' ), 'text' ),
			'hero_primary_url'     => self::field( 'gso-settings-hero', __( 'CTA principal — destino', 'gustavoo-portfolio-core' ), 'link', __( 'Aceita URL HTTP(S), mailto:, tel:, caminho relativo ou âncora como #projetos.', 'gustavoo-portfolio-core' ) ),
			'hero_secondary_label' => self::field( 'gso-settings-hero', __( 'CTA secundário — texto', 'gustavoo-portfolio-core' ), 'text' ),
			'hero_secondary_url'   => self::field( 'gso-settings-hero', __( 'CTA secundário — destino', 'gustavoo-portfolio-core' ), 'link', __( 'Aceita URL HTTP(S), mailto:, tel:, caminho relativo ou âncora.', 'gustavoo-portfolio-core' ) ),
			'about_title'          => self::field( 'gso-settings-about', __( 'Título', 'gustavoo-portfolio-core' ), 'text' ),
			'about_text'           => self::field( 'gso-settings-about', __( 'Texto', 'gustavoo-portfolio-core' ), 'textarea' ),
			'projects_title'       => self::field( 'gso-settings-content', __( 'Projetos — título', 'gustavoo-portfolio-core' ), 'text' ),
			'projects_text'        => self::field( 'gso-settings-content', __( 'Projetos — texto', 'gustavoo-portfolio-core' ), 'textarea' ),
			'projects_limit'       => self::field( 'gso-settings-content', __( 'Projetos — quantidade', 'gustavoo-portfolio-core' ), 'number', __( 'Entre 1 e 24.', 'gustavoo-portfolio-core' ), array( 'min' => 1, 'max' => 24 ) ),
			'blog_title'           => self::field( 'gso-settings-content', __( 'Blog — título', 'gustavoo-portfolio-core' ), 'text' ),
			'blog_text'            => self::field( 'gso-settings-content', __( 'Blog — texto', 'gustavoo-portfolio-core' ), 'textarea' ),
			'blog_limit'           => self::field( 'gso-settings-content', __( 'Blog — quantidade', 'gustavoo-portfolio-core' ), 'number', __( 'Entre 1 e 24.', 'gustavoo-portfolio-core' ), array( 'min' => 1, 'max' => 24 ) ),
			'contact_heading'      => self::field( 'gso-settings-contact', __( 'Título', 'gustavoo-portfolio-core' ), 'text' ),
			'contact_text'         => self::field( 'gso-settings-contact', __( 'Texto', 'gustavoo-portfolio-core' ), 'textarea' ),
			'contact_form_id'      => self::field( 'gso-settings-contact', __( 'ID do formulário de contato', 'gustavoo-portfolio-core' ), 'number', __( 'ID numérico do Fluent Forms. O seed preenche este campo quando possível.', 'gustavoo-portfolio-core' ), array( 'min' => 0 ) ),
			'email'                => self::field( 'gso-settings-contact', __( 'E-mail', 'gustavoo-portfolio-core' ), 'email' ),
			'whatsapp'             => self::field( 'gso-settings-contact', __( 'WhatsApp', 'gustavoo-portfolio-core' ), 'tel', __( 'Inclua o DDI, por exemplo +55 31 99999-9999.', 'gustavoo-portfolio-core' ) ),
			'whatsapp_message'     => self::field( 'gso-settings-contact', __( 'WhatsApp — mensagem inicial', 'gustavoo-portfolio-core' ), 'textarea', __( 'Texto que será preenchido automaticamente ao abrir o botão flutuante.', 'gustavoo-portfolio-core' ) ),
			'newsletter_heading'   => self::field( 'gso-settings-newsletter', __( 'Título', 'gustavoo-portfolio-core' ), 'text' ),
			'newsletter_text'      => self::field( 'gso-settings-newsletter', __( 'Texto', 'gustavoo-portfolio-core' ), 'textarea' ),
			'newsletter_form_id'   => self::field( 'gso-settings-newsletter', __( 'ID do formulário de newsletter', 'gustavoo-portfolio-core' ), 'number', __( 'ID numérico do Fluent Forms. O seed preenche este campo quando possível.', 'gustavoo-portfolio-core' ), array( 'min' => 0 ) ),
			'github_url'           => self::field( 'gso-settings-social', __( 'GitHub', 'gustavoo-portfolio-core' ), 'url' ),
			'linkedin_url'         => self::field( 'gso-settings-social', __( 'LinkedIn', 'gustavoo-portfolio-core' ), 'url' ),
			'instagram_url'        => self::field( 'gso-settings-social', __( 'Instagram', 'gustavoo-portfolio-core' ), 'url' ),
		);
	}

	/**
	 * Build one field definition.
	 *
	 * @param string               $section     Section ID.
	 * @param string               $label       Label.
	 * @param string               $type        Field type.
	 * @param string               $description Help text.
	 * @param array<string, mixed> $extra       Extra attributes.
	 * @return array<string, mixed>
	 */
	private static function field( $section, $label, $type, $description = '', $extra = array() ) {
		return array_merge(
			array(
				'section'     => $section,
				'label'       => $label,
				'type'        => $type,
				'description' => $description,
			),
			$extra
		);
	}

	/**
	 * Sanitize every documented setting and retain unknown extension keys.
	 *
	 * @param mixed $input Raw submitted option.
	 * @return array<string, mixed>
	 */
	public static function sanitize_settings( $input ) {
		$current = get_option( self::OPTION_NAME, array() );
		$output  = array_merge( self::defaults(), is_array( $current ) ? $current : array() );
		$input   = is_array( $input ) ? $input : array();

		foreach ( self::fields() as $key => $field ) {
			$value = $input[ $key ] ?? '';

			switch ( $field['type'] ) {
				case 'textarea':
					$output[ $key ] = sanitize_textarea_field( $value );
					break;
				case 'email':
					$output[ $key ] = sanitize_email( $value );
					break;
				case 'tel':
					$output[ $key ] = self::sanitize_phone( $value );
					break;
				case 'url':
					$output[ $key ] = self::sanitize_public_url( $value );
					break;
				case 'link':
					$output[ $key ] = self::sanitize_link( $value );
					break;
				case 'number':
					$number = absint( $value );
					$min    = isset( $field['min'] ) ? absint( $field['min'] ) : 0;
					$max    = isset( $field['max'] ) ? absint( $field['max'] ) : PHP_INT_MAX;
					$output[ $key ] = min( $max, max( $min, $number ) );
					break;
				default:
					$output[ $key ] = sanitize_text_field( $value );
			}
		}

		return $output;
	}

	/**
	 * Sanitize a public social URL.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	private static function sanitize_public_url( $value ) {
		$url = esc_url_raw( trim( (string) $value ), array( 'http', 'https' ) );

		return $url && wp_http_validate_url( $url ) ? $url : '';
	}

	/**
	 * Sanitize a CTA link, including safe same-page anchors.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	private static function sanitize_link( $value ) {
		$value = trim( sanitize_text_field( $value ) );

		if ( preg_match( '/^#[A-Za-z][A-Za-z0-9_:.\-]*$/', $value ) ) {
			return $value;
		}

		return esc_url_raw( $value, array( 'http', 'https', 'mailto', 'tel' ) );
	}

	/**
	 * Keep common telephone punctuation and discard everything else.
	 *
	 * @param mixed $value Raw phone value.
	 * @return string
	 */
	private static function sanitize_phone( $value ) {
		$value = sanitize_text_field( $value );
		$value = preg_replace( '/[^0-9+()\-\s]/', '', $value );

		return is_string( $value ) ? trim( $value ) : '';
	}

	/**
	 * Render a section introduction.
	 *
	 * @param array<string, mixed> $args Section arguments.
	 * @return void
	 */
	public static function render_section_description( $args ) {
		if ( ! empty( $args['description'] ) ) {
			echo '<p>' . esc_html( $args['description'] ) . '</p>';
		}
	}

	/**
	 * Render a settings field from its schema.
	 *
	 * @param array<string, mixed> $args Field arguments.
	 * @return void
	 */
	public static function render_field( $args ) {
		$settings = self::get_settings();
		$key      = $args['key'];
		$value    = $settings[ $key ] ?? '';
		$id       = 'gso-setting-' . str_replace( '_', '-', $key );
		$name     = self::OPTION_NAME . '[' . $key . ']';

		if ( 'textarea' === $args['type'] ) {
			printf(
				'<textarea class="large-text" id="%1$s" name="%2$s" rows="4">%3$s</textarea>',
				esc_attr( $id ),
				esc_attr( $name ),
				esc_textarea( (string) $value )
			);
		} else {
			$html_type = in_array( $args['type'], array( 'email', 'number', 'tel', 'url' ), true ) ? $args['type'] : 'text';
			$attrs     = '';

			if ( isset( $args['min'] ) ) {
				$attrs .= ' min="' . esc_attr( (string) $args['min'] ) . '"';
			}
			if ( isset( $args['max'] ) ) {
				$attrs .= ' max="' . esc_attr( (string) $args['max'] ) . '"';
			}

			printf(
				'<input class="%1$s" id="%2$s" name="%3$s" type="%4$s" value="%5$s"%6$s>',
				'number' === $html_type ? 'small-text' : 'regular-text',
				esc_attr( $id ),
				esc_attr( $name ),
				esc_attr( $html_type ),
				esc_attr( (string) $value ),
				$attrs // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes are assembled from escaped integers.
			);
		}

		if ( ! empty( $args['description'] ) ) {
			echo '<p class="description">' . esc_html( $args['description'] ) . '</p>';
		}
	}

	/**
	 * Render the admin settings page.
	 *
	 * @return void
	 */
	public static function render_settings_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		?>
		<div class="wrap">
			<h1><?php esc_html_e( 'Configurações do portfólio', 'gustavoo-portfolio-core' ); ?></h1>
			<p><?php esc_html_e( 'Estes valores são compartilhados com o tema e ficam preservados ao trocar a apresentação visual.', 'gustavoo-portfolio-core' ); ?></p>
			<?php self::render_seed_status(); ?>
			<form action="options.php" method="post">
				<?php
				settings_fields( self::OPTION_GROUP );
				do_settings_sections( self::PAGE_SLUG );
				submit_button();
				?>
			</form>
		</div>
		<?php
	}

	/**
	 * Render a concise status for optional form integrations.
	 *
	 * @return void
	 */
	private static function render_seed_status() {
		$state           = GSO_Seeder::get_state();
		$fluent_forms    = class_exists( '\\FluentForm\\App\\Models\\Form' );
		$fluent_crm      = function_exists( 'FluentCrmApi' );
		$contact_id      = absint( $state['contact_form_id'] ?? 0 );
		$newsletter_id   = absint( $state['newsletter_form_id'] ?? 0 );
		$feeds_installed = ! empty( $state['crm_feeds'] );
		?>
		<div class="notice notice-info inline">
			<p><strong><?php esc_html_e( 'Integrações automáticas', 'gustavoo-portfolio-core' ); ?></strong></p>
			<ul>
				<li><?php echo esc_html( sprintf( 'Fluent Forms: %s', $fluent_forms ? __( 'ativo', 'gustavoo-portfolio-core' ) : __( 'inativo', 'gustavoo-portfolio-core' ) ) ); ?></li>
				<li><?php echo esc_html( sprintf( 'Formulário de contato: %s', $contact_id ? '#' . $contact_id : __( 'aguardando', 'gustavoo-portfolio-core' ) ) ); ?></li>
				<li><?php echo esc_html( sprintf( 'Formulário de newsletter: %s', $newsletter_id ? '#' . $newsletter_id : __( 'aguardando', 'gustavoo-portfolio-core' ) ) ); ?></li>
				<li><?php echo esc_html( sprintf( 'FluentCRM: %s', $fluent_crm ? ( $feeds_installed ? __( 'feeds configurados', 'gustavoo-portfolio-core' ) : __( 'ativo; configuração pendente', 'gustavoo-portfolio-core' ) ) : __( 'inativo', 'gustavoo-portfolio-core' ) ) ); ?></li>
			</ul>
		</div>
		<?php
	}

	/**
	 * Add a shortcut from the Plugins screen.
	 *
	 * @param array<int, string> $links Existing links.
	 * @return array<int, string>
	 */
	public static function plugin_action_links( $links ) {
		$url = admin_url( 'edit.php?post_type=' . GSO_Projects::POST_TYPE . '&page=' . self::PAGE_SLUG );

		array_unshift(
			$links,
			'<a href="' . esc_url( $url ) . '">' . esc_html__( 'Configurações', 'gustavoo-portfolio-core' ) . '</a>'
		);

		return $links;
	}
}
