<?php
/**
 * Admin menu for the WordPress.org free build.
 *
 * @package CF7MasterPro\Admin
 */

namespace CF7MasterPro\Admin;

defined( 'ABSPATH' ) || exit;

/**
 * Admin menu registration and template rendering.
 */
class AdminMenu {

	const MENU_SLUG        = 'frontierline-forms';
	const SUBMISSIONS_SLUG = 'frontierline-forms-submissions';
	const SETTINGS_SLUG    = 'frontierline-forms-settings';
	const TEMPLATE_DIR     = CF7MP_PLUGIN_DIR . 'templates/admin/';

	/**
	 * Register hooks.
	 */
	public function register() {
		add_action( 'admin_menu', array( $this, 'add_menu' ) );
		add_action( 'admin_init', array( $this, 'maybe_export_csv' ) );
	}

	/**
	 * Handle CSV export before admin HTML output.
	 */
	public function maybe_export_csv() {
		if ( ! is_admin() ) {
			return;
		}
		if ( empty( $_GET['page'] ) || self::SUBMISSIONS_SLUG !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}
		if ( empty( $_GET['export'] ) || 'csv' !== $_GET['export'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
		if ( ! wp_verify_nonce( $nonce, 'cf7mp_export_csv' ) ) {
			wp_die( esc_html__( 'Security check failed.', 'frontierline-forms' ), '', array( 'back_link' => true ) );
		}
		$this->export_submissions_csv();
	}

	/**
	 * Add admin menu.
	 */
	public function add_menu() {
		add_menu_page(
			__( 'Frontierline Forms', 'frontierline-forms' ),
			__( 'Frontierline Forms', 'frontierline-forms' ),
			'manage_options',
			self::MENU_SLUG,
			array( $this, 'render_dashboard' ),
			'dashicons-feedback',
			58
		);

		$pages = array(
			self::SUBMISSIONS_SLUG => array( __( 'Submissions', 'frontierline-forms' ), 'render_submissions' ),
			self::SETTINGS_SLUG    => array( __( 'Settings', 'frontierline-forms' ), 'render_settings' ),
		);

		foreach ( $pages as $slug => $conf ) {
			add_submenu_page(
				self::MENU_SLUG,
				$conf[0],
				$conf[0],
				'manage_options',
				$slug,
				array( $this, $conf[1] )
			);
		}
	}

	/**
	 * Render an admin template.
	 *
	 * @param string $name Template name without extension.
	 * @param array  $vars Template vars.
	 */
	private function render_template( $name, array $vars = array() ) {
		$file = self::TEMPLATE_DIR . $name . '.php';
		if ( ! file_exists( $file ) ) {
			echo '<div class="notice notice-error"><p>Template not found: ' . esc_html( $name ) . '</p></div>';
			return;
		}
		extract( $vars, EXTR_SKIP ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
		include $file;
	}

	/**
	 * Dashboard.
	 */
	public function render_dashboard() {
		$this->render_template(
			'dashboard',
			array(
				'stats' => $this->get_dashboard_stats(),
			)
		);
	}

	/**
	 * Submission list and detail.
	 */
	public function render_submissions() {
		$action = isset( $_GET['action'] ) ? sanitize_key( wp_unslash( $_GET['action'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( 'view' === $action && ! empty( $_GET['id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$this->render_submission_detail( (int) $_GET['id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		$filters = array(
			's'        => isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			'priority' => isset( $_GET['priority'] ) ? sanitize_text_field( wp_unslash( $_GET['priority'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		);
		$total         = $this->count_submissions();
		$display_limit = 10000;

		$this->render_template(
			'submissions',
			array(
				'submissions'   => $this->get_submissions( $filters, $display_limit ),
				'filters'       => $filters,
				'total_count'   => $total,
				'display_limit' => $display_limit,
				'export_url'    => wp_nonce_url(
					admin_url( 'admin.php?page=' . self::SUBMISSIONS_SLUG . '&export=csv' ),
					'cf7mp_export_csv'
				),
			)
		);
	}

	/**
	 * Count submissions.
	 *
	 * @return int
	 */
	private function count_submissions() {
		global $wpdb;
		$table  = $wpdb->prefix . CF7MP_DB_PREFIX . 'submissions';
		$exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); // phpcs:ignore WordPress.DB, PluginCheck.Security.DirectDB.UnescapedDBParameter
		if ( ! $exists ) {
			return 0;
		}
		return (int) $wpdb->get_var( "SELECT COUNT(*) FROM `$table`" ); // phpcs:ignore WordPress.DB, PluginCheck.Security.DirectDB.UnescapedDBParameter
	}

	/**
	 * Render a submission detail.
	 *
	 * @param int $id Submission ID.
	 */
	private function render_submission_detail( $id ) {
		global $wpdb;
		$table = $wpdb->prefix . CF7MP_DB_PREFIX . 'submissions';
		$row   = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM `$table` WHERE id=%d", $id ), ARRAY_A ); // phpcs:ignore WordPress.DB, PluginCheck.Security.DirectDB.UnescapedDBParameter
		if ( ! $row ) {
			echo '<div class="notice notice-error"><p>' . esc_html__( 'Submission not found', 'frontierline-forms' ) . '</p></div>';
			return;
		}
		$formatted  = $this->format_submission_row( $row );
		$raw_fields = $this->decode_form_data( $row['form_data'] ?? '' );
		$meta       = array(
			'ip_address'   => $row['ip_address'] ?? '',
			'referer'      => $row['referer'] ?? '',
			'user_agent'   => $row['user_agent'] ?? '',
			'utm_source'   => $row['utm_source'] ?? '',
			'utm_medium'   => $row['utm_medium'] ?? '',
			'utm_campaign' => $row['utm_campaign'] ?? '',
		);
		$this->render_template(
			'submission-detail',
			array(
				'submission' => $formatted,
				'raw_fields' => $raw_fields,
				'meta'       => $meta,
			)
		);
	}

	/**
	 * Export submissions as CSV.
	 */
	private function export_submissions_csv() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		global $wpdb;
		$table = $wpdb->prefix . CF7MP_DB_PREFIX . 'submissions';
		$rows  = $wpdb->get_results( "SELECT * FROM `$table` ORDER BY created_at DESC LIMIT 10000", ARRAY_A ); // phpcs:ignore WordPress.DB, PluginCheck.Security.DirectDB.UnescapedDBParameter
		if ( ! is_array( $rows ) ) {
			$rows = array();
		}

		while ( ob_get_level() ) {
			ob_end_clean();
		}
		nocache_headers();
		header( 'Content-Type: text/csv; charset=UTF-8' );
		header( 'Content-Disposition: attachment; filename="frontierline-forms-submissions-' . gmdate( 'Ymd-His' ) . '.csv"' );

		echo "\xEF\xBB\xBF";
		$fp = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- Streaming CSV download to output, WP_Filesystem not applicable.
		fputcsv(
			$fp,
			array( 'ID', __( 'Date', 'frontierline-forms' ), __( 'Form', 'frontierline-forms' ), __( 'Sender', 'frontierline-forms' ), __( 'Subject', 'frontierline-forms' ), __( 'Priority', 'frontierline-forms' ), 'IP', 'Referer', 'utm_source', 'utm_medium', 'utm_campaign' )
		);
		foreach ( $rows as $row ) {
			$formatted = $this->format_submission_row( $row );
			fputcsv(
				$fp,
				array(
					$formatted['id'],
					$formatted['created_at'],
					$formatted['form_title'],
					$formatted['sender'],
					$formatted['subject'],
					$formatted['priority_label'],
					$row['ip_address'] ?? '',
					$row['referer'] ?? '',
					$row['utm_source'] ?? '',
					$row['utm_medium'] ?? '',
					$row['utm_campaign'] ?? '',
				)
			);
		}
		exit;
	}

	/**
	 * Settings.
	 */
	public function render_settings() {
		$active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( ! in_array( $active_tab, array( 'general', 'design' ), true ) ) {
			$active_tab = 'general';
		}
		$this->render_template(
			'settings',
			array(
				'settings'   => (array) get_option( 'cf7mp_settings', array() ),
				'cf7mp_active_tab' => $active_tab,
			)
		);
	}

	/**
	 * Dashboard stats.
	 *
	 * @return array
	 */
	private function get_dashboard_stats() {
		global $wpdb;
		$table  = $wpdb->prefix . CF7MP_DB_PREFIX . 'submissions';
		$exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, PluginCheck.Security.DirectDB.UnescapedDBParameter
		if ( ! $exists ) {
			return array( 'month' => 0, 'today' => 0, 'cvr' => '0.0', 'month_diff' => 0 );
		}
		$month = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `$table` WHERE created_at >= DATE_FORMAT(NOW(),'%Y-%m-01')" ); // phpcs:ignore WordPress.DB, PluginCheck.Security.DirectDB.UnescapedDBParameter
		$today = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `$table` WHERE DATE(created_at) = CURDATE()" ); // phpcs:ignore WordPress.DB, PluginCheck.Security.DirectDB.UnescapedDBParameter
		return array(
			'month'      => $month,
			'today'      => $today,
			'cvr'        => '0.0',
			'month_diff' => 0,
		);
	}

	/**
	 * Get submissions.
	 *
	 * @param array $filters Filters.
	 * @param int   $limit Display limit.
	 * @return array
	 */
	private function get_submissions( array $filters, $limit = 10000 ) {
		global $wpdb;
		$table  = $wpdb->prefix . CF7MP_DB_PREFIX . 'submissions';
		$exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); // phpcs:ignore WordPress.DB, PluginCheck.Security.DirectDB.UnescapedDBParameter
		if ( ! $exists ) {
			return array();
		}
		$limit = max( 1, (int) $limit );
		$rows  = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `$table` ORDER BY created_at DESC LIMIT %d", $limit ), ARRAY_A ); // phpcs:ignore WordPress.DB, PluginCheck.Security.DirectDB.UnescapedDBParameter
		if ( ! is_array( $rows ) ) {
			return array();
		}
		return array_map( array( $this, 'format_submission_row' ), $rows );
	}

	/**
	 * Format one submission row.
	 *
	 * @param array $row Raw row.
	 * @return array
	 */
	private function format_submission_row( array $row ) {
		$priority_label = array(
			'high'   => __( 'High', 'frontierline-forms' ),
			'medium' => __( 'Medium', 'frontierline-forms' ),
			'low'    => __( 'Low', 'frontierline-forms' ),
		);
		$data     = $this->decode_form_data( $row['form_data'] ?? '' );
		$priority = $row['priority'] ?? 'low';

		return array(
			'id'             => (int) ( $row['id'] ?? 0 ),
			'created_at'     => $row['created_at'] ?? '',
			'form_title'     => $this->get_cf7_title( (int) ( $row['form_id'] ?? 0 ) ),
			'sender'         => $this->guess_sender( $data ),
			'subject'        => $this->guess_subject( $data ),
			'priority'       => $priority,
			'priority_label' => $priority_label[ $priority ] ?? $priority,
			'category'       => $row['category'] ?? '-',
			'is_new'         => isset( $row['status'] ) && 'new' === $row['status'],
		);
	}

	/**
	 * Decode stored form data.
	 *
	 * @param string $raw Raw JSON.
	 * @return array
	 */
	private function decode_form_data( $raw ) {
		$decoded = json_decode( (string) $raw, true );
		return is_array( $decoded ) ? $decoded : array();
	}

	/**
	 * Get Contact Form 7 title.
	 *
	 * @param int $form_id Form post ID.
	 * @return string
	 */
	private function get_cf7_title( $form_id ) {
		if ( ! $form_id ) {
			return '-';
		}
		$title = get_the_title( $form_id );
		return '' !== $title ? $title : sprintf( '#%d', $form_id );
	}

	/**
	 * Guess sender label.
	 *
	 * @param array $data Form data.
	 * @return string
	 */
	private function guess_sender( array $data ) {
		foreach ( array( 'your-email', 'email', 'mail', 'your-name', 'name' ) as $key ) {
			if ( ! empty( $data[ $key ] ) ) {
				return is_array( $data[ $key ] ) ? implode( ', ', $data[ $key ] ) : (string) $data[ $key ];
			}
		}
		return '-';
	}

	/**
	 * Guess subject label.
	 *
	 * @param array $data Form data.
	 * @return string
	 */
	private function guess_subject( array $data ) {
		foreach ( array( 'your-subject', 'subject', 'title', 'your-message', 'message' ) as $key ) {
			if ( ! empty( $data[ $key ] ) ) {
				$val = is_array( $data[ $key ] ) ? implode( ' ', $data[ $key ] ) : (string) $data[ $key ];
				return mb_substr( $val, 0, 60 );
			}
		}
		return '-';
	}
}
