<?php
namespace ONLINE_ADAv4;

add_action("wp_ajax_oada__regenerate_sitemap", __NAMESPACE__ . "\\regenerate_sitemap");

function regenerate_sitemap()
{
    delete_option("_oadaas_sitemap");
    $sitemap = [];
    $pages = get_pages();
    $posts = get_posts();
    $merged = array_merge($pages, $posts);
    array_unshift($merged, home_url());
    $pattern = "/\.\w+$/"; //check for extensions.
    foreach ($merged as $object) {
        
        $link = $object;
        if( $object !== \home_url() ){
            $link = sanitize_text_field(trim(untrailingslashit(get_page_link($object->ID))));
            preg_match($pattern, $link, $match);
        }
        
        if(!empty($match) && ( strpos($match[0], ".php") === FALSE && strpos($match[0], ".html") === FALSE ) ){
            continue;
        }

        if (strpos($link, "?") !== false) {
            $sitemap["query_links"][] = $link;
        } else {
            $sitemap["non_query_links"][] = $link;
        }
    }

    $result = add_option("_oadaas_sitemap", $sitemap);
    echo $result ? wp_json_encode(get_option("_oadaas_sitemap")) : false;
    wp_die();
}

add_action("wp_ajax_oada__save_sitemap", __NAMESPACE__ . "\\save_sitemap");
function save_sitemap()
{
    if (!isset($_POST["sitemap"]) || empty($_POST["sitemap"])) {
        echo "empty";
        exit;
    }
    $sitemap_pre = $_POST["sitemap"];
    $sitemap_final = [];
    
    $pattern = "/\.(\w+)$/"; //check for extensions.
    foreach ($sitemap_pre as $link) {
        $link = sanitize_text_field(trim(untrailingslashit($link)));
        if( $link !== home_url() ){
            preg_match($pattern, $link, $match);
        }
        
        if(!empty($match) && in_array($match[1], Helper::media_extensions())){
            continue;
        }
        
        if(strpos( $link, home_url() ) === false){
            continue;
        }

        if (strpos($link, "?") !== false) {
            $sitemap_final["query_links"][] = $link;
        } else {
            $sitemap_final["non_query_links"][] = $link;
        }
    }
    delete_option("_oadaas_sitemap");
    $re = add_option("_oadaas_sitemap", $sitemap_final);
    echo $re ? wp_json_encode(get_option("_oadaas_sitemap")) : "failed";
    wp_die();
}

add_action("wp_ajax_oada__parse_upload", __NAMESPACE__ . "\\parse_upload");
function parse_upload()
{
    $re = server_validate_upload($_FILES["file"]);
    if ($re != "success") {
        echo wp_kses($re,wp_kses_allowed_html());
        wp_die();
    }
    delete_option("_oadaas_sitemap");
    $sitemap_unfiltered = [];
    $path = wp_upload_dir()["basedir"] . "/oadaas/sitemap/sitemap.csv";
    if (is_file($path) && file_exists($path)) {
        $file = fopen($path, 'r');  // phpcs:ignore

        while (($line = fgetcsv($file, 0, "\n")) !== false) {
            $link = esc_html(wp_strip_all_tags($line[0], true));

            if (strpos($link, "?") !== false) {
                $sitemap_unfiltered["query_links"][] = sanitize_text_field(trim(untrailingslashit($link)));
            } else {
                $sitemap_unfiltered["non_query_links"][] = sanitize_text_field(trim(untrailingslashit($link)));
            }
        }

        fclose($file);  // phpcs:ignore
        wp_delete_file($path);

        $sitemap_final = filter_uploaded_sitemap($sitemap_unfiltered);
        $re = add_option("_oadaas_sitemap", $sitemap_final);
    }

    //Return the unfiltered array so the user can see feedback about why some links may not have been saved
    echo wp_json_encode($sitemap_unfiltered);
    wp_die();
}

function filter_uploaded_sitemap($sitemap)
{
    $returnMe = [];
    foreach ($sitemap as $type => $links) {
        foreach ($links as $link) {
            if ((strpos($link, "http://") !== false && strpos($link, "http://") === 0) || (strpos($link, "https://") !== false && strpos($link, "https://") === 0) &&
                strpos($link, home_url()) !== false) {
                $returnMe[$type] = sanitize_text_field(trim(untrailingslashit($link)));
            }
        }
    }
    return $returnMe;
}

function server_validate_upload($file)
{
    // Verify user has appropriate permissions
    if (!current_user_can('manage_options')) {
        return "Unauthorized access";
    }

    // Validate file exists and has no errors
    if (!isset($file) || $file['error'] !== UPLOAD_ERR_OK) {
        return "File upload error: " . (isset($file['error']) ? $file['error'] : 'Unknown error');
    }

    // Get file extension and validate
    $pathinfo = pathinfo($file['name']);
    $extension = strtolower($pathinfo["extension"] ?? '');
    
    // Define allowed file formats
    $supportedFormats = ['csv', 'txt', 'xml', 'xls', 'xlsx'];
    
    if (!in_array($extension, $supportedFormats)) {
        return "Incorrect file format: " . esc_html($extension);
    }
    
    // Additional security check - prevent image uploads disguised as other formats
    $finfo = new \finfo(FILEINFO_MIME_TYPE);
    $mime_type = $finfo->file($file["tmp_name"]);
    $allowed_mime_types = [
        'text/csv', 'text/plain', 'application/xml', 'text/xml',
        'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    ];
    
    if (!in_array($mime_type, $allowed_mime_types)) {
        return "Invalid file type detected: " . esc_html($mime_type);
    }
    
    // Set up directory with secure permissions
    $basedir = wp_upload_dir()["basedir"];
    $rel_path = "/oadaas/sitemap/";
    $upload_dir = $basedir . $rel_path;
    
    // Create directory with secure permissions if it doesn't exist
    if (!file_exists($upload_dir)) {
        if (!wp_mkdir_p($upload_dir, 0755, true)) {
            return "Failed to create upload directory";
        }
    }
    
    // Set secure file path
    $filename = "sitemap." . $extension;
    $path = $upload_dir . $filename;
    
    // Move uploaded file
    if (!move_uploaded_file($file["tmp_name"], $path)) {
        return "Failed to move uploaded file";
    }
    
    // Process file based on type
    if ($extension === 'csv') {
        // Process CSV file
        try {
            $put_arr = [];
            $f = fopen($path, 'r');
            if (!$f) {
                wp_delete_file($path);
                return "Failed to open CSV file";
            }
            
            while (($line = fgetcsv($f, 0, ",")) !== false) {
                $put_arr[] = $line;
            }
            fclose($f);
            
            // Only proceed if we have data
            if (empty($put_arr) || empty($put_arr[0])) {
                wp_delete_file($path);
                return "CSV file is empty or invalid";
            }
            
            // Rewrite the CSV file securely
            $f = fopen($path, "w");
            if (!$f) {
                wp_delete_file($path);
                return "Failed to write CSV file";
            }
            
            foreach ($put_arr[0] as $item) {
                fputcsv($f, [sanitize_text_field($item)], ',', '"');
            }
            
            $stat = fstat($f);
            ftruncate($f, $stat['size'] - 1);
            fclose($f);
            
            return "success";
        } catch (\Exception $e) {
            // Clean up on error
            if (file_exists($path)) {
                wp_delete_file($path);
            }
            return "Error processing CSV: " . esc_html($e->getMessage());
        }
    } else if ($extension === 'xml') {
        // Convert XML to CSV
        try {
            if (!file_exists($path)) {
                return "XML file not found after upload";
            }
            
            // Validate XML structure before processing
            $xml = @simplexml_load_file($path);
            if ($xml === false) {
                wp_delete_file($path);
                return "Invalid XML file";
            }
            
            $csv_path = $upload_dir . "sitemap.csv";
            $f = fopen($csv_path, 'w');
            if (!$f) {
                wp_delete_file($path);
                return "Failed to create CSV file";
            }
            
            // Convert XML to CSV with proper error handling
            $result = convert_xml_to_csv($xml, $f);
            if ($result === false) {
                fclose($f);
                wp_delete_file($csv_path);
                wp_delete_file($path);
                return "Failed to convert XML to CSV";
            }
            
            $stat = fstat($f);
            ftruncate($f, $stat['size'] - 1);
            fclose($f);
            
            // Remove the original XML file after successful conversion
            wp_delete_file($path);
            
            return "success";
        } catch (\Exception $e) {
            // Clean up on error
            if (file_exists($path)) {
                wp_delete_file($path);
            }
            if (file_exists($upload_dir . "sitemap.csv")) {
                wp_delete_file($upload_dir . "sitemap.csv");
            }
            return "Error processing XML: " . esc_html($e->getMessage());
        }
    } else {
        // For other file types that need conversion but aren't implemented yet
        wp_delete_file($path);
        return "File type " . esc_html($extension) . " is supported but conversion is not implemented";
    }
}


function convert_xml_to_csv($xml, $f)
{
    foreach ($xml->children() as $item) {
        $hasChild = (count($item->children()) > 0) ? true : false;

        if (!$hasChild) {
            if ($item->getName() === "loc") {
                fputcsv($f, [$item], ',', '"');
            }
        } else {
            convert_xml_to_csv($item, $f);
        }
    }
}
