<?php

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Class Irep_Project
 * 
 * Handles CRUD operations for the "projects" table in the database.
 * Provides functionality to retrieve, create, update, and delete projects.
 */
class Irep_Project
{
    /**
     * @var wpdb $wpdb WordPress database object.
     */
    protected $wpdb;

    /**
     * @var string $table_name Name of the projects table in the WordPress database.
     */
    protected $table_name;

    /**
     * Irep_Project constructor.
     *
     * Initializes the project class with the global $wpdb object to interact with the WordPress database.
     */
    public function __construct()
    {
        global $wpdb;
        $this->wpdb = $wpdb;
        $this->table_name = 'irep_projects';  // Set the projects table name with WordPress table prefix.
    }

    /**
     * Retrieve all projects or a specific project by ID.
     * 
     * @param array $data The request data, should include 'nonce' and optionally 'project_id'.
     * 
     * @return array Returns an array where the first element is a boolean indicating success/failure,
     *               and the second element is either the projects data or an error message.
     */
    public function get_projects(array $data)
    {

        $data = [
            'nonce'        => isset($data['nonce']) ? sanitize_text_field($data['nonce']) : '',
            'action'       => isset($data['action']) ? sanitize_key($data['action']) : '',
            'project_id'   => isset($data['project_id']) ? absint($data['project_id']) : 0,
        ];

        // Verify nonce for security to prevent CSRF attacks.
        irep_check_nonce($data['nonce'], 'irep_nonce');

        // Retrieve project ID from request, if available.
        $project_id = isset($data['project_id']) ? intval($data['project_id']) : null;

        if ($project_id) {

            $result = Irep_DB::table($this->table_name)->find($project_id);

            if ($result) {
                $result = $this->map_project($result);
            }
        } else {

            $result = Irep_DB::table($this->table_name)->orderBy('id', 'DESC')->get();

            if ($result) {
                // Process each project to decode JSON and format image data.
                $result =  array_map([$this, 'map_project'], $result);
            }
        }

        // Check for database errors and return the results or error message.
        if (!$result) {
            return [false, []];
        } else {
            return [true, $result];
        }
    }

    /**
     * Create a new project in the database.
     * 
     * @param array $data The request data containing the project details (e.g., title, image).
     * 
     * @return void Sends a JSON response indicating success or failure.
     */
    public function create_project($data)
    {

        $data = [
            'nonce'         => isset($data['nonce']) ? sanitize_text_field($data['nonce']) : '',
            'action'        => isset($data['action']) ? sanitize_key($data['action']) : '',
            'title'         => isset($data['title']) ? sanitize_text_field($data['title']) : '',
            'project_image' => isset($data['project_image']) ? absint($data['project_image']) : 0,
            'svg'           => isset($data['svg']) ? sanitize_text_field($data['svg']) : '',
        ];

        $this->canUserAddProject($data);

        // Verify nonce for security.
        irep_check_nonce($data['nonce'], 'irep_nonce');

        // Sanitize input fields.
        $title = isset($data['title']) ? sanitize_text_field($data['title']) : '';
        $project_image = isset($data['project_image']) ? sanitize_text_field($data['project_image']) : '';
        $slug = sanitize_title($title); // Generate a sanitized slug for the project.

        $data = [
            'title' => $title,
            'project_image' => $project_image,
            'svg' => '',
            'slug' => $slug,
            'polygon_data' => '{}',
        ];


        $project_id = Irep_DB::table($this->table_name)->create($data);


        // Return a JSON response based on the success of the database operation.
        if (!$project_id) {
            irep_send_json_response(false, 'Database error');
        } else {
            irep_send_json_response(true,  ['msg' => 'Project added', 'project_id' => $project_id]);
        }
    }

    /**
     * Update an existing project in the database.
     * 
     * @param array $data The request data containing the project ID and updated details (e.g., title, SVG, image).
     * 
     * @return void Sends a JSON response indicating success or failure.
     */
    public function update_project($data)
    {

        $data = [
            'nonce'           => isset($data['nonce']) ? sanitize_text_field($data['nonce']) : '',
            'action'          => isset($data['action']) ? sanitize_key($data['action']) : '',
            'title'           => isset($data['title']) ? sanitize_text_field($data['title']) : '',
            'projectId'       => isset($data['projectId']) ? absint($data['projectId']) : 0,
            'slug'            => isset($data['slug']) ? sanitize_text_field($data['slug']) : '',
            'project_image'   => isset($data['project_image']) ? absint($data['project_image']) : 0,
            'svg'             => $data['svg'],
            'polygon_data'    => $data['polygon_data'],
            'mobile_svg'      => $data['mobile_svg'] ?? '',
            'mobile_polygon_data' => $data['mobile_polygon_data'] ?? null,
            '360images'       => $data['360images'],
            'project_views'   => $data['project_views'] ?? null,
        ];


        $decoded_svg = isset($_POST['svg']) ? base64_decode($_POST['svg']) : '';
        if (is_string($decoded_svg) && trim($decoded_svg) !== '') {
            $data['svg'] = $decoded_svg;
        } else {
            unset($data['svg']);
        }

        // Mobile SVG arrives either base64-encoded (freshly drawn) or as raw markup (unchanged round-trip).
        $mobile_svg_raw = is_string($data['mobile_svg']) ? $data['mobile_svg'] : '';
        $decoded_mobile_svg = base64_decode($mobile_svg_raw, true);
        if (is_string($decoded_mobile_svg) && strpos(ltrim($decoded_mobile_svg), '<svg') === 0) {
            $data['mobile_svg'] = $decoded_mobile_svg;
        } elseif (strpos(ltrim($mobile_svg_raw), '<svg') === 0) {
            $data['mobile_svg'] = wp_unslash($mobile_svg_raw);
        } else {
            $data['mobile_svg'] = '';
        }

        // Verify nonce for security.
        irep_check_nonce($data['nonce'], 'irep_nonce');

        // Retrieve project ID from request.
        $project_id = isset($data['projectId']) ? intval($data['projectId']) : null;

        // Define allowed fields for updating.
        $keys = ['svg', 'title', 'polygon_data', 'mobile_svg', 'mobile_polygon_data', 'project_image', '360images', 'project_views'];

        // Filter the request data to only include valid fields.
        $params = array_filter($data, function ($key) use ($keys) {
            return in_array($key, $keys);
        }, ARRAY_FILTER_USE_KEY);

        // Ensure polygon_data is properly encoded as JSON.
        $params['polygon_data'] = json_encode($params['polygon_data'] ?? '');
        $params['mobile_polygon_data'] = json_encode($params['mobile_polygon_data'] ?? []);

        $images_360_raw = $params['360images'] ?? null;
        if (is_string($images_360_raw)) {
            $images_360 = json_decode(wp_unslash($images_360_raw), true) ?: [];
        } elseif (is_array($images_360_raw)) {
            $images_360 = $images_360_raw;
        } else {
            $images_360 = [];
        }
        $normalized_360 = [];

        foreach ($images_360 as $image) {
            if (!is_array($image)) {
                continue;
            }

            $svg_value = isset($image['svg']) && is_string($image['svg']) ? $image['svg'] : '';
            $decoded_svg = base64_decode($svg_value, true);
            if (is_string($decoded_svg) && strpos(ltrim($decoded_svg), '<svg') === 0) {
                $svg_value = $decoded_svg;
            }

            $normalized_360[] = [
                'img' => isset($image['img']) ? esc_url_raw((string) $image['img']) : '',
                'svg' => $svg_value,
                'polygon_data' => isset($image['polygon_data']) && is_array($image['polygon_data']) ? $image['polygon_data'] : [],
            ];
        }

        $params['360images'] = json_encode($normalized_360);

        $views_raw = $params['project_views'] ?? null;
        if (is_string($views_raw)) {
            $views = json_decode(wp_unslash($views_raw), true) ?: [];
        } elseif (is_array($views_raw)) {
            $views = $views_raw;
        } else {
            $views = [];
        }
        $normalized_views = [];
        foreach ($views as $view) {
            if (!is_array($view)) {
                continue;
            }
            $svg_val = isset($view['svg']) && is_string($view['svg']) ? $view['svg'] : '';
            $decoded_svg_val = base64_decode($svg_val, true);
            if (is_string($decoded_svg_val) && strpos(ltrim($decoded_svg_val), '<svg') === 0) {
                $svg_val = $decoded_svg_val;
            }
            $mobile_svg_val = isset($view['mobile_svg']) && is_string($view['mobile_svg']) ? $view['mobile_svg'] : '';
            $decoded_mobile_svg_val = base64_decode($mobile_svg_val, true);
            if (is_string($decoded_mobile_svg_val) && strpos(ltrim($decoded_mobile_svg_val), '<svg') === 0) {
                $mobile_svg_val = $decoded_mobile_svg_val;
            }
            $normalized_views[] = [
                'img'          => isset($view['img']) ? esc_url_raw((string) $view['img']) : '',
                'mobile_img'   => isset($view['mobile_img']) ? esc_url_raw((string) $view['mobile_img']) : '',
                'svg'          => $svg_val,
                'mobile_svg'   => $mobile_svg_val,
                'polygon_data' => isset($view['polygon_data']) && is_array($view['polygon_data']) ? $view['polygon_data'] : [],
                'mobile_polygon_data' => isset($view['mobile_polygon_data']) && is_array($view['mobile_polygon_data']) ? $view['mobile_polygon_data'] : [],
                'title'        => isset($view['title']) ? sanitize_text_field((string) $view['title']) : '',
            ];
        }
        $params['project_views'] = json_encode($normalized_views);

        $updated_project = Irep_DB::table($this->table_name)->where('id', '=', $project_id)->update($params);


        // Return a JSON response based on the success of the update.
        if ($updated_project->last_error) {
            irep_send_json_response(false, 'project not updated.');
        } else {
            irep_send_json_response(true, 'Project updated');
        }
    }

    /**
     * Delete a project from the database.
     * 
     * @param array $data The request data containing the project ID to delete.
     * 
     * @return void Sends a JSON response indicating success or failure.
     */
    public function delete_project($data)
    {
        // Verify nonce for security.
        irep_check_nonce($data['nonce'], 'irep_nonce');

        // Retrieve project ID from request.
        $project_id = isset($data['project_id']) ? intval($data['project_id']) : null;

        // Check if the project ID is provided.
        if (!$project_id) {
            irep_send_json_response(false, 'project_id is required');
            return;
        }

        $deleted_project = Irep_DB::table($this->table_name)->where('id', '=',  $project_id)->delete();


        // Return a JSON response based on the success of the deletion.
        if ($deleted_project) {
            irep_send_json_response(true, 'Project deleted successfully');
        } else {
            irep_send_json_response(false, 'Database error');
        }
    }

    public function map_project($item)
    {
        if (is_object($item)) {
            $item = (array) $item;
        }

        $item['project_image'] = [irep_get_image_instance($item['project_image'])];
        $decoded_360 = json_decode((string) ($item['360images'] ?? ''), true);
        $item['360images'] = is_array($decoded_360) ? $decoded_360 : [];
        $item['svg'] = irep_transformSvgString($item['svg']);
        $item['polygon_data'] = json_decode((string) ($item['polygon_data'] ?? ''));
        $item['mobile_svg'] = irep_transformSvgString($item['mobile_svg'] ?? '');
        $decoded_mobile_polygon_data = json_decode((string) ($item['mobile_polygon_data'] ?? ''), true);
        $item['mobile_polygon_data'] = is_array($decoded_mobile_polygon_data) ? $decoded_mobile_polygon_data : [];

        foreach ($item['360images'] as &$image) {
            if (!is_array($image)) {
                continue;
            }
            $image['svg'] = irep_transformSvgString($image['svg'] ?? '');
            $image['svgRef'] = null;
        }
        unset($image);

        $decoded_views = json_decode((string) ($item['project_views'] ?? ''), true);
        $item['project_views'] = is_array($decoded_views) ? $decoded_views : [];
        foreach ($item['project_views'] as &$view) {
            if (!is_array($view)) {
                continue;
            }
            $view['svg'] = irep_transformSvgString($view['svg'] ?? '');
            $view['svgRef'] = null;
            $view['mobile_svg'] = irep_transformSvgString($view['mobile_svg'] ?? '');
            $view['mobile_polygon_data'] = isset($view['mobile_polygon_data']) && is_array($view['mobile_polygon_data']) ? $view['mobile_polygon_data'] : [];
            $view['mobile_svgRef'] = null;
        }
        unset($view);

        return $item;
    }

    public function canUserAddProject($data)
    {
        $projects = $this->get_projects($data)[1];
        $check = !ire_fs()->can_use_premium_code() && count($projects) >= 1;

        if ($check) {
            irep_upgrade_plan();
        }
    }
}

// Initialize the Irep_Project class.
$irep_project = new Irep_Project();

/**
 * AJAX handler function to retrieve all projects.
 */
function irep_get_projects()
{
    global $irep_project;
    $results = $irep_project->get_projects($_POST);


    // Send the results or error as a JSON response.
    if (!$results[0]) {
        irep_send_json_response(false, $results[1]);
    } else {
        irep_send_json_response(true, $results[1]);
    }
}

/**
 * AJAX handler function to create a new project.
 */
function irep_create_project()
{
    global $irep_project;
    $irep_project->create_project($_POST);
}

/**
 * AJAX handler function to update an existing project.
 */
function irep_update_project()
{
    global $irep_project;
    $irep_project->update_project($_POST);
}

/**
 * AJAX handler function to delete a project.
 */
function irep_delete_project()
{
    global $irep_project;
    $irep_project->delete_project($_POST);
}

// Register the AJAX actions for WordPress.
add_action('wp_ajax_irep_get_projects', 'irep_get_projects');
add_action('wp_ajax_irep_create_project', 'irep_create_project');
add_action('wp_ajax_irep_update_project', 'irep_update_project');
add_action('wp_ajax_irep_delete_project', 'irep_delete_project');
