<?php

namespace Fab\Api;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

use Fab\Interfaces\JIT_Interface;
use Fab\Helper\FAB_Template;

/**
 * Templates
 *
 * @package    Fab
 * @subpackage Fab/Api
 */
class Templates extends Api implements JIT_Interface {

    /**
     * Registers REST API routes for template import.
     *
     * @return void
     */
    public function register_routes() {
        \register_rest_route(
            'fab/v1',
            '/add_new_fab',
            array(
                'methods'             => 'POST',
                'permission_callback' => function () {
                    return defined( 'FAB_REST_API_USER_IS_ADMIN' ) && FAB_REST_API_USER_IS_ADMIN;
                },
                'callback'            => array( $this, 'add_new_fab_rest_callback' ),
            )
        );

        \register_rest_route(
            'fab/v1',
            '/import',
            array(
                array(
                    'methods'             => \WP_REST_Server::CREATABLE,
                    'permission_callback' => function () {
                        return defined( 'FAB_REST_API_USER_IS_ADMIN' ) && FAB_REST_API_USER_IS_ADMIN;
                    },
                    'callback'            => array( $this, 'import_template' ),
                ),
            )
        );
    }

    /**
     * Add new fab rest callback
     *
     * @param array $data The data.
     * @return array
     */
    public function add_new_fab_rest_callback( $data ) {
        $data = json_decode( file_get_contents( 'php://input' ) );

        // Add new fab.
        $result   = FAB_Template::getInstance()->add_new_fab( $data );
        $response = ! is_wp_error( $result ) ?
            array(
                'message' => __( 'Success', 'floating-awesome-button' ),
                'post_id' => $result,
            ) :
            // translators: %s: Error message from WP_Error object.
            array( 'message' => sprintf( __( 'Error: %s', 'floating-awesome-button' ), $result->get_error_message() ) );

        return rest_ensure_response( $response );
    }

    /**
     * Handles the REST API request for importing a template file.
     *
     * @param WP_REST_Request $request Full details about the request.
     * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
     */
    public function import_template( $request ) {
        // Check if file was uploaded.
        $files = $request->get_file_params();

        // Check upload limits for free users.
        if ( ! \Fab\Plugin\Helper::getInstance()->isPremiumPlan() ) {
            $current_month = date( 'Y-m' );
            $upload_count  = get_option( 'fab_site_upload_count_' . $current_month, 0 );

            if ( $upload_count >= 3 ) {
                return new \WP_Error(
                    'fab_upload_limit_exceeded',
                    __( 'Free users can only upload 3 templates per month. Please upgrade to premium for unlimited uploads.', 'floating-awesome-button' ),
                    array( 'status' => 403 )
                );
            }

            // Increment the site-wide upload count.
            update_option(
                'fab_site_upload_count_' . $current_month,
                $upload_count + 1
            );
        }

        // Check if file was uploaded.
        if ( ! is_array( $files['template_file'] ) || empty( $files['template_file'] ) ) {
            return new \WP_Error(
                'fab_missing_template_file',
                __( 'No template file was uploaded.', 'floating-awesome-button' ),
                array( 'status' => 400 )
            );
        }

        $file = $files['template_file'];

        // Check for upload errors.
        if ( $file['error'] > 0 ) {
            return new \WP_Error(
                'fab_template_upload_error',
                // translators: %s is the upload error message.
                sprintf( __( 'Upload error: %s', 'floating-awesome-button' ), $this->get_upload_error_message( $file['error'] ) ),
                array( 'status' => 400 )
            );
        }

        // Validate file type.
        if ( false === strpos( strtolower( $file['name'] ), '.json' ) ) {
            return new \WP_Error(
                'fab_invalid_file_type',
                __( 'Invalid file type. Only JSON files are allowed.', 'floating-awesome-button' ),
                array( 'status' => 400 )
            );
        }

        // Read and validate the JSON content.
        $json_content  = file_get_contents( $file['tmp_name'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
        $template_data = json_decode( $json_content );

        if ( null === $template_data ) {
            return new \WP_Error(
                'fab_invalid_json',
                __( 'Invalid JSON file. Could not parse the template data.', 'floating-awesome-button' ),
                array( 'status' => 400 )
            );
        }

        // Validate template structure.
        if ( ! $this->validate_template_structure( $template_data ) ) {
            return new \WP_Error(
                'fab_invalid_template_structure',
                __( 'Invalid template structure. The file does not contain a valid FAB template.', 'floating-awesome-button' ),
                array( 'status' => 400 )
            );
        }

        try {
            // Process the template.
            $template_id = sanitize_title( $template_data->id );

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

            // Create a new FAB from the imported template.
            $fab_template = FAB_Template::getInstance();
            $post_id      = $fab_template->add_new_fab( (object) array( 'id' => $template_id ) );

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

            return rest_ensure_response(
                array(
                    'success'  => true,
                    'message'  => __( 'Template imported successfully.', 'floating-awesome-button' ),
                    'post_id'  => $post_id,
                    'edit_url' => get_edit_post_link( $post_id, 'url' ),
                )
            );

        } catch ( \Exception $e ) {
            return new \WP_Error(
                'fab_template_import_error',
                $e->getMessage(),
                array( 'status' => 500 )
            );
        }
    }

    /**
     * Validates the template structure.
     *
     * @param object $template_data The template data to validate.
     * @return bool True if valid, false otherwise.
     */
    private function validate_template_structure( $template_data ) {
        // Check for required template properties.
        $required_props = array( 'id', 'name', 'description', 'settings', 'design' );

        foreach ( $required_props as $prop ) {
            if ( ! isset( $template_data->$prop ) ) {
                return false;
            }
        }

        // Check for required settings properties.
        if ( ! isset( $template_data->settings->type ) ) {
            return false;
        }

        return true;
    }

    /**
     * Gets a human-readable error message for upload errors.
     *
     * @param int $error_code The PHP upload error code.
     * @return string The error message.
     */
    private function get_upload_error_message( $error_code ) {
        $upload_errors = array(
            UPLOAD_ERR_INI_SIZE   => __( 'The uploaded file exceeds the upload_max_filesize directive in php.ini.', 'floating-awesome-button' ),
            UPLOAD_ERR_FORM_SIZE  => __( 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', 'floating-awesome-button' ),
            UPLOAD_ERR_PARTIAL    => __( 'The uploaded file was only partially uploaded.', 'floating-awesome-button' ),
            UPLOAD_ERR_NO_FILE    => __( 'No file was uploaded.', 'floating-awesome-button' ),
            UPLOAD_ERR_NO_TMP_DIR => __( 'Missing a temporary folder.', 'floating-awesome-button' ),
            UPLOAD_ERR_CANT_WRITE => __( 'Failed to write file to disk.', 'floating-awesome-button' ),
            UPLOAD_ERR_EXTENSION  => __( 'A PHP extension stopped the file upload.', 'floating-awesome-button' ),
        );

        return isset( $upload_errors[ $error_code ] ) ? $upload_errors[ $error_code ] : __( 'Unknown upload error.', 'floating-awesome-button' );
    }

    /*
    |--------------------------------------------------------------------------
    | Fulfill implemented interface contracts
    |--------------------------------------------------------------------------
     */

    /**
     * JIT Method.
     *
     * @return void
     */
    public static function jit() {
        add_action( 'rest_api_init', array( self::class, 'jit_register_routes' ) );
    }
}
