<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

if ( ! function_exists( 'elementsell_is_elementor_context' ) || ! elementsell_is_elementor_context() ) {
    add_action( 'init', 'elementsell_register_page_access_meta' );
    add_action( 'add_meta_boxes', 'elementsell_register_page_access_meta_box' );
    add_action( 'save_post_page', 'elementsell_save_page_access_meta_box', 10, 2 );
    add_filter( 'manage_pages_columns', 'elementsell_add_page_access_column' );
    add_action( 'manage_pages_custom_column', 'elementsell_render_page_access_column', 10, 2 );
}

add_action( 'template_redirect', 'elementsell_restrict_page_access_frontend', 9 );
add_action( 'template_redirect', 'elementsell_maybe_gate_login_destination_page', 7 );
add_action( 'wp_body_open', 'elementsell_echo_post_login_logout_link', 5 );
add_action( 'wp_footer', 'elementsell_echo_post_login_logout_link', 5 );
add_action( 'wp_head', 'elementsell_echo_post_login_logout_styles', 99 );
add_filter( 'the_content', 'elementsell_maybe_add_login_destination_placeholder', 999 );

/**
 * @return void
 */
function elementsell_register_page_access_meta() {
    register_post_meta(
        'page',
        '_access_roles',
        [
            'type'              => 'array',
            'single'            => true,
            'default'           => [],
            'show_in_rest'      => [
                'schema' => [
                    'type'  => 'array',
                    'items' => [
                        'type' => 'string',
                    ],
                ],
            ],
            'auth_callback'     => function () {
                return current_user_can( 'edit_pages' );
            },
            'sanitize_callback' => 'elementsell_sanitize_page_access_roles',
        ]
    );
}

/**
 * @param mixed $value
 * @return string[]
 */
function elementsell_sanitize_page_access_roles( $value ) {
    if ( ! is_array( $value ) ) {
        return [];
    }

    $allowed_roles = array_keys( wp_roles()->roles );
    $selected      = [];

    foreach ( $value as $role ) {
        $role = trim( (string) $role );

        if ( $role === '' ) {
            continue;
        }

        // Product role klíče můžou obsahovat mezery — sanitize_key by je smazal.
        if ( in_array( $role, $allowed_roles, true ) ) {
            $selected[] = $role;
            continue;
        }

        $sanitized = sanitize_key( $role );

        if ( $sanitized !== '' && in_array( $sanitized, $allowed_roles, true ) ) {
            $selected[] = $sanitized;
        }
    }

    return array_values( array_unique( $selected ) );
}

/**
 * @param int      $page_id
 * @param string[] $roles
 * @return void
 */
function elementsell_merge_page_access_roles( $page_id, $roles ) {
    $page_id = (int) $page_id;
    $roles   = elementsell_sanitize_page_access_roles( $roles );

    if ( $page_id <= 0 || empty( $roles ) ) {
        return;
    }

    // Děkovací /diky nesmí mít _access_roles — zákazník tam jde hned po platbě ještě bez role.
    if ( function_exists( 'elementsell_is_gated_thank_you_page' ) && elementsell_is_gated_thank_you_page( $page_id ) ) {
        return;
    }

    $merged = elementsell_sanitize_page_access_roles(
        array_merge( elementsell_get_page_access_roles( $page_id ), $roles )
    );

    update_post_meta( $page_id, '_access_roles', $merged );
    update_post_meta( $page_id, '_elementsell_access_roles_auto', '1' );
}

/**
 * @param string $url
 * @return int
 */
function elementsell_resolve_internal_page_id_from_url( $url ) {
    $url = trim( (string) $url );

    if ( $url === '' ) {
        return 0;
    }

    $url_host = wp_parse_url( $url, PHP_URL_HOST );

    if ( $url_host ) {
        $site_host = wp_parse_url( home_url(), PHP_URL_HOST );

        if ( $site_host && strtolower( (string) $url_host ) !== strtolower( (string) $site_host ) ) {
            return 0;
        }
    }

    $page_id = (int) url_to_postid( $url );

    if ( $page_id > 0 && get_post_type( $page_id ) === 'page' ) {
        return $page_id;
    }

    $path = wp_parse_url( $url, PHP_URL_PATH );

    if ( ! is_string( $path ) || $path === '' ) {
        return 0;
    }

    $path = trim( $path, '/' );

    if ( $path === '' ) {
        return 0;
    }

    $page = get_page_by_path( $path );

    return ( $page instanceof WP_Post ) ? (int) $page->ID : 0;
}

/**
 * @param array $elements
 * @return array<int, string[]>
 */
function elementsell_collect_course_image_access_map( $elements ) {
    $map = [];

    if ( ! is_array( $elements ) ) {
        return $map;
    }

    foreach ( $elements as $element ) {
        if (
            ! empty( $element['widgetType'] )
            && $element['widgetType'] === 'elementsell_course_image'
            && ! empty( $element['settings'] )
            && is_array( $element['settings'] )
        ) {
            $settings = $element['settings'];
            $roles    = function_exists( 'elementsell_get_course_roles_from_widget_settings' )
                ? elementsell_get_course_roles_from_widget_settings( $settings )
                : [];
            $roles    = elementsell_sanitize_page_access_roles( $roles );

            if ( ! empty( $roles ) ) {
                $link    = $settings['link'] ?? [];
                $url     = is_array( $link ) ? (string) ( $link['url'] ?? '' ) : '';
                $page_id = elementsell_resolve_internal_page_id_from_url( $url );

                if ( $page_id > 0 ) {
                    if ( ! isset( $map[ $page_id ] ) ) {
                        $map[ $page_id ] = [];
                    }

                    $map[ $page_id ] = array_merge( $map[ $page_id ], $roles );
                }
            }
        }

        if ( ! empty( $element['elements'] ) && is_array( $element['elements'] ) ) {
            $child_map = elementsell_collect_course_image_access_map( $element['elements'] );

            foreach ( $child_map as $page_id => $roles ) {
                if ( ! isset( $map[ $page_id ] ) ) {
                    $map[ $page_id ] = [];
                }

                $map[ $page_id ] = array_merge( $map[ $page_id ], $roles );
            }
        }
    }

    foreach ( $map as $page_id => $roles ) {
        $map[ $page_id ] = elementsell_sanitize_page_access_roles( $roles );
    }

    return $map;
}

/**
 * @param array $elements
 * @return void
 */
function elementsell_sync_course_image_page_access_from_elements( $elements ) {
    $map = elementsell_collect_course_image_access_map( $elements );

    foreach ( $map as $page_id => $roles ) {
        elementsell_merge_page_access_roles( (int) $page_id, $roles );
    }
}

/**
 * @param int $page_id
 * @return string[]
 */
function elementsell_get_page_access_roles( $page_id ) {
    $page_id = (int) $page_id;

    if ( $page_id <= 0 ) {
        return [];
    }

    $roles = get_post_meta( $page_id, '_access_roles', true );

    return elementsell_sanitize_page_access_roles( is_array( $roles ) ? $roles : [] );
}

/**
 * @param int $page_id
 * @return bool
 */
function elementsell_page_has_access_restrictions( $page_id ) {
    return ! empty( elementsell_get_page_access_roles( $page_id ) );
}

/**
 * @param int $page_id
 * @param int $user_id
 * @return bool
 */
function elementsell_user_can_view_restricted_page( $page_id, $user_id = 0 ) {
    $roles = elementsell_get_page_access_roles( $page_id );

    if ( empty( $roles ) ) {
        return true;
    }

    $user_id = $user_id > 0 ? $user_id : get_current_user_id();

    if ( $user_id <= 0 ) {
        return false;
    }

    if ( user_can( $user_id, 'manage_options' ) ) {
        return true;
    }

    if ( user_can( $user_id, 'edit_page', $page_id ) ) {
        return true;
    }

    $user = get_userdata( $user_id );

    if ( ! $user instanceof WP_User ) {
        return false;
    }

    foreach ( $roles as $role ) {
        if ( in_array( $role, (array) $user->roles, true ) ) {
            return true;
        }
    }

    return false;
}

/**
 * @return void
 */
function elementsell_register_page_access_meta_box() {
    add_meta_box(
        'elementsell_page_access_roles',
        'Kdo vidí tuto stránku',
        'elementsell_render_page_access_meta_box',
        'page',
        'side',
        'high'
    );
}

/**
 * @param WP_Post $post
 * @return void
 */
function elementsell_render_page_access_meta_box( $post ) {
    if ( ! $post instanceof WP_Post ) {
        return;
    }

    wp_nonce_field( 'elementsell_save_page_access_roles', 'elementsell_page_access_nonce' );

    $selected_roles = elementsell_get_page_access_roles( (int) $post->ID );
    $roles          = wp_roles()->roles;

    echo '<p class="description" style="margin-top:0;">Nic nezaškrtnuté = stránku vidí všichni. Administrátor a editor stránky ji vždy vidí.</p>';

    if ( get_post_meta( (int) $post->ID, '_elementsell_access_roles_auto', true ) === '1' ) {
        echo '<p class="description">Část rolí mohla být doplněna automaticky z platebního formuláře (stránka po přihlášení) nebo z widgetu <strong>Obrázek kurzu</strong> při uložení v Elementoru.</p>';
    }

    echo '<div class="elementsell-page-access-roles">';

    foreach ( $roles as $role_key => $role_data ) {
        if ( $role_key === 'administrator' ) {
            continue;
        }

        $label = translate_user_role( $role_data['name'] );
        ?>
        <label style="display:block; margin: 0 0 8px;">
            <input
                type="checkbox"
                name="elementsell_page_access_roles[]"
                value="<?php echo esc_attr( $role_key ); ?>"
                <?php checked( in_array( $role_key, $selected_roles, true ) ); ?>
            >
            <?php echo esc_html( $label ); ?>
        </label>
        <?php
   }

    echo '</div>';
}

/**
 * @param int     $post_id
 * @param WP_Post $post
 * @return void
 */
function elementsell_save_page_access_meta_box( $post_id, $post ) {
    if ( ! $post instanceof WP_Post || $post->post_type !== 'page' ) {
        return;
    }

    if (
        empty( $_POST['elementsell_page_access_nonce'] )
        || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['elementsell_page_access_nonce'] ) ), 'elementsell_save_page_access_roles' )
    ) {
        return;
    }

    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }

    if ( ! current_user_can( 'edit_page', $post_id ) ) {
        return;
    }

    $selected_roles = [];

    if ( isset( $_POST['elementsell_page_access_roles'] ) && is_array( $_POST['elementsell_page_access_roles'] ) ) {
        $selected_roles = elementsell_sanitize_page_access_roles( wp_unslash( $_POST['elementsell_page_access_roles'] ) );
    }

    if ( empty( $selected_roles ) ) {
        delete_post_meta( $post_id, '_access_roles' );
        return;
    }

    update_post_meta( $post_id, '_access_roles', $selected_roles );
}

/**
 * @return void
 */
function elementsell_restrict_page_access_frontend() {
    if ( is_admin() || ! is_singular( 'page' ) ) {
        return;
    }

    if ( function_exists( 'elementsell_is_elementor_context' ) && elementsell_is_elementor_context() ) {
        return;
    }

    $page_id = (int) get_queried_object_id();

    if ( $page_id <= 0 || ! elementsell_page_has_access_restrictions( $page_id ) ) {
        return;
    }

    // Děkovací stránka má vlastní gate přes payment_uid — role ji nesmí blokovat.
    if ( function_exists( 'elementsell_is_gated_thank_you_page' ) && elementsell_is_gated_thank_you_page( $page_id ) ) {
        return;
    }

    if ( elementsell_user_can_view_restricted_page( $page_id ) ) {
        return;
    }

    $redirect = wp_login_url( get_permalink( $page_id ) );

    if ( ! is_user_logged_in() ) {
        wp_safe_redirect( $redirect );
        exit;
    }

    wp_die(
        '<p>Tato stránka je dostupná jen pro oprávněné zákazníky.</p><p><a href="' . esc_url( $redirect ) . '">Přihlásit se jiným účtem</a></p>',
        'Přístup odepřen',
        [
            'response' => 403,
        ]
    );
}

/**
 * @return string[]
 */
function elementsell_get_registered_login_destination_urls() {
    static $urls = null;

    if ( $urls !== null ) {
        return $urls;
    }

    global $wpdb;

    $rows = $wpdb->get_col(
        "SELECT DISTINCT field_value
         FROM {$wpdb->prefix}elementsell_order_fields
         WHERE field_name = 'login_url'
         AND field_value != ''"
    );

    $urls = [];

    foreach ( (array) $rows as $row ) {
        if ( is_string( $row ) && $row !== '' ) {
            $urls[] = $row;
        }
    }

    return $urls;
}

/**
 * @param int $page_id
 * @return bool
 */
function elementsell_page_is_login_destination( $page_id = 0 ) {
    $page_id = $page_id > 0 ? $page_id : (int) get_queried_object_id();

    if ( $page_id <= 0 ) {
        return false;
    }

    if ( get_post_meta( $page_id, '_elementsell_login_destination', true ) === '1' ) {
        return true;
    }

    if ( ! function_exists( 'elementsell_resolve_internal_page_id_from_url' ) ) {
        return false;
    }

    foreach ( elementsell_get_registered_login_destination_urls() as $url ) {
        if ( elementsell_resolve_internal_page_id_from_url( $url ) === $page_id ) {
            update_post_meta( $page_id, '_elementsell_login_destination', '1' );

            return true;
        }
    }

    return false;
}

/**
 * Nepřihlášeného na login_url pošle na přihlašovací formulář.
 *
 * @return void
 */
function elementsell_maybe_gate_login_destination_page() {
    if ( is_admin() || ! is_singular( 'page' ) ) {
        return;
    }

    if ( function_exists( 'elementsell_is_elementor_context' ) && elementsell_is_elementor_context() ) {
        return;
    }

    $page_id = (int) get_queried_object_id();

    if ( $page_id <= 0 || ! elementsell_page_is_login_destination( $page_id ) ) {
        return;
    }

    // /diky není stránka po přihlášení — i kdyby někdo omylem nastavil login_url = /diky.
    if ( function_exists( 'elementsell_is_gated_thank_you_page' ) && elementsell_is_gated_thank_you_page( $page_id ) ) {
        return;
    }

    if ( function_exists( 'elementsell_current_user_is_administrator' ) && elementsell_current_user_is_administrator() ) {
        return;
    }

    if ( is_user_logged_in() ) {
        return;
    }

    wp_safe_redirect( wp_login_url( get_permalink( $page_id ) ) );
    exit;
}

/**
 * @param int    $page_id
 * @param string $content
 * @return bool
 */
function elementsell_login_destination_page_has_visible_content( $page_id, $content ) {
    if ( trim( wp_strip_all_tags( (string) $content ) ) !== '' ) {
        return true;
    }

    $elementor_raw = get_post_meta( $page_id, '_elementor_data', true );

    if ( is_string( $elementor_raw ) && $elementor_raw !== '' && $elementor_raw !== '[]' ) {
        return true;
    }

    return false;
}

/**
 * @param string $content
 * @return string
 */
function elementsell_maybe_add_login_destination_placeholder( $content ) {
    if ( is_admin() || ! is_singular( 'page' ) || ! is_main_query() || ! in_the_loop() ) {
        return $content;
    }

    if ( ! is_user_logged_in() ) {
        return $content;
    }

    if ( function_exists( 'elementsell_current_user_is_administrator' ) && elementsell_current_user_is_administrator() ) {
        return $content;
    }

    $page_id = (int) get_queried_object_id();

    if ( $page_id <= 0 || ! elementsell_page_is_login_destination( $page_id ) ) {
        return $content;
    }

    if ( elementsell_login_destination_page_has_visible_content( $page_id, $content ) ) {
        return $content;
    }

    $placeholder = '<div class="elementsell-login-destination-placeholder" style="max-width:640px;margin:40px auto;padding:32px 24px;text-align:center;color:#374151;font-size:16px;line-height:1.6;">'
        . '<p style="margin:0;">Vítejte. Tato stránka zatím nemá vlastní obsah — doplníte ji v Elementoru.</p>'
        . '</div>';

    return $placeholder . $content;
}

/**
 * @param string[] $columns
 * @return string[]
 */
function elementsell_add_page_access_column( $columns ) {
    $columns['elementsell_access_roles'] = 'Viditelnost';

    return $columns;
}

/**
 * @param string $column
 * @param int    $post_id
 * @return void
 */
function elementsell_render_page_access_column( $column, $post_id ) {
    if ( $column !== 'elementsell_access_roles' ) {
        return;
    }

    $roles = elementsell_get_page_access_roles( $post_id );

    if ( empty( $roles ) ) {
        echo '<span style="color:#646970;">Všichni</span>';
        return;
    }

    $labels = [];

    foreach ( $roles as $role_key ) {
        $role_obj = get_role( $role_key );
        $labels[] = $role_obj ? translate_user_role( $role_obj->name ) : $role_key;
    }

    echo esc_html( implode( ', ', $labels ) );
}

/**
 * @param string $destination_url
 * @return bool
 */
function elementsell_is_current_post_login_destination_page( $destination_url ) {
    $destination_url = trim( (string) $destination_url );

    if ( $destination_url === '' ) {
        return false;
    }

    $destination_path = untrailingslashit( (string) wp_parse_url( $destination_url, PHP_URL_PATH ) );
    $request_uri      = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '/';
    $current_path     = untrailingslashit( (string) wp_parse_url( $request_uri, PHP_URL_PATH ) );

    if ( $destination_path !== '' && $destination_path === $current_path ) {
        return true;
    }

    if ( is_singular( 'page' ) ) {
        $page_id = elementsell_resolve_internal_page_id_from_url( $destination_url );

        if ( $page_id > 0 && (int) get_queried_object_id() === $page_id ) {
            return true;
        }
    }

    return false;
}

/**
 * @return bool
 */
function elementsell_should_show_post_login_logout_link() {
    if ( ! is_user_logged_in() || is_admin() ) {
        return false;
    }

    if ( function_exists( 'elementsell_current_user_is_administrator' ) && elementsell_current_user_is_administrator() ) {
        return false;
    }

    if ( function_exists( 'elementsell_is_thank_you_page' ) && elementsell_is_thank_you_page() ) {
        return false;
    }

    if ( isset( $_GET['payment_uid'] ) && sanitize_text_field( wp_unslash( $_GET['payment_uid'] ) ) !== '' ) {
        return false;
    }

    if ( is_singular( 'page' ) && elementsell_page_is_login_destination() ) {
        return true;
    }

    if ( ! function_exists( 'elementsell_get_post_login_url_for_user' ) ) {
        return false;
    }

    $destination = elementsell_get_post_login_url_for_user();

    return elementsell_is_current_post_login_destination_page( $destination );
}

/**
 * @return void
 */
function elementsell_echo_post_login_logout_styles() {
    if ( ! elementsell_should_show_post_login_logout_link() ) {
        return;
    }

    static $rendered = false;

    if ( $rendered ) {
        return;
    }

    $rendered = true;

    echo '<style>
        .elementsell-post-login-logout {
            position: fixed;
            top: 20px;
            right: 28px;
            z-index: 9999;
            font-size: 11px;
            line-height: 1.4;
            color: #6b7280;
            text-decoration: underline;
        }
        .elementsell-post-login-logout:hover {
            color: #111827;
        }
    </style>';
}

/**
 * @return string
 */
function elementsell_render_post_login_logout_link() {
    static $rendered = false;

    if ( $rendered || ! elementsell_should_show_post_login_logout_link() ) {
        return '';
    }

    $rendered = true;

    $redirect = remove_query_arg( [ '_wpnonce', 'reauth' ] );

    if ( ! $redirect ) {
        $redirect = home_url( '/' );
    }

    $logout_url = wp_logout_url( $redirect );

    return '<a class="elementsell-post-login-logout" href="' . esc_url( $logout_url ) . '">Odhlásit</a>';
}

/**
 * @return void
 */
function elementsell_echo_post_login_logout_link() {
    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- obsah je escapován v elementsell_render_post_login_logout_link().
    echo elementsell_render_post_login_logout_link();
}
