<?php
/**
 * Helpers for determining where translation files should be stored.
 *
 * @package WPR_Translate
 */

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

/**
 * Retrieve a list of directories that could store generated translation files.
 *
 * @return string[]
 */
function wpr_translate_get_custom_translations_directory_candidates() {
    // Build the list of candidate directories.
    $directories = array();

    if ( function_exists( 'get_stylesheet_directory' ) ) {
        $stylesheet_directory = trailingslashit( get_stylesheet_directory() );

        if ( '' !== $stylesheet_directory ) {
            // Prefer the child theme language directory.
            $directories[] = $stylesheet_directory . 'languages/wpr';
        }
    }

    if ( function_exists( 'get_template_directory' ) ) {
        $template_directory = trailingslashit( get_template_directory() );

        if ( '' !== $template_directory ) {
            // Fall back to the parent theme language directory.
            $directories[] = $template_directory . 'languages/wpr';
        }
    }

    // Always include the plugin language directory as a fallback.
    $directories[] = trailingslashit( WPR_TRANSLATE_PLUGIN_ROOT ) . 'languages/wpr';

    // Remove duplicates and empty values.
    $directories = array_values( array_unique( array_filter( $directories ) ) );

    /**
     * Filter the list of directories that could store generated translation files.
     *
     * @param string[] $directories Absolute paths to directories.
     */
    return apply_filters( 'wpr_translate_custom_translations_directory_candidates', $directories );
}

/**
 * Cache the directory path used to store generated translation files.
 *
 * @param string $directory Absolute path to the directory.
 */
function wpr_translate_cache_custom_translations_directory( $directory ) {
    // Normalize and store the directory in globals and options.
    $directory = (string) $directory;

    if ( '' !== $directory && function_exists( 'wp_normalize_path' ) ) {
        $directory = wp_normalize_path( $directory );
    }

    $GLOBALS['wpr_translate_custom_directory'] = $directory;

    if ( function_exists( 'update_option' ) && function_exists( 'get_option' ) ) {
        $current = get_option( 'wpr_translate_custom_directory', null );

        if ( null === $current || (string) $current !== $directory ) {
            // Persist the directory when it changes.
            update_option( 'wpr_translate_custom_directory', $directory );
        }
    }
}

/**
 * Retrieve the cached directory path used for generated translation files.
 *
 * @return string
 */
function wpr_translate_get_cached_custom_translations_directory() {
    if ( isset( $GLOBALS['wpr_translate_custom_directory'] ) ) {
        // Return the request-scoped cached directory when available.
        return (string) $GLOBALS['wpr_translate_custom_directory'];
    }

    if ( function_exists( 'get_option' ) ) {
        // Load the stored directory from options as a fallback.
        $stored = get_option( 'wpr_translate_custom_directory', '' );

        if ( '' !== $stored ) {
            $stored = (string) $stored;

            if ( function_exists( 'wp_normalize_path' ) ) {
                $stored = wp_normalize_path( $stored );
            }

            // Cache the stored path for later calls.
            $GLOBALS['wpr_translate_custom_directory'] = $stored;

            return $stored;
        }
    }

    return '';
}

/**
 * Select the most appropriate directory from the provided candidates.
 *
 * @param string[] $candidates Ordered list of potential directories.
 *
 * @return string
 */
function wpr_translate_select_preferred_translations_directory( $candidates ) {
    if ( empty( $candidates ) ) {
        // No candidates to select from.
        return '';
    }

    $first_candidate       = '';
    $first_theme_candidate = '';
    $fallback_candidate    = '';

    foreach ( $candidates as $index => $candidate ) {
        $candidate = (string) $candidate;

        if ( '' === $candidate ) {
            // Skip empty entries.
            continue;
        }

        if ( '' === $first_candidate ) {
            $first_candidate = $candidate;
        }

        $is_theme_candidate = ( $index < 2 );

        if ( $is_theme_candidate && '' === $first_theme_candidate ) {
            $first_theme_candidate = $candidate;
        }

        if ( is_dir( $candidate ) && is_writable( $candidate ) ) {
            // Prefer writable theme directories first.
            if ( $is_theme_candidate ) {
                return $candidate;
            }

            if ( '' === $first_theme_candidate ) {
                return $candidate;
            }

            if ( '' === $fallback_candidate ) {
                $fallback_candidate = $candidate;
            }
        }
    }

    if ( '' !== $first_theme_candidate ) {
        // Fall back to the first theme directory.
        return $first_theme_candidate;
    }

    if ( '' !== $fallback_candidate ) {
        // Use the first writable fallback.
        return $fallback_candidate;
    }

    return $first_candidate;
}

/**
 * Retrieve the directory used to store generated translation files.
 *
 * @return string
 */
function wpr_translate_get_custom_translations_directory() {
    // Load cached value and candidate list.
    $cached_directory = wpr_translate_get_cached_custom_translations_directory();
    $candidates       = wpr_translate_get_custom_translations_directory_candidates();

    if ( '' === $cached_directory ) {
        // Select and cache a directory when none is stored yet.
        $selected         = wpr_translate_select_preferred_translations_directory( $candidates );
        $cached_directory = $selected;

        wpr_translate_cache_custom_translations_directory( $cached_directory );
    }

    /**
     * Filter the directory that stores generated translation files.
     *
     * @param string   $cached_directory Absolute path to the directory.
     * @param string[] $candidates       List of candidate directories.
     */
    return apply_filters( 'wpr_translate_custom_translations_directory', $cached_directory, $candidates );
}

/**
 * Attempt to prepare a specific directory for storing generated translation files.
 *
 * @param string $directory Absolute path to the directory.
 *
 * @return string|WP_Error
 */
function wpr_translate_prepare_specific_translations_directory( $directory ) {
    // Normalize the input directory for consistent checks.
    $directory = (string) $directory;

    if ( '' === $directory ) {
        // Fail fast when no directory is provided.
        return new WP_Error( 'wpr_translate_invalid_directory', __( 'The translations directory is not configured.', 'wpr-translate' ) );
    }

    if ( is_dir( $directory ) ) {
        if ( is_writable( $directory ) ) {
            // Existing writable directory is ready to use.
            return $directory;
        }

        return new WP_Error( 'wpr_translate_directory_unwritable', __( 'The translations directory is not writable.', 'wpr-translate' ) );
    }

    if ( wp_mkdir_p( $directory ) ) {
        if ( is_writable( $directory ) ) {
            // Newly created directory is writable.
            return $directory;
        }

        return new WP_Error( 'wpr_translate_directory_unwritable', __( 'The translations directory is not writable.', 'wpr-translate' ) );
    }

    if ( is_dir( $directory ) && is_writable( $directory ) ) {
        // Directory exists now and is writable.
        return $directory;
    }

    if ( is_dir( $directory ) && ! is_writable( $directory ) ) {
        // Directory exists but cannot be written to.
        return new WP_Error( 'wpr_translate_directory_unwritable', __( 'The translations directory is not writable.', 'wpr-translate' ) );
    }

    return new WP_Error( 'wpr_translate_directory_uncreatable', __( 'Could not create the translations directory.', 'wpr-translate' ) );
}

/**
 * Ensure the custom translations directory exists and is writable.
 *
 * @return string|WP_Error Absolute path on success, error otherwise.
 */
function wpr_translate_prepare_custom_translations_directory() {
    // Iterate through candidates until one can be prepared.
    $candidates = wpr_translate_get_custom_translations_directory_candidates();

    if ( empty( $candidates ) ) {
        // No candidate directories available.
        return new WP_Error( 'wpr_translate_invalid_directory', __( 'The translations directory is not configured.', 'wpr-translate' ) );
    }

    $last_error = new WP_Error( 'wpr_translate_directory_uncreatable', __( 'Could not create the translations directory.', 'wpr-translate' ) );

    foreach ( $candidates as $candidate ) {
        $result = wpr_translate_prepare_specific_translations_directory( $candidate );

        if ( is_wp_error( $result ) ) {
            // Track the last failure and keep trying.
            $last_error = $result;
            continue;
        }

        // Cache the usable directory and return it.
        wpr_translate_cache_custom_translations_directory( $result );

        return $result;
    }

    return $last_error;
}

