<?php
namespace AIFI;

/**
 * Handles Gutenberg block registration and related REST API endpoints.
 *
 * @package AIFI
 */
class Blocks {
    /**
     * Settings instance.
     *
     * @var Settings
     */
    private $settings;

    /**
     * Generator instance.
     *
     * @var Generator
     */
    private $generator;

    /**
     * Initialize blocks.
     *
     * @param Settings  $settings  Settings instance.
     * @param Generator $generator Generator instance.
     */
    public function __construct($settings, $generator) {
        $this->settings = $settings;
        $this->generator = $generator;

        // Register block and editor assets for all users.
        add_action('init', array($this, 'register_blocks'));
        add_action('enqueue_block_editor_assets', array($this, 'enqueue_block_editor_assets'));

        // REST endpoint for generating block images.
        add_action('rest_api_init', array($this, 'register_block_routes'));
    }

    /**
     * Check if current user has premium access.
     *
     * @return bool
     */
    private function is_premium_user() {
        return function_exists('afig_fs') && afig_fs()->can_use_premium_code();
    }

    /**
     * Register the AI Image Generator block.
     */
    public function register_blocks() {
        $block_path = AIFI_PLUGIN_DIR . 'build/blocks/ai-image-generator';

        if (file_exists($block_path . '/block.json')) {
            register_block_type($block_path);
        }
    }

    /**
     * Enqueue block editor assets and pass configuration to JavaScript.
     */
    public function enqueue_block_editor_assets() {
        $block_path = AIFI_PLUGIN_DIR . 'build/blocks/ai-image-generator';

        if (!file_exists($block_path . '/index.asset.php')) {
            return;
        }

        // Prepare the data to pass to JavaScript
        $settings = $this->settings->get_settings();
        $current_provider = $settings['ai_provider'] ?? 'openai';
        $enabled_post_types = $this->settings->get_enabled_post_types();

        $default_aspect_ratio = $this->get_inline_default_aspect_ratio($settings, $current_provider);

        $block_data = array(
            'restUrl' => rest_url('aifi/v1/generate-block-image'),
            'nonce' => wp_create_nonce('wp_rest'),
            'isPremium' => $this->is_premium_user(),
            'upgradeUrl' => function_exists('afig_fs') ? afig_fs()->get_upgrade_url() : '',
            'styles' => $this->get_styles_for_block(),
            'defaultStyle' => $settings['inline_default_style'] ?? ($settings['default_style'] ?? 'realistic'),
            'defaultAspectRatio' => $default_aspect_ratio,
            'aspectRatios' => $this->get_aspect_ratios(),
            'currentProvider' => $current_provider,
            'enabledPostTypes' => $enabled_post_types,
            'settingsUrl' => admin_url('admin.php?page=ai-featured-image-generator&tab=general'),
            'allowText' => !empty($settings['allow_text']),
        );

        // Output the data as inline script - wp-blocks loads before our block
        $inline_script = 'window.aifiBlockData = ' . wp_json_encode($block_data) . ';';
        wp_add_inline_script('wp-blocks', $inline_script, 'before');
    }

    /**
     * Get available styles for the block.
     *
     * @return array
     */
    private function get_styles_for_block() {
        $styles = array(
            'none' => __('None (No Style)', 'ai-featured-image-generator'),
            'realistic' => __('Realistic', 'ai-featured-image-generator'),
            'artistic' => __('Artistic', 'ai-featured-image-generator'),
            'cartoon' => __('Cartoon', 'ai-featured-image-generator'),
            'sketch' => __('Sketch', 'ai-featured-image-generator'),
            'watercolor' => __('Watercolor', 'ai-featured-image-generator'),
            '3d' => __('3D Render', 'ai-featured-image-generator'),
            'pixel' => __('Pixel Art', 'ai-featured-image-generator'),
            'cyberpunk' => __('Cyberpunk', 'ai-featured-image-generator'),
            'fantasy' => __('Fantasy', 'ai-featured-image-generator'),
            'anime' => __('Anime', 'ai-featured-image-generator'),
            'minimalist' => __('Minimalist', 'ai-featured-image-generator'),
            'technicolor' => __('Technicolor', 'ai-featured-image-generator'),
        );

        $custom_styles = $this->settings->get_custom_styles();
        foreach ($custom_styles as $i => $cs) {
            if (!empty($cs['name'])) {
                $styles['custom_' . $i] = $cs['name'];
            }
        }

        return $styles;
    }

    /**
     * Get the inline default aspect ratio for the current provider.
     *
     * Maps provider-specific inline settings (e.g. inline_gemini_aspect_ratio)
     * to a single aspect ratio string for the block editor.
     *
     * @param array  $settings         Plugin settings.
     * @param string $current_provider Active AI provider.
     * @return string Aspect ratio string (e.g. '16:9').
     */
    private function get_inline_default_aspect_ratio($settings, $current_provider) {
        $size_to_ratio = array(
            '1024x1024' => '1:1',
            '1536x1024' => '16:9',
            '1024x1536' => '9:16',
            '1792x1024' => '16:9',
            '1024x1792' => '9:16',
        );

        switch ($current_provider) {
            case 'gemini':
                return $settings['inline_gemini_aspect_ratio'] ?? '16:9';
            case 'stability':
                return $settings['inline_stability_aspect_ratio'] ?? '16:9';
            case 'grok':
                return $settings['inline_grok_aspect_ratio'] ?? '1:1';
            case 'openai':
            default:
                $size = $settings['inline_default_size'] ?? '1024x1024';
                return $size_to_ratio[$size] ?? '1:1';
        }
    }

    /**
     * Get available aspect ratios organized by provider.
     *
     * OpenAI supports only 3 sizes: 1024x1024, 1792x1024, 1024x1792
     * Gemini natively supports: 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9
     *
     * @return array Provider-specific aspect ratio options.
     */
    private function get_aspect_ratios() {
        return array(
            'openai' => array(
                '1:1' => array(
                    'label' => __('Square (1:1)', 'ai-featured-image-generator'),
                    'ratio' => 1.0,
                    'size'  => '1024x1024',
                ),
                '16:9' => array(
                    'label' => __('Landscape (16:9)', 'ai-featured-image-generator'),
                    'ratio' => 1.778,
                    'size'  => '1792x1024',
                ),
                '9:16' => array(
                    'label' => __('Portrait (9:16)', 'ai-featured-image-generator'),
                    'ratio' => 0.5625,
                    'size'  => '1024x1792',
                ),
            ),
            'gemini' => array(
                '1:1' => array(
                    'label' => __('Square (1:1)', 'ai-featured-image-generator'),
                    'ratio' => 1.0,
                    'size'  => '1024x1024',
                ),
                '4:3' => array(
                    'label' => __('Landscape (4:3)', 'ai-featured-image-generator'),
                    'ratio' => 1.333,
                    'size'  => '1536x1024',
                ),
                '3:2' => array(
                    'label' => __('Landscape (3:2)', 'ai-featured-image-generator'),
                    'ratio' => 1.5,
                    'size'  => '1536x1024',
                ),
                '16:9' => array(
                    'label' => __('Widescreen (16:9)', 'ai-featured-image-generator'),
                    'ratio' => 1.778,
                    'size'  => '1536x1024',
                ),
                '3:4' => array(
                    'label' => __('Portrait (3:4)', 'ai-featured-image-generator'),
                    'ratio' => 0.75,
                    'size'  => '1024x1536',
                ),
                '2:3' => array(
                    'label' => __('Portrait (2:3)', 'ai-featured-image-generator'),
                    'ratio' => 0.667,
                    'size'  => '1024x1536',
                ),
                '9:16' => array(
                    'label' => __('Tall (9:16)', 'ai-featured-image-generator'),
                    'ratio' => 0.5625,
                    'size'  => '1024x1536',
                ),
            ),
            'stability' => array(
                '1:1' => array(
                    'label' => __('Square (1:1)', 'ai-featured-image-generator'),
                    'ratio' => 1.0,
                    'size'  => '1:1',
                ),
                '16:9' => array(
                    'label' => __('Landscape (16:9)', 'ai-featured-image-generator'),
                    'ratio' => 1.778,
                    'size'  => '16:9',
                ),
                '9:16' => array(
                    'label' => __('Portrait (9:16)', 'ai-featured-image-generator'),
                    'ratio' => 0.5625,
                    'size'  => '9:16',
                ),
                '3:2' => array(
                    'label' => __('Landscape (3:2)', 'ai-featured-image-generator'),
                    'ratio' => 1.5,
                    'size'  => '3:2',
                ),
                '2:3' => array(
                    'label' => __('Portrait (2:3)', 'ai-featured-image-generator'),
                    'ratio' => 0.667,
                    'size'  => '2:3',
                ),
                '5:4' => array(
                    'label' => __('Landscape (5:4)', 'ai-featured-image-generator'),
                    'ratio' => 1.25,
                    'size'  => '5:4',
                ),
                '4:5' => array(
                    'label' => __('Portrait (4:5)', 'ai-featured-image-generator'),
                    'ratio' => 0.8,
                    'size'  => '4:5',
                ),
                '21:9' => array(
                    'label' => __('Cinematic (21:9)', 'ai-featured-image-generator'),
                    'ratio' => 2.333,
                    'size'  => '21:9',
                ),
                '9:21' => array(
                    'label' => __('Ultra Tall (9:21)', 'ai-featured-image-generator'),
                    'ratio' => 0.429,
                    'size'  => '9:21',
                ),
            ),
            'grok' => array(
                '1:1' => array(
                    'label' => __('Square (1:1)', 'ai-featured-image-generator'),
                    'ratio' => 1.0,
                    'size'  => '1024x1024',
                ),
                '16:9' => array(
                    'label' => __('Landscape (16:9)', 'ai-featured-image-generator'),
                    'ratio' => 1.778,
                    'size'  => '1024x576',
                ),
                '9:16' => array(
                    'label' => __('Portrait (9:16)', 'ai-featured-image-generator'),
                    'ratio' => 0.5625,
                    'size'  => '576x1024',
                ),
                '4:3' => array(
                    'label' => __('Landscape (4:3)', 'ai-featured-image-generator'),
                    'ratio' => 1.333,
                    'size'  => '1024x768',
                ),
                '3:4' => array(
                    'label' => __('Portrait (3:4)', 'ai-featured-image-generator'),
                    'ratio' => 0.75,
                    'size'  => '768x1024',
                ),
                '3:2' => array(
                    'label' => __('Landscape (3:2)', 'ai-featured-image-generator'),
                    'ratio' => 1.5,
                    'size'  => '1024x682',
                ),
                '2:3' => array(
                    'label' => __('Portrait (2:3)', 'ai-featured-image-generator'),
                    'ratio' => 0.667,
                    'size'  => '682x1024',
                ),
                '2:1' => array(
                    'label' => __('Wide (2:1)', 'ai-featured-image-generator'),
                    'ratio' => 2.0,
                    'size'  => '1024x512',
                ),
                '1:2' => array(
                    'label' => __('Tall (1:2)', 'ai-featured-image-generator'),
                    'ratio' => 0.5,
                    'size'  => '512x1024',
                ),
            ),
        );
    }

    /**
     * Register REST API routes for block image generation.
     */
    public function register_block_routes() {
        register_rest_route('aifi/v1', '/generate-block-image', array(
            'methods' => 'POST',
            'callback' => array($this, 'generate_block_image'),
            'permission_callback' => array($this, 'check_block_permission'),
            'args' => array(
                'prompt' => array(
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_textarea_field',
                    'validate_callback' => function($value) {
                        if (strlen($value) > 4000) {
                            return new \WP_Error('prompt_too_long', __('Prompt is too long. Maximum 4000 characters.', 'ai-featured-image-generator'));
                        }
                        if (empty(trim($value))) {
                            return new \WP_Error('prompt_empty', __('Prompt cannot be empty.', 'ai-featured-image-generator'));
                        }
                        return true;
                    },
                ),
                'style' => array(
                    'required' => false,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                    'default' => '',
                    'validate_callback' => function($value) {
                        if (empty($value)) {
                            return true;
                        }
                        $valid_styles = array('none', 'realistic', 'artistic', 'cartoon', 'sketch', 'watercolor', '3d', 'pixel', 'cyberpunk', 'fantasy', 'anime', 'minimalist', 'technicolor');
                        if (in_array($value, $valid_styles, true)) {
                            return true;
                        }
                        return (bool) preg_match('/^custom_\d+$/', $value);
                    },
                ),
                'aspect_ratio' => array(
                    'required' => false,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                    'default' => '',
                    'validate_callback' => function($value) {
                        if (empty($value)) {
                            return true;
                        }
                        $valid_ratios = array('1:1', '4:3', '3:2', '16:9', '3:4', '2:3', '9:16', '5:4', '4:5', '21:9', '9:21', '2:1', '1:2');
                        return in_array($value, $valid_ratios, true);
                    },
                ),
                'post_id' => array(
                    'required' => false,
                    'type' => 'integer',
                    'sanitize_callback' => 'absint',
                    'default' => 0,
                ),
                'display_width' => array(
                    'required' => false,
                    'type' => 'integer',
                    'sanitize_callback' => 'absint',
                    'default' => 1200,
                    'validate_callback' => function($value) {
                        // Clamp to reasonable range (100-4000px)
                        return $value >= 100 && $value <= 4000;
                    },
                ),
                'custom_text' => array(
                    'required' => false,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                    'default' => '',
                ),
            ),
        ));
    }

    /**
     * Check if user has permission to generate block images.
     *
     * @param \WP_REST_Request $request REST request object.
     * @return bool|\WP_Error
     */
    public function check_block_permission($request) {
        // Capability check - must be able to upload files
        if (!current_user_can('upload_files')) {
            return new \WP_Error(
                'rest_forbidden',
                __('You do not have permission to upload files.', 'ai-featured-image-generator'),
                array('status' => 403)
            );
        }

        // Optional: If post_id provided, check edit_post capability
        $post_id = $request->get_param('post_id');
        if ($post_id && !current_user_can('edit_post', $post_id)) {
            return new \WP_Error(
                'rest_forbidden',
                __('You do not have permission to edit this post.', 'ai-featured-image-generator'),
                array('status' => 403)
            );
        }

        return true;
    }

    /**
     * Generate an image for the block.
     *
     * @param \WP_REST_Request $request REST request object.
     * @return \WP_REST_Response|\WP_Error
     */
    public function generate_block_image($request) {
        $prompt = $request->get_param('prompt');
        $style = $request->get_param('style');
        $aspect_ratio = $request->get_param('aspect_ratio');
        $post_id = $request->get_param('post_id');
        $display_width = $request->get_param('display_width');
        $custom_text = $request->get_param('custom_text');

        // Rate limiting with unique key for blocks
        $lock_key = 'aifi_block_lock_' . get_current_user_id();
        if (get_transient($lock_key)) {
            return new \WP_Error(
                'rate_limited',
                __('Please wait a moment before generating another image.', 'ai-featured-image-generator'),
                array('status' => 429)
            );
        }
        set_transient($lock_key, true, 5);

        // Generate the inline image using the Generator class
        $result = $this->generator->generate_inline_image($prompt, $style, $aspect_ratio, $post_id, $display_width, $custom_text);

        if (is_wp_error($result)) {
            return $result;
        }

        return rest_ensure_response(array(
            'success' => true,
            'attachmentId' => $result['attachment_id'],
            'url' => $result['url'],
            'alt' => $result['alt'],
            'width' => $result['width'],
            'height' => $result['height'],
        ));
    }
}
