<?php

declare(strict_types=1);

namespace SecurWP\Modules\WhiteLabel;

use SecurWP\Includes\Interfaces\Module;
use SecurWP\Includes\SettingsStore;

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

class WhiteLabel implements Module {

    private $branding = [];
    private $plugin_name;
    private $version;
    
    public function __construct( string $plugin_name, string $version ) {
        $this->plugin_name = $plugin_name;
        $this->version = $version;
        $this->branding = self::sanitize_branding( SettingsStore::get( SettingsStore::COL_BRANDING ) );
    }

    /**
     * Sanitize a branding text value.
     *
     * @param mixed $value Raw text value.
     * @param int   $max_length Maximum stored length.
     * @return string
     */
    public static function sanitize_brand_text( $value, int $max_length = 160 ): string {
        $value = sanitize_text_field( (string) $value );
        if ( function_exists( 'mb_substr' ) ) {
            return mb_substr( $value, 0, $max_length );
        }
        return substr( $value, 0, $max_length );
    }

    /**
     * Sanitize a public branding URL.
     *
     * @param mixed $value Raw URL value.
     * @return string
     */
    public static function sanitize_brand_url( $value ): string {
        $url = trim( (string) $value );
        if ( '' === $url ) {
            return '';
        }

        if ( strlen( $url ) > 2048 || preg_match( '/[\x00-\x1F\x7F]/', $url ) ) {
            return '';
        }

        $parts = wp_parse_url( $url );
        if ( ! is_array( $parts ) ) {
            return '';
        }

        $scheme = strtolower( (string) ( $parts['scheme'] ?? '' ) );
        $host   = strtolower( trim( (string) ( $parts['host'] ?? '' ) ) );
        if ( 'https' !== $scheme || '' === $host || ! empty( $parts['user'] ) || ! empty( $parts['pass'] ) ) {
            return '';
        }
        if ( 'localhost' === $host || substr( $host, -6 ) === '.local' ) {
            return '';
        }
        if ( filter_var( $host, FILTER_VALIDATE_IP ) && ! filter_var( $host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
            return '';
        }

        return esc_url_raw( $url, [ 'https' ] );
    }

    /**
     * Normalize boolean values from JSON, import files, and options.
     *
     * @param mixed $value Raw boolean-like value.
     * @return bool
     */
    private static function normalize_brand_bool( $value ): bool {
        if ( is_bool( $value ) ) {
            return $value;
        }
        if ( is_int( $value ) || is_float( $value ) ) {
            return (int) $value === 1;
        }
        if ( is_string( $value ) ) {
            return in_array( strtolower( trim( $value ) ), [ '1', 'true', 'yes', 'on' ], true );
        }
        return false;
    }

    /**
     * Normalize branding payloads before persistence.
     *
     * @param mixed $branding Raw branding payload.
     * @return array<string,mixed>
     */
    public static function normalize_branding( $branding ): array {
        if ( ! is_array( $branding ) ) {
            return [];
        }

        $clean_data = [];

        $required_text_fields = [
            'plugin_name'  => 80,
            'company_name' => 120,
        ];
        foreach ( $required_text_fields as $field => $max_length ) {
            if ( array_key_exists( $field, $branding ) ) {
                $value = self::sanitize_brand_text( $branding[ $field ], $max_length );
                if ( '' !== $value ) {
                    $clean_data[ $field ] = $value;
                }
            }
        }

        $text_fields = [
            'plugin_description' => 300,
            'author_name'        => 120,
            'admin_footer_text'  => 240,
            'email_from_name'    => 120,
        ];
        foreach ( $text_fields as $field => $max_length ) {
            if ( array_key_exists( $field, $branding ) ) {
                $clean_data[ $field ] = self::sanitize_brand_text( $branding[ $field ], $max_length );
            }
        }

        $url_fields = [ 'author_url', 'plugin_url', 'support_url', 'logo_url' ];
        foreach ( $url_fields as $field ) {
            if ( array_key_exists( $field, $branding ) ) {
                $clean_data[ $field ] = self::sanitize_brand_url( $branding[ $field ] );
            }
        }

        $bool_fields = [ 'hide_attribution', 'hide_plugin' ];
        foreach ( $bool_fields as $field ) {
            if ( array_key_exists( $field, $branding ) ) {
                $clean_data[ $field ] = self::normalize_brand_bool( $branding[ $field ] );
            }
        }

        return $clean_data;
    }

    /**
     * Sanitize persisted branding payloads.
     *
     * @param mixed $branding Raw branding payload.
     * @return array<string,mixed>
     */
    private static function sanitize_branding( $branding ): array {
        return self::normalize_branding( $branding );
    }

    public function initialize( \SecurWP\Includes\Module_Loader $loader ) {
        if ( empty( $this->branding ) ) {
            return;
        }

        $loader->add_action( 'admin_menu', $this, 'update_menu_name', 999 );
        $loader->add_filter( 'admin_footer_text', $this, 'update_footer_text', 999 );
        $loader->add_filter( 'all_plugins', $this, 'override_plugin_metadata', 999 );
        $loader->add_filter( 'admin_title', $this, 'override_admin_title', 999 );
    }

    public function update_menu_name() {
        global $menu;
        $plugin_name = $this->branding['plugin_name'] ?? 'securwp';

        if ( empty( $plugin_name ) || strcasecmp( $plugin_name, 'securwp' ) === 0 ) {
            return;
        }

        foreach ( $menu as $key => $item ) {
            if ( $item[2] === 'securwp' ) {
                $menu[$key][0] = esc_html( $plugin_name );
                break;
            }
        }
    }

    public function update_footer_text( $text ) {
        $screen = get_current_screen();
        if ( ! $screen || strpos( $screen->id, 'securwp' ) === false ) {
            return $text;
        }

        if ( ! empty( $this->branding['admin_footer_text'] ) ) {
            return wp_kses_post( $this->branding['admin_footer_text'] );
        }
        if ( ! empty( $this->branding['hide_attribution'] ) ) {
            return '';
        }
        return $text;
    }

    /**
     * Override plugin metadata on the Plugins page.
     *
     * @param array $plugins
     * @return array
     */
    public function override_plugin_metadata( $plugins ) {
        $plugin_file = 'securwp/securwp.php';
        if ( ! isset( $plugins[ $plugin_file ] ) ) {
            return $plugins;
        }

        if ( ! empty( $this->branding['hide_plugin'] ) ) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only query flag used only to reveal a hidden admin list entry.
            if ( sanitize_text_field( wp_unslash( $_GET['show_hidden_plugins'] ?? '' ) ) !== '1' ) {
                unset( $plugins[ $plugin_file ] );
                return $plugins;
            }
        }

        $b = $this->branding;

        // Text fields: escaped for display.
        $text_map = [
            'plugin_name'        => [ 'Name', 'Title' ],
            'plugin_description' => [ 'Description' ],
            'author_name'        => [ 'Author', 'AuthorName' ],
        ];
        foreach ( $text_map as $key => $fields ) {
            if ( ! empty( $b[ $key ] ) ) {
                foreach ( $fields as $f ) {
                    $plugins[ $plugin_file ][ $f ] = esc_html( $b[ $key ] );
                }
            }
        }

        // URL fields: escaped as URLs.
        $url_map = [
            'author_url' => 'AuthorURI',
            'plugin_url' => 'PluginURI',
        ];
        foreach ( $url_map as $key => $field ) {
            if ( ! empty( $b[ $key ] ) ) {
                $plugins[ $plugin_file ][ $field ] = esc_url( $b[ $key ], [ 'https' ] );
            }
        }

        return $plugins;
    }

    /**
     * Get the branded email sender name, or empty string if not set.
     *
     * @return string
     */
    public static function get_email_from_name(): string {
        $branding = SettingsStore::get( SettingsStore::COL_BRANDING );
        $branding = self::normalize_branding( $branding );
        $name = $branding['email_from_name'] ?? '';
        return $name !== '' ? sanitize_text_field( $name ) : '';
    }

    /**
     * Replace "SecurWP" in the browser admin title.
     *
     * @param string $admin_title
     * @return string
     */
    public function override_admin_title( $admin_title ) {
        $screen = get_current_screen();
        if ( ! $screen || strpos( $screen->id, 'securwp' ) === false ) {
            return $admin_title;
        }
        $plugin_name = $this->branding['plugin_name'] ?? '';
        if ( $plugin_name !== '' && strcasecmp( $plugin_name, 'securwp' ) !== 0 ) {
            return str_ireplace( 'securwp', esc_html( $plugin_name ), $admin_title );
        }
        return $admin_title;
    }
    
    /**
     * Called by LicenseManager when branding data is received from Cloud.
     */
    public static function update_settings( $branding_data ) {
        if ( empty( $branding_data ) || ! is_array( $branding_data ) ) {
            SettingsStore::save( SettingsStore::COL_BRANDING, [] );
            return;
        }

        SettingsStore::save( SettingsStore::COL_BRANDING, self::normalize_branding( $branding_data ) );
    }
}
