<?php
/**
 * Custom icons (open + close), size and padding for the Navigation block burger.
 *
 * 1. Allow SVG uploads (admins only) via upload_mimes.
 * 2. On render of core/navigation, inject a scoped <style> that:
 *    - hides the native <svg> in the open/close buttons
 *    - paints the user's icon via mask-image (so it inherits currentColor)
 *    - applies the configured size and button padding
 * 3. The close icon also drives our .audace-menu-overlay__close button.
 */

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

// --- SVG upload support (admins only) -----------------------------------

add_filter( 'upload_mimes', function ( $mimes ) {
    if ( current_user_can( 'manage_options' ) ) {
        $mimes['svg'] = 'image/svg+xml';
    }
    return $mimes;
} );

add_filter( 'wp_check_filetype_and_ext', function ( $data, $file, $filename, $mimes ) {
    if ( ! empty( $data['ext'] ) && ! empty( $data['type'] ) ) {
        return $data;
    }
    $ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
    if ( 'svg' === $ext && current_user_can( 'manage_options' ) ) {
        $data['ext']             = 'svg';
        $data['type']            = 'image/svg+xml';
        $data['proper_filename'] = $filename;
    }
    return $data;
}, 10, 4 );

// --- Render-time icon swap ----------------------------------------------

/**
 * Resolve the open/close icon URLs and dimensions for a navigation block,
 * falling back to the Customizer mod for the open icon.
 */
/**
 * Sanitize a CSS length value (e.g. "24px", "1.5em", "5%"). Falls back to $default.
 * Accepts integers/floats too (treated as px) for back-compat with older saved attrs.
 */
/**
 * Accept hex, rgb(a), hsl(a), or var(--*) values; reject everything else.
 * Returns a safe-to-inject-as-CSS color string, or '' if invalid / empty.
 */
function audace_sanitize_color( $value ) {
    if ( ! is_string( $value ) ) return '';
    $v = trim( $value );
    if ( $v === '' ) return '';
    if ( preg_match( '/^(#[0-9a-f]{3,8}|rgba?\([^)]+\)|hsla?\([^)]+\)|var\(--[a-z0-9\-_]+\))$/i', $v ) ) {
        return $v;
    }
    return '';
}

function audace_sanitize_length( $value, $default ) {
    if ( is_numeric( $value ) ) {
        return ( (float) $value ) . 'px';
    }
    if ( ! is_string( $value ) || $value === '' ) {
        return $default;
    }
    if ( ! preg_match( '/^-?\d*\.?\d+(px|em|rem|%|vh|vw|svh|dvh|lvh|ch)$/i', trim( $value ) ) ) {
        return $default;
    }
    return trim( $value );
}

/**
 * Resolve the aspect ratio (width/height) of an SVG at a given URL, so we can
 * keep width fixed and let height scale naturally. Returns null if unknown.
 */
function audace_svg_aspect_ratio( $url ) {
    if ( ! $url ) {
        return null;
    }
    static $cache = array();
    if ( array_key_exists( $url, $cache ) ) {
        return $cache[ $url ];
    }

    $path = null;
    $uploads = wp_get_upload_dir();
    if ( ! empty( $uploads['baseurl'] ) && strpos( $url, $uploads['baseurl'] ) === 0 ) {
        $path = $uploads['basedir'] . substr( $url, strlen( $uploads['baseurl'] ) );
    }

    $svg = '';
    if ( $path && is_readable( $path ) ) {
        $svg = (string) file_get_contents( $path );
    }
    if ( $svg === '' ) {
        return $cache[ $url ] = null;
    }

    $ratio = null;
    if ( preg_match( '/<svg[^>]*\bviewBox\s*=\s*["\']\s*[-\d.]+\s+[-\d.]+\s+([\d.]+)\s+([\d.]+)/i', $svg, $m ) ) {
        $w = (float) $m[1]; $h = (float) $m[2];
        if ( $w > 0 && $h > 0 ) $ratio = $w / $h;
    } elseif ( preg_match( '/<svg[^>]*\bwidth\s*=\s*["\']([\d.]+)/i', $svg, $mw )
            && preg_match( '/<svg[^>]*\bheight\s*=\s*["\']([\d.]+)/i', $svg, $mh ) ) {
        $w = (float) $mw[1]; $h = (float) $mh[1];
        if ( $w > 0 && $h > 0 ) $ratio = $w / $h;
    }
    return $cache[ $url ] = $ratio;
}

function audace_nav_icon_settings_for_block( $attrs ) {
    $open_id   = isset( $attrs['audaceIconId'] )      ? (int) $attrs['audaceIconId']      : 0;
    $close_id  = isset( $attrs['audaceCloseIconId'] ) ? (int) $attrs['audaceCloseIconId'] : 0;

    $open_url  = ! empty( $attrs['audaceIconUrl'] )      ? esc_url_raw( $attrs['audaceIconUrl'] )      : ( $open_id  ? wp_get_attachment_url( $open_id )  : '' );
    $close_url = ! empty( $attrs['audaceCloseIconUrl'] ) ? esc_url_raw( $attrs['audaceCloseIconUrl'] ) : ( $close_id ? wp_get_attachment_url( $close_id ) : '' );

    return array(
        'open_url'      => $open_url,
        'close_url'     => $close_url,
        'open_size'     => audace_sanitize_length( $attrs['audaceOpenSize']  ?? null, '24px' ),
        'open_pad_y'    => audace_sanitize_length( $attrs['audaceOpenPadY']  ?? null, '8px' ),
        'open_pad_x'    => audace_sanitize_length( $attrs['audaceOpenPadX']  ?? null, '8px' ),
        'close_size'    => audace_sanitize_length( $attrs['audaceCloseSize'] ?? null, '24px' ),
        'close_pad_y'   => audace_sanitize_length( $attrs['audaceClosePadY'] ?? null, '8px' ),
        'close_pad_x'   => audace_sanitize_length( $attrs['audaceClosePadX'] ?? null, '8px' ),
        'sticky'        => ! empty( $attrs['audaceSticky'] ),
        'sticky_offset' => audace_sanitize_length( $attrs['audaceStickyOffset'] ?? null, '0px' ),
    );
}

add_filter( 'render_block', function ( $block_content, $block ) {
    if ( empty( $block['blockName'] ) || 'core/navigation' !== $block['blockName'] ) {
        return $block_content;
    }

    // Audace nav colors (link text + hover): scoped <style> so each nav
    // instance can be styled independently.
    $attrs  = $block['attrs'] ?? array();
    $text   = audace_sanitize_color( $attrs['audaceTextColor']  ?? '' );
    $hover  = audace_sanitize_color( $attrs['audaceHoverColor'] ?? '' );
    if ( $text !== '' || $hover !== '' ) {
        $uid = 'audace-nav-c-' . substr( md5( $block_content . $text . $hover ), 0, 8 );
        $block_content = preg_replace(
            '/(<nav\b[^>]*class="[^"]*)(")/',
            '$1 ' . $uid . '$2',
            $block_content,
            1
        );
        $css = '';
        if ( $text !== '' ) {
            $css .= '.' . $uid . ' .wp-block-navigation-item__content,';
            $css .= '.' . $uid . ' .wp-block-navigation-item a,';
            $css .= '.' . $uid . ' .wp-block-navigation-item button,';
            // Overlay nav has no <nav> wrapper, so the uid class isn't on
            // anything — scope to the overlay container itself instead.
            $css .= '.audace-menu-overlay__inner a,';
            $css .= '.audace-menu-overlay__inner button';
            $css .= '{color:' . $text . '!important;}';
        }
        if ( $hover !== '' ) {
            $css .= '.' . $uid . ' .wp-block-navigation-item__content:hover,';
            $css .= '.' . $uid . ' .wp-block-navigation-item__content:focus,';
            $css .= '.' . $uid . ' .wp-block-navigation-item a:hover,';
            $css .= '.' . $uid . ' .wp-block-navigation-item a:focus,';
            $css .= '.' . $uid . ' .wp-block-navigation-item button:hover,';
            $css .= '.' . $uid . ' .wp-block-navigation-item button:focus,';
            $css .= '.audace-menu-overlay__inner a:hover,';
            $css .= '.audace-menu-overlay__inner a:focus,';
            $css .= '.audace-menu-overlay__inner button:hover,';
            $css .= '.audace-menu-overlay__inner button:focus';
            $css .= '{color:' . $hover . '!important;}';
        }
        $block_content = '<style>' . $css . '</style>' . $block_content;
    }

    $cfg = audace_nav_icon_settings_for_block( $block['attrs'] ?? array() );

    $is_default = ! $cfg['open_url'] && ! $cfg['close_url']
        && $cfg['open_size']  === '24px' && $cfg['open_pad_y']  === '8px' && $cfg['open_pad_x']  === '8px'
        && $cfg['close_size'] === '24px' && $cfg['close_pad_y'] === '8px' && $cfg['close_pad_x'] === '8px'
        && ! $cfg['sticky'];
    if ( $is_default ) {
        return $block_content;
    }

    $uid = 'audace-nav-' . substr( md5( $block_content ), 0, 8 );
    $block_content = preg_replace(
        '/(<nav\b[^>]*class="[^"]*)(")/',
        '$1 ' . $uid . '$2',
        $block_content,
        1
    );

    $css = '';

    if ( $cfg['open_url'] ) {
        $u = esc_url( $cfg['open_url'] );
        $s = $cfg['open_size'];
        $r = audace_svg_aspect_ratio( $cfg['open_url'] );
        $ar = $r ? "aspect-ratio:{$r};" : '';
        $css .= ".$uid .wp-block-navigation__responsive-container-open > svg{display:none!important;}";
        $css .= ".$uid .wp-block-navigation__responsive-container-open::before{content:\"\";display:inline-block;width:{$s};height:auto;{$ar}background:url('$u') center/contain no-repeat;}";
    }
    if ( $cfg['close_url'] ) {
        $u  = esc_url( $cfg['close_url'] );
        $s  = $cfg['close_size'];
        $py = $cfg['close_pad_y'];
        $px = $cfg['close_pad_x'];
        $r  = audace_svg_aspect_ratio( $cfg['close_url'] );
        $ar = $r ? "aspect-ratio:{$r};" : '';
        $css .= ".$uid .wp-block-navigation__responsive-container-close > svg{display:none!important;}";
        $css .= ".$uid .wp-block-navigation__responsive-container-close::before{content:\"\";display:inline-block;width:{$s};height:auto;{$ar}background:url('$u') center/contain no-repeat;}";
        // Mirror the close icon onto our custom overlay close button.
        $css .= ".audace-menu-overlay__close{font-size:0;padding:{$py} {$px};}";
        $css .= ".audace-menu-overlay__close::before{content:\"\";display:block;width:{$s};height:auto;{$ar}background:url('$u') center/contain no-repeat;}";
    }

    $css .= ".$uid .wp-block-navigation__responsive-container-open{padding:{$cfg['open_pad_y']} {$cfg['open_pad_x']}!important;}";
    $css .= ".$uid .wp-block-navigation__responsive-container-close{padding:{$cfg['close_pad_y']} {$cfg['close_pad_x']}!important;}";

    $extra = '';
    if ( $cfg['sticky'] ) {
        $top = "calc({$cfg['sticky_offset']} + var(--wp-admin--admin-bar--height, 0px))";
        $css .= ".$uid{position:sticky!important;top:{$top}!important;z-index:50;}";
        $css .= "header.audace-sticky-header,.audace-sticky-header{position:sticky!important;top:{$top}!important;z-index:50;}";
        // Add the audace-sticky-header class to the closest ancestor <header> so users can style it.
        $extra = '<script>(function(){var n=document.querySelector(".' . esc_js( $uid ) . '");if(n){var h=n.closest("header");if(h)h.classList.add("audace-sticky-header");}})();</script>';
    }

    return '<style>' . $css . '</style>' . $block_content . $extra;
}, 10, 2 );
