<?php
namespace BLR\Backline\Modules\Users;

use BLR\Backline\Core\ListPage;
use BLR\Backline\Core\Request;
use BLR\Backline\Core\SettingsPage;
use BLR\Backline\Core\Views;

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

final class Pages {
    private const PER_PAGE = 25;

    public static function render_list(array $ctx): string {
        $ctx['users_list'] = self::list_data($ctx);
        return Views::render('pages/users', $ctx);
    }

    public static function render_view(array $ctx): string {
        $ctx['user_view'] = self::view_data($ctx);
        return Views::render('pages/view-user', $ctx);
    }

    public static function list_data(array $ctx): array {
        $base = ListPage::base_url($ctx);
        $page_num = Views::current_page_from_query_arg('pg');
        $view_mode = ListPage::view_mode();
        $search_term = Request::query_text('s');

        $query_args = [
            'include'        => self::backline_user_ids() ?: [0],
            'number'         => self::PER_PAGE,
            'offset'         => ($page_num - 1) * self::PER_PAGE,
            'orderby'        => 'display_name',
            'order'          => 'ASC',
            'count_total'    => true,
            'fields'         => 'all_with_meta',
        ];

        if ($search_term !== '') {
            $query_args['search'] = '*' . $search_term . '*';
            $query_args['search_columns'] = ['user_login', 'user_nicename', 'user_email', 'display_name'];
        }

        $query = new \WP_User_Query($query_args);
        $users = array_values(array_filter((array) $query->get_results(), static function ($user): bool {
            return $user instanceof \WP_User;
        }));
        $total = (int) $query->get_total();

        $persist_args = [];
        if ($search_term !== '') {
            $persist_args['s'] = $search_term;
        }

        $urls = ListPage::view_urls($base, 'users', $persist_args, $view_mode);
        $summary = self::pagination_summary($total, self::PER_PAGE, $page_num);
        $pagination_base_url = (string) ($urls['pagination_base_url'] ?? ($base . 'users/'));

        return array_merge($urls, [
            'base'                => $base,
            'page_num'            => $page_num,
            'search_term'         => $search_term,
            'view_mode'           => $view_mode,
            'users'               => $query,
            'users_summary'       => $summary,
            'user_items'          => array_map(static function (\WP_User $user) use ($base): array {
                return self::user_item($user, $base);
            }, $users),
            'pagination_html'     => self::render_pagination($summary['total_pages'], $page_num, $pagination_base_url),
        ]);
    }

    public static function view_data(array $ctx): array {
        $base = ListPage::base_url($ctx);
        $id = absint((int) ($ctx['id'] ?? 0));

        if ($id <= 0 || !self::is_backline_user($id)) {
            return [
                'base'      => $base,
                'not_found' => true,
            ];
        }

        $user = get_userdata($id);
        if (!$user instanceof \WP_User || !$user->exists()) {
            return [
                'base'      => $base,
                'not_found' => true,
            ];
        }

        return [
            'base'       => $base,
            'not_found'  => false,
            'user'       => $user,
            'user_item'  => self::user_item($user, $base, true),
        ];
    }

    private static function backline_user_ids(): array {
        $ids = [];

        $admin_ids = get_users([
            'role__in' => ['administrator'],
            'fields'   => 'ID',
            'number'   => 500,
        ]);

        foreach ((array) $admin_ids as $admin_id) {
            $admin_id = absint($admin_id);
            if ($admin_id > 0) {
                $ids[] = $admin_id;
            }
        }

        if (is_multisite()) {
            foreach (get_super_admins() as $login) {
                $super_admin = get_user_by('login', (string) $login);
                if ($super_admin instanceof \WP_User) {
                    $ids[] = (int) $super_admin->ID;
                }
            }
        }

        foreach (SettingsPage::get_allowed_user_ids() as $allowed_id) {
            $allowed_id = absint($allowed_id);
            if ($allowed_id > 0) {
                $ids[] = $allowed_id;
            }
        }

        $ids = array_values(array_unique(array_filter($ids)));
        sort($ids, SORT_NUMERIC);

        return $ids;
    }

    private static function is_backline_user(int $user_id): bool {
        $user_id = absint($user_id);
        if ($user_id <= 0) {
            return false;
        }

        $user = get_userdata($user_id);
        if (!$user instanceof \WP_User || !$user->exists()) {
            return false;
        }

        if (user_can($user_id, 'manage_options') || in_array('administrator', (array) $user->roles, true)) {
            return true;
        }

        return in_array($user_id, SettingsPage::get_allowed_user_ids(), true);
    }

    private static function user_item(\WP_User $user, string $base, bool $include_bio = false): array {
        $user_id = (int) $user->ID;
        $first_name = (string) get_user_meta($user_id, 'first_name', true);
        $last_name = (string) get_user_meta($user_id, 'last_name', true);
        $description = $include_bio ? (string) get_user_meta($user_id, 'description', true) : '';
        $website = (string) $user->user_url;
        $registered = (string) $user->user_registered;
        $last_login_timestamp = Activity::last_login_timestamp($user_id);
        $is_admin = user_can($user_id, 'manage_options') || in_array('administrator', (array) $user->roles, true);
        $module_labels = self::user_module_labels($user_id, $is_admin);
        $extra_labels = self::user_extra_cap_labels($user_id, $is_admin);

        return [
            'id'              => $user_id,
            'display_name'    => (string) ($user->display_name ?: $user->user_login),
            'user_login'      => (string) $user->user_login,
            'user_email'      => (string) $user->user_email,
            'first_name'      => $first_name,
            'last_name'       => $last_name,
            'website'         => $website,
            'description'     => $description,
            'roles'           => self::role_labels((array) $user->roles),
            'is_admin'        => $is_admin,
            'access_label'    => $is_admin ? __('Administrator', 'blr-backline') : __('Backline user', 'blr-backline'),
            'module_labels'   => $module_labels,
            'extra_labels'    => $extra_labels,
            'avatar_url'      => self::avatar_url($user_id, 96),
            'registered'       => $registered,
            'registered_label' => self::date_label($registered),
            'last_login'       => $last_login_timestamp,
            'last_login_label' => Activity::last_login_label($user_id),
            'profile_url'      => $base . 'users/view/' . $user_id . '/',
        ];
    }

    private static function avatar_url(int $user_id, int $size = 96): string {
        $avatar_id = absint(get_user_meta($user_id, 'blr_ba_avatar_id', true));
        if ($avatar_id > 0) {
            $avatar_url = (string) wp_get_attachment_image_url($avatar_id, 'thumbnail');
            if ($avatar_url !== '') {
                return $avatar_url;
            }
        }

        return BLR_BA_URL . 'assets/blr-ba/img/placeholder-image.png';
    }

    private static function user_module_labels(int $user_id, bool $is_admin): array {
        $labels = SettingsPage::module_labels();
        $modules = $is_admin ? SettingsPage::enabled_modules() : SettingsPage::user_enabled_modules($user_id);
        $out = [];

        foreach ($modules as $module) {
            $module = sanitize_key($module);
            if (isset($labels[$module])) {
                $out[] = (string) $labels[$module];
            }
        }

        return array_values(array_unique($out));
    }

    private static function user_extra_cap_labels(int $user_id, bool $is_admin): array {
        if ($is_admin) {
            return [__('Can manage settings', 'blr-backline')];
        }

        $extra_caps = SettingsPage::user_extra_caps($user_id);
        $labels = [];

        if (in_array('blr_ba_edit_settings', $extra_caps, true)) {
            $labels[] = __('Can edit settings', 'blr-backline');
        } elseif (in_array('blr_ba_view_settings', $extra_caps, true)) {
            $labels[] = __('Can view settings', 'blr-backline');
        }

        return $labels;
    }

    private static function role_labels(array $roles): array {
        $role_objects = wp_roles();
        $labels = [];

        foreach ($roles as $role) {
            $role = sanitize_key((string) $role);
            if ($role === '') {
                continue;
            }

            $labels[] = isset($role_objects->role_names[$role])
                ? translate_user_role((string) $role_objects->role_names[$role])
                : $role;
        }

        return array_values(array_unique($labels));
    }

    private static function date_label(string $mysql_date): string {
        if ($mysql_date === '') {
            return '';
        }

        $timestamp = strtotime($mysql_date);
        if (!$timestamp) {
            return '';
        }

        return date_i18n(get_option('date_format'), $timestamp);
    }

    private static function pagination_summary(int $total, int $per_page, int $current_page): array {
        if ($total <= 0 || $per_page <= 0) {
            return [
                'total'        => 0,
                'from'         => 0,
                'to'           => 0,
                'current_page' => $current_page,
                'per_page'     => $per_page,
                'total_pages'  => 0,
            ];
        }

        return [
            'total'        => $total,
            'from'         => (($current_page - 1) * $per_page) + 1,
            'to'           => min($current_page * $per_page, $total),
            'current_page' => $current_page,
            'per_page'     => $per_page,
            'total_pages'  => (int) ceil($total / $per_page),
        ];
    }

    private static function render_pagination(int $total_pages, int $current_page, string $base_url): string {
        if ($total_pages <= 1) {
            return '';
        }

        $base = add_query_arg(['pg' => '%#%'], $base_url);
        $links = paginate_links([
            'base'      => $base,
            'format'    => '',
            'current'   => $current_page,
            'total'     => $total_pages,
            'type'      => 'array',
            'prev_text' => '&laquo;',
            'next_text' => '&raquo;',
        ]);

        if (empty($links) || !is_array($links)) {
            return '';
        }

        $html = '<nav class="mt-3" aria-label="' . esc_attr__('Pagination', 'blr-backline') . '"><ul class="pagination mb-0">';
        foreach ($links as $link) {
            $html .= '<li class="page-item">' . str_replace('page-numbers', 'page-link', $link) . '</li>';
        }
        $html .= '</ul></nav>';

        return $html;
    }
}
