<?php
/**
 * Helper functions for the plugin
 *
 * @package WP_Graphql_YOAST_SEO
 */

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

/**
 * Format string for GraphQL.
 *
 * @param string $string String to format.
 * @return string|null
 */
function wp_gql_seo_format_string($string)
{
    return isset($string) ? html_entity_decode(trim($string)) : null;
}

/**
 * Replace variables in string.
 *
 * @param string $string String with variables.
 * @return string|null
 */
function wp_gql_seo_replace_vars($string)
{
    // Get all the post types that have been registered.
    $post_types = get_post_types();
    // Get all the taxonomies that have been registered.
    $taxomonies = get_taxonomies();
    // Merge them together and pass them through.
    $objects = array_merge($post_types, $taxomonies);
    return isset($string) ? wpseo_replace_vars($string, $objects) : null;
}

/**
 * Get OG image ID from Yoast SEO.
 *
 * @param array $images Array of images from Yoast SEO.
 * @return string|null
 */
function wp_gql_seo_get_og_image($images)
{
    if (empty($images)) {
        return __return_empty_string();
    }

    $image = reset($images);

    if (empty($image)) {
        return __return_empty_string();
    }

    if (!isset($image['url'])) {
        return __return_empty_string();
    }
    // Remove image sizes from url
    $url = preg_replace('/(.*)-\d+x\d+\.(jpg|png|gif)$/', '$1.$2', $image['url']);
    // If the image is equal as the original and the original has an id, return this ID
    if (isset($image['id']) && $url === $image['url']) {
        return $image['id'];
    }
    return wpcom_vip_attachment_url_to_postid($url);
}

/**
 * Normalize field key names for GraphQL.
 *
 * @param string $field_key Field key to normalize.
 * @return string
 */
function wp_gql_seo_get_field_key($field_key)
{
    $field_key = lcfirst(preg_replace('/[^a-zA-Z0-9 \-]/', ' ', $field_key));
    $field_key = lcfirst(str_replace('_', ' ', ucwords($field_key, '_')));
    $field_key = lcfirst(str_replace('-', ' ', ucwords($field_key, '_')));
    $field_key = lcfirst(str_replace(' ', '', ucwords($field_key, ' ')));

    return $field_key;
}

/**
 * Generate cache key for attachment URL.
 *
 * @param string $url URL to generate cache key for.
 * @return string
 */
function wpcom_vip_attachment_cache_key($url)
{
    return 'wpcom_vip_attachment_url_post_id_' . md5($url);
}

/**
 * Get post ID from attachment URL with caching.
 *
 * @param string $url URL to get post ID for.
 * @return int|null
 */
function wpcom_vip_attachment_url_to_postid($url)
{
    $cache_key = wpcom_vip_attachment_cache_key($url);
    $id = wp_cache_get($cache_key);
    if (false === $id) {
        $id = attachment_url_to_postid($url); // phpcs:ignore
        if (empty($id)) {
            wp_cache_set(
                $cache_key,
                'not_found',
                'default',
                12 * HOUR_IN_SECONDS + mt_rand(0, 4 * HOUR_IN_SECONDS) // phpcs:ignore
            );
            $id = null; // Set $id to null instead of false
        } else {
            wp_cache_set(
                $cache_key,
                $id,
                'default',
                24 * HOUR_IN_SECONDS + mt_rand(0, 12 * HOUR_IN_SECONDS) // phpcs:ignore
            );
        }
    } elseif ('not_found' === $id) {
        return null; // Return null instead of false
    }

    return $id;
}

/**
 * Build content types data array for GraphQL schema.
 *
 * @param array $types Post types.
 * @return array
 */
function wp_gql_seo_build_content_types($types)
{
    $carry = [];
    foreach ($types as $type) {
        $post_type_object = get_post_type_object($type);
        if ($post_type_object->graphql_single_name) {
            $carry[wp_gql_seo_get_field_key($post_type_object->graphql_single_name)] = ['type' => 'SEOContentType'];
        }
    }
    return $carry;
}

/**
 * Build taxonomy types data array for GraphQL schema.
 *
 * @param array $taxonomies Taxonomies.
 * @return array
 */
function wp_gql_seo_build_taxonomy_types($taxonomies)
{
    $carry = [];
    foreach ($taxonomies as $taxonomy) {
        $taxonomy_object = get_taxonomy($taxonomy);
        if ($taxonomy_object->graphql_single_name) {
            $carry[wp_gql_seo_get_field_key($taxonomy_object->graphql_single_name)] = ['type' => 'SEOTaxonomyType'];
        }
    }
    return $carry;
}

/**
 * Get full head content from Yoast SEO.
 *
 * @param \Yoast\WP\SEO\Surfaces\Values\Meta|bool $metaForPost Meta object.
 * @return string
 */
function wp_gql_seo_get_full_head($metaForPost)
{
    if ($metaForPost !== false) {
        $head = $metaForPost->get_head();

        return is_string($head) ? $head : $head->html;
    }

    return '';
}

/**
 * Build content type data for GraphQL schema.
 *
 * @param array $types Post types.
 * @param array $all All Yoast SEO options.
 * @return array
 */
function wp_gql_seo_build_content_type_data($types, $all)
{
    $carry = [];

    // Validate input parameters
    if (!is_array($types) || empty($types) || !is_array($all) || empty($all)) {
        return $carry;
    }

    foreach ($types as $type) {
        $post_type_object = get_post_type_object($type);

        // Validate post type object
        if (!$post_type_object || !$post_type_object->graphql_single_name) {
            continue;
        }

        $tag = wp_gql_seo_get_field_key($post_type_object->graphql_single_name);

        $meta = YoastSEO()->meta->for_post_type_archive($type);

        $carry[$tag] = [
            'title' => wp_gql_seo_format_string(wp_gql_seo_replace_vars($all['title-' . $type] ?? null)),
            'metaDesc' => wp_gql_seo_format_string(wp_gql_seo_replace_vars($all['metadesc-' . $type] ?? null)),
            'metaRobotsNoindex' => boolval($all['noindex-' . $type] ?? false),
            'schemaType' => $all['schema-page-type-' . $type] ?? null,
            'schema' => [
                'raw' =>
                    !empty($meta) && !empty($meta->schema) ? wp_json_encode($meta->schema, JSON_UNESCAPED_SLASHES) : null,
            ],
            'archive' => [
                'hasArchive' => boolval($post_type_object->has_archive),
                'archiveLink' => apply_filters('wp_gql_seo_archive_link', get_post_type_archive_link($type), $type),
                'title' => wp_gql_seo_format_string($meta->title ?? null),
                'metaDesc' => wp_gql_seo_format_string($all['metadesc-ptarchive-' . $type] ?? null),
                'metaRobotsNoindex' =>
                    !empty($meta) && !empty($meta->robots['index']) && $meta->robots['index'] === 'index'
                        ? false
                        : true,
                'metaRobotsNofollow' =>
                    !empty($meta) && !empty($meta->robots['follow']) && $meta->robots['follow'] === 'follow'
                        ? false
                        : true,
                'metaRobotsIndex' => $meta->robots['index'] ?? 'noindex',
                'metaRobotsFollow' => $meta->robots['follow'] ?? 'nofollow',
                'breadcrumbTitle' => wp_gql_seo_format_string($all['bctitle-ptarchive-' . $type] ?? null),
                'fullHead' => wp_gql_seo_get_full_head($meta),
            ],
        ];
    }

    return $carry;
}

/**
 * Build taxonomy data for GraphQL schema.
 *
 * @param array $taxonomies Taxonomies.
 * @param array $all All Yoast SEO options.
 * @return array
 */
function wp_gql_seo_build_taxonomy_data($taxonomies, $all)
{
    $carry = [];

    // Validate input parameters
    if (!is_array($taxonomies) || empty($taxonomies) || !is_array($all) || empty($all)) {
        return $carry;
    }

    foreach ($taxonomies as $taxonomy) {
        $taxonomy_object = get_taxonomy($taxonomy);

        // Validate taxonomy object
        if (!$taxonomy_object || !$taxonomy_object->graphql_single_name) {
            continue;
        }

        $tag = wp_gql_seo_get_field_key($taxonomy_object->graphql_single_name);
        $carry[$tag] = [
            'archive' => [
                'title' => wp_gql_seo_format_string(wp_gql_seo_replace_vars($all['title-tax-' . $taxonomy] ?? null)),
                'metaDesc' => wp_gql_seo_format_string(
                    wp_gql_seo_replace_vars($all['metadesc-tax-' . $taxonomy] ?? null)
                ),
                'metaRobotsNoindex' => boolval($all['noindex-tax-' . $taxonomy] ?? false),
            ],
        ];
    }

    return $carry;
}
