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

/**
 * Handles Custom Post Type registration.
 */
class NNAXFUF_CPT {

    public function __construct() {
        add_action( 'init', array( $this, 'register_cpt' ) );
        add_action( 'init', array( $this, 'add_rewrite_endpoint' ) );
        add_filter( 'query_vars', array( $this, 'register_query_var' ) );

        add_filter( 'manage_' . NNAXFUF_Plugin::CPT . '_posts_columns', array( $this, 'filter_file_columns' ) );
        add_action( 'manage_' . NNAXFUF_Plugin::CPT . '_posts_custom_column', array( $this, 'render_file_column' ), 10, 2 );
        add_filter( 'manage_edit-' . NNAXFUF_Plugin::CPT . '_sortable_columns', array( $this, 'file_sortable_columns' ) );

        add_filter( 'manage_' . NNAXFUF_Plugin::CPT_FOLDER . '_posts_columns', array( $this, 'filter_folder_columns' ) );
        add_action( 'manage_' . NNAXFUF_Plugin::CPT_FOLDER . '_posts_custom_column', array( $this, 'render_folder_column' ), 10, 2 );
        add_filter( 'manage_edit-' . NNAXFUF_Plugin::CPT_FOLDER . '_sortable_columns', array( $this, 'folder_sortable_columns' ) );

        add_action( 'restrict_manage_posts', array( $this, 'render_admin_filters' ), 10, 2 );
        add_action( 'pre_get_posts', array( $this, 'apply_admin_filters' ) );
    }

    public function register_cpt() {
        // FILE-CPT
        $labels = array(
            'name'               => __( 'User Files', 'nnax-frontend-user-files' ),
            'singular_name'      => __( 'User File', 'nnax-frontend-user-files' ),
            'add_new'            => __( 'Add File', 'nnax-frontend-user-files' ),
            'add_new_item'       => __( 'Add New User File', 'nnax-frontend-user-files' ),
            'edit_item'          => __( 'Edit User File', 'nnax-frontend-user-files' ),
            'new_item'           => __( 'New User File', 'nnax-frontend-user-files' ),
            'view_item'          => __( 'View User File', 'nnax-frontend-user-files' ),
            'search_items'       => __( 'Search User Files', 'nnax-frontend-user-files' ),
            'not_found'          => __( 'No User Files found', 'nnax-frontend-user-files' ),
            'not_found_in_trash' => __( 'No User Files in trash', 'nnax-frontend-user-files' ),
            'menu_name'          => __( 'Files', 'nnax-frontend-user-files' ),
        );

        $args = array(
            'labels'             => $labels,
            'public'             => false,
            'show_ui'            => true,
            'show_in_menu'       => 'nnax-user-files',
            'supports'           => array( 'title' ),
            'capability_type'    => 'post',
            'map_meta_cap'       => true,
        );

        register_post_type( NNAXFUF_Plugin::CPT, $args );

        // FOLDER-CPT
        $folder_labels = array(
            'name'          => __( 'User Folders', 'nnax-frontend-user-files' ),
            'singular_name' => __( 'User Folder', 'nnax-frontend-user-files' ),
            'add_new_item'  => __( 'Add New Folder', 'nnax-frontend-user-files' ),
            'edit_item'     => __( 'Edit Folder', 'nnax-frontend-user-files' ),
            'menu_name'     => __( 'User Folders', 'nnax-frontend-user-files' ),
        );

        $folder_args = array(
            'labels'        => $folder_labels,
            'public'        => false,
            'show_ui'       => true,
            'show_in_menu'  => 'nnax-user-files',
            'hierarchical'  => true,
            'supports'      => array( 'title' ),
            'capability_type' => 'post',
            'map_meta_cap'  => true,
        );

        register_post_type( NNAXFUF_Plugin::CPT_FOLDER, $folder_args );
    }

    public function add_rewrite_endpoint() {
        add_rewrite_rule(
            '^' . NNAXFUF_Plugin::DOWNLOAD_ENDPOINT . '/([0-9]+)(?:/[^/]+)?(?:/(inline))?/?$',
            'index.php?' . NNAXFUF_Plugin::DOWNLOAD_VAR . '=$matches[1]&nnaxfuf_mode=$matches[2]',
            'top'
        );

        add_rewrite_rule(
            '^' . NNAXFUF_Plugin::DOWNLOAD_ENDPOINT . '/zip/([^/]+)(?:/([^/]+))?/?$',
            'index.php?nnaxfuf_zip_items=$matches[1]&nnaxfuf_zip_name=$matches[2]',
            'top'
        );

        $manager_pattern = 'nnaxfuf(?:/view/(trash))?(?:/filter/(all|owned|shared|shared_by_me))?(?:/type/(all|pdf|image|doc|sheet|archive))?(?:/folder/([0-9]+))?(?:/paged/([0-9]+))?(?:/search/([^/]+))?/?$';

        $front_page_id = (int) get_option( 'page_on_front' );
        if ( $front_page_id > 0 ) {
            add_rewrite_rule(
                '^' . $manager_pattern,
                'index.php?page_id=' . $front_page_id . '&' . NNAXFUF_Plugin::VIEW_VAR . '=$matches[1]&' . NNAXFUF_Plugin::FILTER_VAR . '=$matches[2]&' . NNAXFUF_Plugin::TYPE_VAR . '=$matches[3]&' . NNAXFUF_Plugin::FOLDER_VAR . '=$matches[4]&' . NNAXFUF_Plugin::PAGED_VAR . '=$matches[5]&' . NNAXFUF_Plugin::SEARCH_VAR . '=$matches[6]',
                'top'
            );
        }

        add_rewrite_rule(
            '^(.+?)/' . $manager_pattern,
            'index.php?pagename=$matches[1]&' . NNAXFUF_Plugin::VIEW_VAR . '=$matches[2]&' . NNAXFUF_Plugin::FILTER_VAR . '=$matches[3]&' . NNAXFUF_Plugin::TYPE_VAR . '=$matches[4]&' . NNAXFUF_Plugin::FOLDER_VAR . '=$matches[5]&' . NNAXFUF_Plugin::PAGED_VAR . '=$matches[6]&' . NNAXFUF_Plugin::SEARCH_VAR . '=$matches[7]',
            'top'
        );
    }

    /**
     * Register custom query vars used by the plugin.
     *
     * @param array $vars Existing query vars.
     * @return array
     */
    public function register_query_var( $vars ) {
        $vars[] = NNAXFUF_Plugin::DOWNLOAD_VAR;
        $vars[] = NNAXFUF_Plugin::FOLDER_VAR;
        $vars[] = NNAXFUF_Plugin::VIEW_VAR;
        $vars[] = NNAXFUF_Plugin::FILTER_VAR;
        $vars[] = NNAXFUF_Plugin::PAGED_VAR;
        $vars[] = NNAXFUF_Plugin::SEARCH_VAR;
        $vars[] = NNAXFUF_Plugin::TYPE_VAR;
        $vars[] = NNAXFUF_Plugin::SORT_VAR;
        $vars[] = NNAXFUF_Plugin::ORDER_VAR;
        $vars[] = NNAXFUF_Plugin::SHOW_VAR;
        $vars[] = 'nnaxfuf_mode';
        $vars[] = 'nnaxfuf_zip_items';
        $vars[] = 'nnaxfuf_zip_name';
        return $vars;
    }

    /**
     * Filter columns for file post type list table.
     *
     * @param array $columns
     * @return array
     */
    public function filter_file_columns( $columns ) {
        $new_columns = array();

        if ( isset( $columns['cb'] ) ) {
            $new_columns['cb'] = $columns['cb'];
        }

        $new_columns['title']      = __( 'Title', 'nnax-frontend-user-files' );
        $new_columns['nnaxfuf_owner']  = __( 'Owner', 'nnax-frontend-user-files' );
        $new_columns['nnaxfuf_folder'] = __( 'Folder / Location', 'nnax-frontend-user-files' );
        $new_columns['nnaxfuf_shared'] = __( 'Shared with', 'nnax-frontend-user-files' );
        $new_columns['date']       = __( 'Date', 'nnax-frontend-user-files' );

        return $new_columns;
    }

    /**
     * Render custom file list columns.
     *
     * @param string $column Column key.
     * @param int $post_id Post ID.
     * @return void
     */
    public function render_file_column( $column, $post_id ) {
        if ( 'nnaxfuf_owner' === $column ) {
            echo esc_html( $this->get_owner_display_name( $post_id ) );
            return;
        }

        if ( 'nnaxfuf_folder' === $column ) {
            $folder_id = (int) wp_get_post_parent_id( $post_id );
            if ( $folder_id <= 0 ) {
                echo esc_html__( 'Root', 'nnax-frontend-user-files' );
                return;
            }

            $folder_title = NNAXFUF_Helpers::get_raw_item_title( $folder_id );
            $path_label   = $this->get_folder_path_label( $folder_id );

            $edit_link = get_edit_post_link( $folder_id );
            if ( ! empty( $edit_link ) ) {
                printf(
                    '<a href="%1$s">%2$s</a><br><small>%3$s</small>',
                    esc_url( $edit_link ),
                    esc_html( $folder_title !== '' ? $folder_title : (string) $folder_id ),
                    esc_html( $path_label )
                );
                return;
            }

            echo esc_html( $path_label );
            return;
        }

        if ( 'nnaxfuf_shared' === $column ) {
            echo wp_kses_post( $this->get_shared_summary_html( $post_id ) );
            return;
        }

    }

    /**
     * Filter columns for folder post type list table.
     *
     * @param array $columns
     * @return array
     */
    public function filter_folder_columns( $columns ) {
        $new_columns = array();

        if ( isset( $columns['cb'] ) ) {
            $new_columns['cb'] = $columns['cb'];
        }

        $new_columns['title']     = __( 'Title', 'nnax-frontend-user-files' );
        $new_columns['nnaxfuf_owner'] = __( 'Owner', 'nnax-frontend-user-files' );
        $new_columns['nnaxfuf_shared'] = __( 'Shared with', 'nnax-frontend-user-files' );
        $new_columns['date']      = __( 'Date', 'nnax-frontend-user-files' );

        return $new_columns;
    }

    /**
     * Render custom folder list columns.
     *
     * @param string $column Column key.
     * @param int $post_id Post ID.
     * @return void
     */
    public function render_folder_column( $column, $post_id ) {
        if ( 'nnaxfuf_owner' === $column ) {
            echo esc_html( $this->get_owner_display_name( $post_id ) );
            return;
        }

        if ( 'nnaxfuf_shared' === $column ) {
            echo wp_kses_post( $this->get_shared_summary_html( $post_id ) );
            return;
        }

    }

    /**
     * Register sortable columns for file list.
     *
     * @param array $columns
     * @return array
     */
    public function file_sortable_columns( $columns ) {
        $columns['nnaxfuf_owner']  = 'nnaxfuf_owner';
        $columns['nnaxfuf_folder'] = 'nnaxfuf_folder';
        return $columns;
    }

    /**
     * Register sortable columns for folder list.
     *
     * @param array $columns
     * @return array
     */
    public function folder_sortable_columns( $columns ) {
        $columns['nnaxfuf_owner'] = 'nnaxfuf_owner';
        return $columns;
    }

    /**
     * Render admin list filters for owner and folder.
     *
     * @param string $post_type
     * @param string $which
     * @return void
     */
    public function render_admin_filters( $post_type, $which ) {
        // Read-only list table filter inputs in wp-admin.
        // phpcs:disable WordPress.Security.NonceVerification.Recommended
        if ( 'top' !== $which ) {
            return;
        }

        if ( $post_type !== NNAXFUF_Plugin::CPT && $post_type !== NNAXFUF_Plugin::CPT_FOLDER ) {
            return;
        }

        $selected_owner = isset( $_GET['nnaxfuf_owner_filter'] ) ? (int) $_GET['nnaxfuf_owner_filter'] : 0;
        $owners         = $this->get_owner_choices_for_post_type( $post_type );

        echo '<label class="screen-reader-text" for="nnaxfuf_owner_filter">' . esc_html__( 'Filter by owner', 'nnax-frontend-user-files' ) . '</label>';
        echo '<select name="nnaxfuf_owner_filter" id="nnaxfuf_owner_filter">';
        echo '<option value="0">' . esc_html__( 'All owners', 'nnax-frontend-user-files' ) . '</option>';
        foreach ( $owners as $owner ) {
            printf(
                '<option value="%1$d"%2$s>%3$s</option>',
                (int) $owner['id'],
                selected( $selected_owner, (int) $owner['id'], false ),
                esc_html( $owner['label'] )
            );
        }
        echo '</select>';

        if ( $post_type !== NNAXFUF_Plugin::CPT ) {
            // phpcs:enable WordPress.Security.NonceVerification.Recommended
            return;
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin list filter value.
        $selected_folder = isset( $_GET['nnaxfuf_folder_filter'] ) ? (int) $_GET['nnaxfuf_folder_filter'] : 0;
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Core function outputs escaped markup for select options.
        wp_dropdown_pages(
            array(
                // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Passed to core dropdown API, not direct output.
                'post_type'        => NNAXFUF_Plugin::CPT_FOLDER,
                'name'             => 'nnaxfuf_folder_filter',
                'id'               => 'nnaxfuf_folder_filter',
                // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Value is cast to int and rendered by core.
                'selected'         => $selected_folder,
                'show_option_all'  => esc_html__( 'All folders', 'nnax-frontend-user-files' ),
                'option_none_value'=> '0',
                'sort_column'      => 'menu_order,post_title',
                'hierarchical'     => 1,
                'depth'            => 3,
            )
        );
        // phpcs:enable WordPress.Security.NonceVerification.Recommended
    }

    /**
     * Apply admin list filters to WP_Query.
     *
     * @param WP_Query $query
     * @return void
     */
    public function apply_admin_filters( $query ) {
        // Read-only list table filter inputs in wp-admin.
        // phpcs:disable WordPress.Security.NonceVerification.Recommended
        if ( ! is_admin() || ! $query->is_main_query() ) {
            return;
        }

        global $pagenow;
        if ( 'edit.php' !== $pagenow ) {
            return;
        }

        $post_type = $query->get( 'post_type' );
        if ( $post_type !== NNAXFUF_Plugin::CPT && $post_type !== NNAXFUF_Plugin::CPT_FOLDER ) {
            return;
        }

        $owner_id = isset( $_GET['nnaxfuf_owner_filter'] ) ? (int) $_GET['nnaxfuf_owner_filter'] : 0;
        if ( $owner_id > 0 ) {
            $meta_query = $query->get( 'meta_query' );
            if ( ! is_array( $meta_query ) ) {
                $meta_query = array();
            }
            $meta_query[] = array(
                'key'     => NNAXFUF_Plugin::META_OWNER,
                'value'   => $owner_id,
                'compare' => '=',
                'type'    => 'NUMERIC',
            );
            $query->set( 'meta_query', $meta_query );
        }

        if ( $post_type === NNAXFUF_Plugin::CPT ) {
            $folder_id = isset( $_GET['nnaxfuf_folder_filter'] ) ? (int) $_GET['nnaxfuf_folder_filter'] : 0;
            if ( $folder_id > 0 ) {
                $query->set( 'post_parent', $folder_id );
            }

            // Default sorting for file list: first by folder, then by title.
            if ( empty( $_GET['orderby'] ) ) {
                $query->set(
                    'orderby',
                    array(
                        'parent' => 'ASC',
                        'title'  => 'ASC',
                    )
                );
            }
        }

        $orderby = (string) $query->get( 'orderby' );
        if ( 'nnaxfuf_owner' === $orderby ) {
            $query->set( 'meta_key', NNAXFUF_Plugin::META_OWNER );
            $query->set( 'orderby', 'meta_value_num' );
        } elseif ( 'nnaxfuf_folder' === $orderby && $post_type === NNAXFUF_Plugin::CPT ) {
            $query->set( 'orderby', 'parent' );
        }
        // phpcs:enable WordPress.Security.NonceVerification.Recommended
    }

    /**
     * Get display name for owner of a post.
     *
     * @param int $post_id
     * @return string
     */
    private function get_owner_display_name( $post_id ) {
        $owner_id = (int) get_post_meta( $post_id, NNAXFUF_Plugin::META_OWNER, true );
        if ( $owner_id <= 0 ) {
            $owner_id = (int) get_post_field( 'post_author', $post_id );
        }

        if ( $owner_id <= 0 ) {
            return __( 'Unknown', 'nnax-frontend-user-files' );
        }

        $owner = get_user_by( 'id', $owner_id );
        if ( ! $owner ) {
            return sprintf( '#%d', $owner_id );
        }

        return $owner->display_name !== '' ? $owner->display_name : $owner->user_login;
    }

    /**
     * Build human-readable path label for a folder.
     *
     * @param int $folder_id
     * @return string
     */
    private function get_folder_path_label( $folder_id ) {
        $folder_id = (int) $folder_id;
        if ( $folder_id <= 0 ) {
            return __( 'Root', 'nnax-frontend-user-files' );
        }

        $chain      = array( $folder_id );
        $ancestors  = get_post_ancestors( $folder_id );
        if ( is_array( $ancestors ) && ! empty( $ancestors ) ) {
            $chain = array_reverse( array_map( 'intval', $ancestors ) );
            $chain[] = $folder_id;
        }

        $parts = array();
        foreach ( $chain as $id ) {
            $title = NNAXFUF_Helpers::get_raw_item_title( $id );
            if ( $title !== '' ) {
                $parts[] = $title;
            }
        }

        if ( empty( $parts ) ) {
            return sprintf( '#%d', $folder_id );
        }

        return implode( ' / ', $parts );
    }

    /**
     * Return HTML summary of shares for an item.
     *
     * @param int $post_id
     * @return string
     */
    private function get_shared_summary_html( $post_id ) {
        $rules = NNAXFUF_Helpers::get_item_share_rules( $post_id );
        if ( empty( $rules ) || ! is_array( $rules ) ) {
            return '&mdash;';
        }

        $user_ids = array_values(
            array_filter(
                array_map( 'intval', array_keys( $rules ) ),
                function ( $id ) {
                    return $id > 0;
                }
            )
        );

        if ( empty( $user_ids ) ) {
            return '&mdash;';
        }

        $count = count( $user_ids );
        if ( $count <= 0 ) {
            return '&mdash;';
        }

        /* translators: %d: number of people this item is shared with. */
        $count_text = sprintf(
            /* translators: %d: number of people this item is shared with. */
            _n( '%d person', '%d people', $count, 'nnax-frontend-user-files' ),
            $count
        );

        return sprintf(
            '<span>%1$s</span>',
            esc_html( $count_text )
        );
    }

    /**
     * Get list of owner choices for a given post type.
     *
     * @param string $post_type
     * @return array
     */
    private function get_owner_choices_for_post_type( $post_type ) {
        global $wpdb;

        $post_type = (string) $post_type;
        $meta_key  = NNAXFUF_Plugin::META_OWNER;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Admin filter options query.
        $owner_ids = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT DISTINCT pm.meta_value
                 FROM {$wpdb->postmeta} pm
                 INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
                 WHERE pm.meta_key = %s
                   AND p.post_type = %s
                   AND p.post_status NOT IN ('auto-draft')
                 ORDER BY pm.meta_value ASC",
                $meta_key,
                $post_type
            )
        );

        if ( empty( $owner_ids ) ) {
            return array();
        }

        $owner_ids = array_values(
            array_filter(
                array_map( 'intval', $owner_ids ),
                function ( $id ) {
                    return $id > 0;
                }
            )
        );

        if ( empty( $owner_ids ) ) {
            return array();
        }

        $users = get_users(
            array(
                'include' => $owner_ids,
                'orderby' => 'display_name',
                'order'   => 'ASC',
            )
        );

        $choices = array();
        foreach ( $users as $user ) {
            $choices[] = array(
                'id'    => (int) $user->ID,
                'label' => $user->display_name !== '' ? $user->display_name : $user->user_login,
            );
        }

        return $choices;
    }
}
