<?php
/**
 * Copyright (C) 2026 Plugixa (https://plugixa.com)
 * License: GNU General Public License v2 or later
 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
 */

namespace PlugixaRecipe\Frontend;

// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.SlowDBQuery, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom-table data layer: table identifiers are built with $wpdb->prefix and are never user input; all request values are bound via $wpdb->prepare(); ORDER BY / LIMIT fragments come out of internal allow-list maps; content reads go through PlugixaRecipe\Cache (the static sniff cannot trace caching through the wrapper); meta_key/meta_value are dedicated plugin columns, not WP_Query.

defined( 'ABSPATH' ) || exit;

/**
 * Print Class - Handles print-friendly recipe output.
 *
 * Registers a rewrite rule for /recipe-print/{id} that outputs a clean,
 * ad-free HTML page suitable for printing with recipe details.
 */
class RecipePrint {

    /**
     * Initialize print route hooks.
     */
    public function init(): void {
        add_action('init', [$this, 'register_rewrite_rules']);
        add_filter('query_vars', [$this, 'register_query_vars']);
        add_action('template_redirect', [$this, 'handle_print_request']);
    }

    /**
     * Register the print rewrite rule.
     */
    public function register_rewrite_rules(): void {
        add_rewrite_rule(
            '^recipe-print/(\d+)/?$',
            'index.php?pxr_print_recipe=$matches[1]',
            'top'
        );
    }

    /**
     * Register custom query variables.
     */
    public function register_query_vars(array $vars): array {
        $vars[] = 'pxr_print_recipe';
        return $vars;
    }

    /**
     * Handle the print request and output print-friendly HTML.
     */
    public function handle_print_request(): void {
        $recipe_id = get_query_var('pxr_print_recipe');
        if (empty($recipe_id)) {
            return;
        }

        $recipe_id = (int) $recipe_id;
        $recipe = $this->get_recipe($recipe_id);

        if (!$recipe) {
            wp_die(
                esc_html__('Recipe not found.', 'plugixarecipe'),
                esc_html__('Recipe Not Found', 'plugixarecipe'),
                ['response' => 404]
            );
        }

        // Check if printing is enabled
        $settings = (array) get_option('plugixarecipe_settings', []);
        if (isset($settings['enable_print']) && !$settings['enable_print']) {
            wp_die(
                esc_html__('Printing is not available for this recipe.', 'plugixarecipe'),
                esc_html__('Print Disabled', 'plugixarecipe'),
                ['response' => 403]
            );
        }

        // Try loading a custom template first
        $template = PLUGIXARECIPE_PATH . 'templates/print.php';
        if (file_exists($template)) {
            $data = $this->prepare_print_data($recipe);
            unset($recipe);
            extract($data, EXTR_SKIP);
            include $template;
            exit;
        }

        // Inline print output
        $this->render_print_html($recipe);
        exit;
    }

    /**
     * Prepare data for the print template.
     *
     * Enriches the raw DB array with computed fields (image_url, permalink,
     * grouped ingredients/instructions, nutrition, cuisine) and casts to
     * object so templates can use $recipe->title syntax.
     */
    private function prepare_print_data(array $recipe): array {
        $recipe_id = (int) $recipe['id'];

        // Image URL from attachment ID.
        if (!empty($recipe['image_id'])) {
            $recipe['image_url'] = wp_get_attachment_image_url((int) $recipe['image_id'], 'medium_large') ?: '';
        } else {
            $recipe['image_url'] = '';
        }

        // Permalink.
        $slug = sanitize_title($recipe['title'] ?? '');
        $recipe['permalink'] = home_url("/recipe/{$recipe_id}/{$slug}/");

        // Grouped ingredients & instructions.
        $recipe['ingredient_groups']  = $this->group_ingredients($this->get_ingredients($recipe_id));
        $recipe['instruction_groups'] = $this->group_instructions($this->get_instructions($recipe_id));

        // Nutrition (cast to object for $nutrition->calories syntax).
        $nutrition = $this->get_nutrition($recipe_id);
        $recipe['nutrition'] = $nutrition ? (object) $nutrition : null;

        // Cuisine name from first assigned cuisine.
        $cuisines = $this->get_cuisines($recipe_id);
        $recipe['cuisine'] = !empty($cuisines) ? $cuisines[0]['name'] : '';

        return [
            'recipe'    => (object) $recipe,
            'site_name' => get_bloginfo('name'),
            'site_url'  => home_url(),
        ];
    }

    /**
     * Group ingredient rows by group_name, mapping DB columns to template fields.
     */
    private function group_ingredients(array $rows): array {
        $groups  = [];
        $current = null;

        foreach ($rows as $row) {
            $name = $row['group_name'] ?? '';
            if ($name !== $current) {
                $current  = $name;
                $groups[] = (object) ['name' => $current, 'items' => []];
            }
            $row['text']   = $row['name'] ?? '';
            $row['amount'] = $row['quantity'] ?? '';
            $groups[count($groups) - 1]->items[] = (object) $row;
        }

        return $groups;
    }

    /**
     * Group instruction rows by group_name, mapping DB columns to template fields.
     */
    private function group_instructions(array $rows): array {
        $groups  = [];
        $current = null;

        foreach ($rows as $row) {
            $name = $row['group_name'] ?? '';
            if ($name !== $current) {
                $current  = $name;
                $groups[] = (object) ['name' => $current, 'steps' => []];
            }
            $row['text']      = $row['instruction_text'] ?? '';
            $row['image_url'] = !empty($row['image_id'])
                ? wp_get_attachment_image_url((int) $row['image_id'], 'medium')
                : '';
            $groups[count($groups) - 1]->steps[] = (object) $row;
        }

        return $groups;
    }

    /**
     * Render the inline print-friendly HTML page.
     */
    private function render_print_html(array $recipe): void {
        $recipe_id = (int) $recipe['id'];
        $ingredients = $this->get_ingredients($recipe_id);
        $instructions = $this->get_instructions($recipe_id);
        $nutrition = $this->get_nutrition($recipe_id);
        $categories = $this->get_categories($recipe_id);
        $cuisines = $this->get_cuisines($recipe_id);
        $image_url = '';

        if (!empty($recipe['image_id'])) {
            $image_url = wp_get_attachment_image_url((int) $recipe['image_id'], 'medium_large') ?: '';
        }

        $site_name = get_bloginfo('name');
        ?>
<!DOCTYPE html>
<html lang="<?php echo esc_attr(get_locale()); ?>">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php echo esc_html($recipe['title']); ?> - <?php echo esc_html($site_name); ?></title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: Georgia, 'Times New Roman', serif;
            color: #333;
            line-height: 1.6;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px 30px;
            background: #fff;
        }
        .print-header {
            text-align: center;
            border-bottom: 2px solid #333;
            padding-bottom: 20px;
            margin-bottom: 20px;
        }
        .print-header h1 {
            font-size: 28px;
            margin-bottom: 8px;
        }
        .print-meta {
            font-size: 14px;
            color: #666;
        }
        .print-meta span { margin: 0 10px; }
        .print-image {
            text-align: center;
            margin: 20px 0;
        }
        .print-image img {
            max-width: 100%;
            max-height: 400px;
            object-fit: cover;
            border-radius: 4px;
        }
        .print-description {
            font-style: italic;
            color: #555;
            margin-bottom: 20px;
            padding: 10px 0;
        }
        .print-section {
            margin-bottom: 25px;
        }
        .print-section h2 {
            font-size: 20px;
            border-bottom: 1px solid #ccc;
            padding-bottom: 6px;
            margin-bottom: 12px;
        }
        .print-ingredients ul {
            list-style: disc;
            padding-left: 25px;
        }
        .print-ingredients li {
            margin-bottom: 4px;
            font-size: 15px;
        }
        .print-ingredients .group-title {
            font-weight: bold;
            margin-top: 10px;
            list-style: none;
            margin-left: -25px;
        }
        .print-instructions ol {
            padding-left: 25px;
        }
        .print-instructions li {
            margin-bottom: 10px;
            font-size: 15px;
        }
        .print-nutrition table {
            width: 100%;
            border-collapse: collapse;
        }
        .print-nutrition th,
        .print-nutrition td {
            text-align: left;
            padding: 6px 10px;
            border-bottom: 1px solid #eee;
            font-size: 14px;
        }
        .print-nutrition th {
            font-weight: 600;
            width: 60%;
        }
        .print-diet-badges {
            margin: 10px 0;
        }
        .print-diet-badges span {
            display: inline-block;
            border: 1px solid #999;
            padding: 2px 8px;
            border-radius: 3px;
            font-size: 12px;
            margin-right: 5px;
        }
        .print-footer {
            margin-top: 30px;
            padding-top: 15px;
            border-top: 1px solid #ccc;
            font-size: 12px;
            color: #999;
            text-align: center;
        }
        .no-print { display: block; }
        .print-btn {
            display: inline-block;
            padding: 10px 24px;
            background: #333;
            color: #fff;
            border: none;
            cursor: pointer;
            font-size: 15px;
            border-radius: 4px;
            margin: 15px 0;
        }
        .print-btn:hover { background: #555; }

        @media print {
            body { padding: 0; }
            .no-print { display: none !important; }
            .print-image img { max-height: 300px; }
        }
    </style>
</head>
<body>
    <div class="no-print" style="text-align:center;">
        <button class="print-btn" onclick="window.print();"><?php esc_html_e('Print Recipe', 'plugixarecipe'); ?></button>
    </div>

    <div class="print-header">
        <h1><?php echo esc_html($recipe['title']); ?></h1>
        <div class="print-meta">
            <?php if (!empty($recipe['prep_time'])): ?>
                <span><?php esc_html_e('Prep:', 'plugixarecipe'); ?> <?php echo esc_html($recipe['prep_time']); ?> <?php esc_html_e('min', 'plugixarecipe'); ?></span>
            <?php endif; ?>
            <?php if (!empty($recipe['cook_time'])): ?>
                <span><?php esc_html_e('Cook:', 'plugixarecipe'); ?> <?php echo esc_html($recipe['cook_time']); ?> <?php esc_html_e('min', 'plugixarecipe'); ?></span>
            <?php endif; ?>
            <?php if (!empty($recipe['servings'])): ?>
                <span><?php esc_html_e('Servings:', 'plugixarecipe'); ?> <?php echo esc_html($recipe['servings']); ?></span>
            <?php endif; ?>
            <?php if (!empty($recipe['difficulty'])): ?>
                <span><?php esc_html_e('Difficulty:', 'plugixarecipe'); ?> <?php echo esc_html(ucfirst($recipe['difficulty'])); ?></span>
            <?php endif; ?>
        </div>
        <?php if (!empty($categories) || !empty($cuisines)): ?>
            <div class="print-meta">
                <?php if (!empty($categories)): ?>
                    <span><?php echo esc_html(implode(', ', array_column($categories, 'name'))); ?></span>
                <?php endif; ?>
                <?php if (!empty($cuisines)): ?>
                    <span><?php echo esc_html(implode(', ', array_column($cuisines, 'name'))); ?></span>
                <?php endif; ?>
            </div>
        <?php endif; ?>
    </div>

    <?php if (!empty($image_url)): ?>
        <div class="print-image">
            <img src="<?php echo esc_url($image_url); ?>" alt="<?php echo esc_attr($recipe['title']); ?>">
        </div>
    <?php endif; ?>

    <?php if (!empty($recipe['description'])): ?>
        <div class="print-description">
            <?php echo wp_kses_post($recipe['description']); ?>
        </div>
    <?php endif; ?>

    <?php
    // Diet badges
    $badges = [];
    if (!empty($recipe['is_vegetarian'])) $badges[] = __('Vegetarian', 'plugixarecipe');
    if (!empty($recipe['is_vegan'])) $badges[] = __('Vegan', 'plugixarecipe');
    if (!empty($recipe['is_gluten_free'])) $badges[] = __('Gluten-Free', 'plugixarecipe');
    if (!empty($recipe['is_dairy_free'])) $badges[] = __('Dairy-Free', 'plugixarecipe');
    if (!empty($recipe['is_keto'])) $badges[] = __('Keto', 'plugixarecipe');
    if (!empty($recipe['is_low_carb'])) $badges[] = __('Low-Carb', 'plugixarecipe');
    if (!empty($badges)):
    ?>
        <div class="print-diet-badges">
            <?php foreach ($badges as $badge): ?>
                <span><?php echo esc_html($badge); ?></span>
            <?php endforeach; ?>
        </div>
    <?php endif; ?>

    <?php if (!empty($ingredients)): ?>
        <div class="print-section print-ingredients">
            <h2><?php esc_html_e('Ingredients', 'plugixarecipe'); ?></h2>
            <ul>
                <?php
                $current_group = null;
                foreach ($ingredients as $ing):
                    if (!empty($ing['group_name']) && $ing['group_name'] !== $current_group):
                        $current_group = $ing['group_name'];
                        ?>
                        <li class="group-title"><?php echo esc_html($current_group); ?></li>
                    <?php endif; ?>
                    <li>
                        <?php
                        $line = '';
                        if (!empty($ing['quantity'])) $line .= $ing['quantity'] . ' ';
                        if (!empty($ing['unit'])) $line .= $ing['unit'] . ' ';
                        $line .= $ing['name'];
                        if (!empty($ing['notes'])) $line .= ' (' . $ing['notes'] . ')';
                        echo esc_html(trim($line));
                        ?>
                    </li>
                <?php endforeach; ?>
            </ul>
        </div>
    <?php endif; ?>

    <?php if (!empty($instructions)): ?>
        <div class="print-section print-instructions">
            <h2><?php esc_html_e('Instructions', 'plugixarecipe'); ?></h2>
            <ol>
                <?php foreach ($instructions as $step): ?>
                    <li><?php echo wp_kses_post($step['instruction_text']); ?></li>
                <?php endforeach; ?>
            </ol>
        </div>
    <?php endif; ?>

    <?php if (!empty($nutrition)): ?>
        <div class="print-section print-nutrition">
            <h2><?php esc_html_e('Nutrition Facts', 'plugixarecipe'); ?></h2>
            <?php if (!empty($nutrition['serving_size'])): ?>
                <p><strong><?php esc_html_e('Serving Size:', 'plugixarecipe'); ?></strong> <?php echo esc_html($nutrition['serving_size']); ?></p>
            <?php endif; ?>
            <table>
                <?php
                $nutrition_labels = [
                    'calories'           => [__('Calories', 'plugixarecipe'), ''],
                    'total_fat'          => [__('Total Fat', 'plugixarecipe'), 'g'],
                    'saturated_fat'      => [__('Saturated Fat', 'plugixarecipe'), 'g'],
                    'cholesterol'        => [__('Cholesterol', 'plugixarecipe'), 'mg'],
                    'sodium'             => [__('Sodium', 'plugixarecipe'), 'mg'],
                    'total_carbohydrate' => [__('Total Carbohydrate', 'plugixarecipe'), 'g'],
                    'dietary_fiber'      => [__('Dietary Fiber', 'plugixarecipe'), 'g'],
                    'total_sugars'       => [__('Total Sugars', 'plugixarecipe'), 'g'],
                    'protein'            => [__('Protein', 'plugixarecipe'), 'g'],
                ];
                foreach ($nutrition_labels as $key => [$label, $unit]):
                    if (isset($nutrition[$key]) && $nutrition[$key] !== null && $nutrition[$key] !== ''):
                ?>
                    <tr>
                        <th><?php echo esc_html($label); ?></th>
                        <td><?php echo esc_html($nutrition[$key] . ($unit ? ' ' . $unit : '')); ?></td>
                    </tr>
                <?php endif; endforeach; ?>
            </table>
        </div>
    <?php endif; ?>

    <div class="print-footer">
        <?php echo esc_html(sprintf(
            /* translators: 1: site name, 2: current date */
            __('Printed from %1$s on %2$s', 'plugixarecipe'),
            get_bloginfo('name'),
            wp_date(get_option('date_format'))
        )); ?>
    </div>

    <script>
        // Auto-trigger print dialog
        if (window.matchMedia) {
            // If opened directly for printing, trigger print
            const urlParams = new URLSearchParams(window.location.search);
            if (urlParams.get('auto') === '1') {
                window.onload = function() { window.print(); };
            }
        }
    </script>
</body>
</html>
        <?php
    }

    /**
     * Get a single published recipe by ID.
     */
    private function get_recipe(int $id): ?array {
        global $wpdb;
        $table = $wpdb->prefix . 'plugixarecipe_recipes';

        $recipe = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE id = %d AND status = 'published'",
            $id
        ), ARRAY_A);

        return $recipe ?: null;
    }

    /**
     * Get recipe ingredients.
     */
    private function get_ingredients(int $recipe_id): array {
        global $wpdb;
        $table = $wpdb->prefix . 'plugixarecipe_ingredients';

        return $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$table} WHERE recipe_id = %d ORDER BY group_order ASC, sort_order ASC",
            $recipe_id
        ), ARRAY_A) ?: [];
    }

    /**
     * Get recipe instructions.
     */
    private function get_instructions(int $recipe_id): array {
        global $wpdb;
        $table = $wpdb->prefix . 'plugixarecipe_instructions';

        return $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$table} WHERE recipe_id = %d ORDER BY group_order ASC, sort_order ASC",
            $recipe_id
        ), ARRAY_A) ?: [];
    }

    /**
     * Get recipe nutrition data.
     */
    private function get_nutrition(int $recipe_id): ?array {
        global $wpdb;
        $table = $wpdb->prefix . 'plugixarecipe_nutrition';

        $result = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE recipe_id = %d",
            $recipe_id
        ), ARRAY_A);

        return $result ?: null;
    }

    /**
     * Get recipe categories.
     */
    private function get_categories(int $recipe_id): array {
        global $wpdb;
        $prefix = $wpdb->prefix . 'plugixarecipe_';

        return $wpdb->get_results($wpdb->prepare(
            "SELECT c.name, c.slug FROM {$prefix}categories c
             INNER JOIN {$prefix}recipe_categories rc ON c.id = rc.category_id
             WHERE rc.recipe_id = %d",
            $recipe_id
        ), ARRAY_A) ?: [];
    }

    /**
     * Get recipe cuisines.
     */
    private function get_cuisines(int $recipe_id): array {
        global $wpdb;
        $prefix = $wpdb->prefix . 'plugixarecipe_';

        return $wpdb->get_results($wpdb->prepare(
            "SELECT cu.name, cu.slug FROM {$prefix}cuisines cu
             INNER JOIN {$prefix}recipe_cuisines rcu ON cu.id = rcu.cuisine_id
             WHERE rcu.recipe_id = %d",
            $recipe_id
        ), ARRAY_A) ?: [];
    }
}
