<?php
namespace BLR\Backline\Core;

use BLR\Backline\Modules\Contacts\Pages as ContactsPages;
use BLR\Backline\Modules\Dashboard\Pages as DashboardPages;
use BLR\Backline\Modules\Discography\Pages as DiscographyPages;
use BLR\Backline\Modules\Events\Pages as EventsPages;
use BLR\Backline\Modules\Outreach\Module as OutreachModule;
use BLR\Backline\Modules\Outreach\Pages as OutreachPages;
use BLR\Backline\Modules\Tasks\Pages as TasksPages;
use BLR\Backline\Modules\Users\Pages as UsersPages;

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

final class Router {
    private static $routes = [];

    public static function boot(): void {
        add_action('init', [self::class, 'register_core_routes'], 5);
        add_action('init', [self::class, 'register_addon_routes'], 6);
        add_action('init', [self::class, 'add_rewrite_rules']);
        add_action('init', [self::class, 'maybe_flush_rewrite_rules'], 20);
        add_filter('query_vars', [self::class, 'query_vars']);
        add_filter('show_admin_bar', [self::class, 'maybe_hide_admin_bar']);
        add_action('template_redirect', [self::class, 'handle_request']);

        // Ensure related files/data are cleaned up whenever WordPress permanently
        // deletes a post, not just when deletion happens through this router.
        add_action('before_delete_post', [self::class, 'handle_before_delete_post']);
    }

    public static function register_addon_routes(): void {
        /**
         * Let add-on plugins register additional Backline routes.
         */
        do_action('blr_backline_register_routes');
    }

    public static function register(string $slug, callable $handler, array $opts = []): void {
        $slug = trim($slug, '/');
        self::$routes[$slug === '' ? 'dashboard' : $slug] = [
            'handler' => $handler,
            'title'   => $opts['title'] ?? '',
        ];
    }

    private static function route_module_map(): array {
        return [
            'dashboard' => '',
            'profile' => '',
            'users' => '',
            'users/view' => '',
            'login' => '',
            'not-allowed' => '',
            'settings' => '',
            'notifications' => 'notifications',
            'albums' => 'discography',
            'albums/view' => 'discography',
            'albums/new' => 'discography',
            'albums/edit' => 'discography',
            'albums/delete' => 'discography',
            'discography' => 'discography',
            'discography/view' => 'discography',
            'discography/new' => 'discography',
            'discography/edit' => 'discography',
            'discography/delete' => 'discography',
            'tracks' => 'discography',
            'tracks/view' => 'discography',
            'tracks/new' => 'discography',
            'tracks/edit' => 'discography',
            'tracks/delete' => 'discography',
            'contacts' => 'contacts',
            'contacts/view' => 'contacts',
            'contacts/new' => 'contacts',
            'contacts/edit' => 'contacts',
            'contacts/delete' => 'contacts',
            'outreach' => 'outreach',
            'outreach/view' => 'outreach',
            'outreach/new' => 'outreach',
            'outreach/edit' => 'outreach',
            'outreach/delete' => 'outreach',
            'events' => 'events',
            'events/view' => 'events',
            'events/new' => 'events',
            'events/edit' => 'events',
            'events/delete' => 'events',
            'calendar' => 'events',
            'tasks' => 'tasks',
            'tasks/view' => 'tasks',
            'tasks/new' => 'tasks',
            'tasks/edit' => 'tasks',
            'tasks/delete' => 'tasks',
            'finances' => 'finances',
            'finances/view' => 'finances',
            'finances/new' => 'finances',
            'finances/edit' => 'finances',
            'finances/delete' => 'finances',
        ];
    }

    private static function route_module(string $page): string {
        $map = self::route_module_map();
        return isset($map[$page]) ? (string) $map[$page] : '';
    }

    private static function current_user_can_route(string $page): bool {
        if (current_user_can('manage_options')) {
            return true;
        }

        if ($page === 'settings') {
            return SettingsPage::can_view_frontend_settings();
        }

        if (in_array($page, ['dashboard', 'profile', 'users', 'users/view'], true)) {
            return current_user_can('blr_ba_view_dashboard');
        }

        $module = self::route_module($page);
        if ($module === '') {
            return true;
        }

        return Access::module_is_accessible($module);
    }

    private static function route_is_enabled(string $page): bool {
        $module = self::route_module($page);
        if ($module === '') {
            return true;
        }

        return SettingsPage::is_module_enabled($module);
    }

    public static function register_core_routes(): void {
        // Auth / access
        self::register('login', function($ctx){
            return Views::render('pages/login', $ctx);
        }, ['title' => __('Log in', 'blr-backline')]);

        self::register('not-allowed', function($ctx){
            return Views::render('pages/not-allowed', $ctx);
        }, ['title' => __('Not allowed', 'blr-backline')]);

        self::register('dashboard', [DashboardPages::class, 'render'], ['title' => __('Dashboard', 'blr-backline')]);

        self::register('profile', function($ctx){
            return Views::render('pages/profile', $ctx);
        }, ['title' => __('Profile', 'blr-backline')]);
        self::register('users', [UsersPages::class, 'render_list'], ['title' => __('Users', 'blr-backline')]);
        self::register('users/view', [UsersPages::class, 'render_view'], ['title' => __('User', 'blr-backline')]);

        self::register('notifications', [self::class, 'handle_notifications_list'], ['title' => __('Notifications', 'blr-backline')]);
        self::register('settings', [SettingsPage::class, 'render_frontend_page'], ['title' => __('Settings', 'blr-backline')]);

        // Albums (with discography aliases for backwards compatibility)
        self::register('albums', [DiscographyPages::class, 'render_releases_list'], ['title' => __('Albums', 'blr-backline')]);
        self::register('albums/view', [DiscographyPages::class, 'render_release_view'], ['title' => __('Album', 'blr-backline')]);
        self::register('albums/new', [DiscographyPages::class, 'render_release_form'], ['title' => __('New Album', 'blr-backline')]);
        self::register('albums/edit', [DiscographyPages::class, 'render_release_form'], ['title' => __('Edit Album', 'blr-backline')]);
        self::register('albums/delete', [DiscographyPages::class, 'handle_release_delete'], ['title' => __('Delete Album', 'blr-backline')]);

        self::register('discography', [DiscographyPages::class, 'render_releases_list'], ['title' => __('Albums', 'blr-backline')]);
        self::register('discography/view', [DiscographyPages::class, 'render_release_view'], ['title' => __('Album', 'blr-backline')]);
        self::register('discography/new', [DiscographyPages::class, 'render_release_form'], ['title' => __('New Album', 'blr-backline')]);
        self::register('discography/edit', [DiscographyPages::class, 'render_release_form'], ['title' => __('Edit Album', 'blr-backline')]);
        self::register('discography/delete', [DiscographyPages::class, 'handle_release_delete'], ['title' => __('Delete Album', 'blr-backline')]);

        // Tracks
        self::register('tracks', [DiscographyPages::class, 'render_tracks_list'], ['title' => __('Tracks', 'blr-backline')]);
        self::register('tracks/view', [DiscographyPages::class, 'render_track_view'], ['title' => __('Track', 'blr-backline')]);
        self::register('tracks/new', [DiscographyPages::class, 'render_track_form'], ['title' => __('New Track', 'blr-backline')]);
        self::register('tracks/edit', [DiscographyPages::class, 'render_track_form'], ['title' => __('Edit Track', 'blr-backline')]);
        self::register('tracks/delete', [DiscographyPages::class, 'handle_track_delete'], ['title' => __('Delete Track', 'blr-backline')]);

        // Contacts
        self::register('contacts', [ContactsPages::class, 'render_list'], ['title' => __('Contacts', 'blr-backline')]);
        self::register('contacts/view', [ContactsPages::class, 'render_view'], ['title' => __('Contact', 'blr-backline')]);
        self::register('contacts/new', [ContactsPages::class, 'render_form'], ['title' => __('New Contact', 'blr-backline')]);
        self::register('contacts/edit', [ContactsPages::class, 'render_form'], ['title' => __('Edit Contact', 'blr-backline')]);
        self::register('contacts/delete', [ContactsPages::class, 'handle_delete'], ['title' => __('Delete Contact', 'blr-backline')]);

        // Outreach
        self::register('outreach', [OutreachPages::class, 'render_list'], ['title' => __('Outreach', 'blr-backline')]);
        self::register('outreach/view', [OutreachPages::class, 'render_view'], ['title' => __('Outreach Campaign', 'blr-backline')]);
        self::register('outreach/new', [OutreachPages::class, 'render_form'], ['title' => __('New Outreach Campaign', 'blr-backline')]);
        self::register('outreach/edit', [OutreachPages::class, 'render_form'], ['title' => __('Edit Outreach Campaign', 'blr-backline')]);
        self::register('outreach/delete', [OutreachPages::class, 'handle_delete'], ['title' => __('Delete Outreach Campaign', 'blr-backline')]);

        // Events + Calendar
        self::register('events', [EventsPages::class, 'render_list'], ['title' => __('Events', 'blr-backline')]);
        self::register('events/view', [EventsPages::class, 'render_view'], ['title' => __('Event', 'blr-backline')]);
        self::register('events/new', [EventsPages::class, 'render_form'], ['title' => __('New Event', 'blr-backline')]);
        self::register('events/edit', [EventsPages::class, 'render_form'], ['title' => __('Edit Event', 'blr-backline')]);
        self::register('events/delete', [EventsPages::class, 'handle_delete'], ['title' => __('Delete Event', 'blr-backline')]);

        // Finances
        self::register('finances', [\BLR\Backline\Modules\Finances\Pages::class, 'render_list'], ['title' => __('Finances', 'blr-backline')]);
        self::register('finances/view', [\BLR\Backline\Modules\Finances\Pages::class, 'render_view'], ['title' => __('Finance Record', 'blr-backline')]);
        self::register('finances/new', [\BLR\Backline\Modules\Finances\Pages::class, 'render_form'], ['title' => __('New Finance Record', 'blr-backline')]);
        self::register('finances/edit', [\BLR\Backline\Modules\Finances\Pages::class, 'render_form'], ['title' => __('Edit Finance Record', 'blr-backline')]);
        self::register('finances/delete', [\BLR\Backline\Modules\Finances\Pages::class, 'handle_delete'], ['title' => __('Delete Finance Record', 'blr-backline')]);

        // Tasks
        self::register('tasks', [TasksPages::class, 'render_list'], ['title' => __('Tasks', 'blr-backline')]);
        self::register('tasks/view', [TasksPages::class, 'render_view'], ['title' => __('Task', 'blr-backline')]);
        self::register('tasks/new', [TasksPages::class, 'render_form'], ['title' => __('New Task', 'blr-backline')]);
        self::register('tasks/edit', [TasksPages::class, 'render_form'], ['title' => __('Edit Task', 'blr-backline')]);
        self::register('tasks/delete', [TasksPages::class, 'handle_delete'], ['title' => __('Delete Task', 'blr-backline')]);

        self::register('calendar', function($ctx){
            return Views::render('pages/module-calendar', $ctx);
        }, ['title' => __('Calendar', 'blr-backline')]);
    }

    public static function add_rewrite_rules(): void {
        $slug = SettingsPage::get_dashboard_slug();
        if (!$slug) {
            $slug = 'blr-backline';
        }

        add_rewrite_tag('%blr_band_admin%', '1');
        add_rewrite_tag('%blr_ba_path%', '(.+)');

        add_rewrite_rule('^' . preg_quote($slug, '/') . '/?$', 'index.php?blr_band_admin=1&blr_ba_path=dashboard', 'top');
        add_rewrite_rule('^' . preg_quote($slug, '/') . '/(.+?)/?$', 'index.php?blr_band_admin=1&blr_ba_path=$matches[1]', 'top');
    }

    public static function maybe_flush_rewrite_rules(): void {
        if (!SettingsPage::rewrite_flush_required()) {
            return;
        }

        flush_rewrite_rules(false);
        SettingsPage::clear_rewrite_flush_required();
    }

    public static function query_vars(array $vars): array {
        $vars[] = 'blr_band_admin';
        $vars[] = 'blr_ba_path';
        return $vars;
    }

    public static function base_url(): string {
        return trailingslashit(home_url('/' . SettingsPage::get_dashboard_slug() . '/'));
    }

    public static function login_url(string $redirect_path = ''): string {
        $u = self::base_url() . 'login/';
        if ($redirect_path !== '') {
            $redirect_path = ltrim($redirect_path, '/');
            $u = add_query_arg(['redirect' => $redirect_path], $u);
        }
        return $u;
    }

    public static function not_allowed_url(): string {
        return self::base_url() . 'not-allowed/';
    }


    private static function canonicalize_path(string $path): string {
        $path = trim($path, '/');
        if ($path === 'discography' || strpos($path, 'discography/') === 0) {
            return preg_replace('~^discography(?=/|$)~', 'albums', $path) ?: 'albums';
        }

        return $path;
    }

    public static function handle_request(): void {
        $is = get_query_var('blr_band_admin');
        if ((string) $is !== '1') {
            return;
        }

        $path = (string) get_query_var('blr_ba_path');
        $path = trim((string) wp_unslash($path), '/');
        if ($path === '') {
            $path = 'dashboard';
        }

        $canonical_path = self::canonicalize_path($path);
        if ($canonical_path !== $path) {
            $request_method = strtoupper(sanitize_text_field((string) wp_unslash($_SERVER['REQUEST_METHOD'] ?? 'GET')));
            if (in_array($request_method, ['GET', 'HEAD'], true)) {
                wp_safe_redirect(self::base_url() . trailingslashit($canonical_path), 301);
                exit;
            }

            $path = $canonical_path;
        }

        $raw_segments = array_values(array_filter(explode('/', $path), 'strlen'));
        $segments = array_map('sanitize_key', $raw_segments);

        $id = 0;
        if ($segments && ctype_digit((string) end($segments))) {
            $id = absint((string) array_pop($segments));
        }

        $page = implode('/', $segments);
        if ($page === '') {
            $page = 'dashboard';
        }

        $section = $segments[0] ?? 'dashboard';
        $action = $segments[1] ?? '';
        $subaction = $segments[2] ?? '';

        // Auth gating
        $unprotected = in_array($section, ['login', 'not-allowed'], true);
        if (!$unprotected) {
            if (!is_user_logged_in()) {
                wp_safe_redirect(self::login_url($path));
                exit;
            }
            if (!Access::user_can_access()) {
                wp_safe_redirect(self::not_allowed_url());
                exit;
            }
        } else {
            if ($section === 'login' && is_user_logged_in()) {
                if (Access::user_can_access()) {
                    wp_safe_redirect(self::base_url());
                } else {
                    wp_safe_redirect(self::not_allowed_url());
                }
                exit;
            }

            if ($section === 'not-allowed' && is_user_logged_in() && Access::user_can_access()) {
                wp_safe_redirect(self::base_url());
                exit;
            }
        }

        $route = self::$routes[$page] ?? null;
        if ($route && !self::route_is_enabled($page)) {
            $route = null;
        }
        $ctx = [
            'page' => $page,
            'title' => $route['title'] ?? ucfirst(str_replace('/', ' ', $page)),
            'dashboard_slug' => SettingsPage::get_dashboard_slug(),
            'nav' => self::nav_items(),
            'section' => $section,
            'action' => $action,
            'subaction' => $subaction,
            'id' => $id,
            'base_url' => self::base_url(),
        ];

        if (in_array($section, ['login', 'not-allowed'], true)) {
            $ctx['layout'] = 'auth';
        }

        if ($route && !self::current_user_can_route($page)) {
            wp_safe_redirect(self::not_allowed_url());
            exit;
        }

        if ($route) {
            $ctx = FrontendFormHandler::maybe_handle($ctx);
        }

        $body = $route ? (string) call_user_func($route['handler'], $ctx) : Views::render('pages/404', $ctx);

        status_header($route ? 200 : 404);
        nocache_headers();
        send_nosniff_header();
        header('X-Robots-Tag: noindex, nofollow', true);
        header('Content-Type: text/html; charset=utf-8');
        Views::render_layout($ctx, $body);
        exit;
    }

    public static function nav_items(): array {
        $slug = SettingsPage::get_dashboard_slug();
        $base = home_url('/' . $slug . '/');

        $items = [
            ['label' => __('Dashboard', 'blr-backline'), 'url' => $base, 'icon' => 'sliders', 'route' => 'dashboard', 'priority' => 10],
        ];

        if (self::route_is_enabled('albums') && self::current_user_can_route('albums')) {
            $items[] = ['label' => __('Albums', 'blr-backline'), 'url' => $base . 'albums/', 'icon' => 'disc', 'route' => 'albums', 'priority' => 20];
            $items[] = ['label' => __('Tracks', 'blr-backline'), 'url' => $base . 'tracks/', 'icon' => 'music', 'route' => 'tracks', 'priority' => 30];
        }
        if (self::route_is_enabled('contacts') && self::current_user_can_route('contacts')) {
            $items[] = ['label' => __('Contacts', 'blr-backline'), 'url' => $base . 'contacts/', 'icon' => 'users', 'route' => 'contacts', 'priority' => 40];
        }
        if (self::route_is_enabled('outreach') && self::current_user_can_route('outreach')) {
            $items[] = ['label' => __('Outreach', 'blr-backline'), 'url' => $base . 'outreach/', 'icon' => 'send', 'route' => 'outreach', 'priority' => 50];
        }
        if (self::route_is_enabled('events') && self::current_user_can_route('events')) {
            $items[] = ['label' => __('Events', 'blr-backline'), 'url' => $base . 'events/', 'icon' => 'calendar', 'route' => 'events', 'priority' => 60];
            $items[] = ['label' => __('Calendar', 'blr-backline'), 'url' => $base . 'calendar/', 'icon' => 'grid', 'route' => 'calendar', 'priority' => 65];
        }
        if (self::route_is_enabled('tasks') && self::current_user_can_route('tasks')) {
            $items[] = ['label' => __('Tasks', 'blr-backline'), 'url' => $base . 'tasks/', 'icon' => 'check-square', 'route' => 'tasks', 'priority' => 70];
        }
        if (self::route_is_enabled('finances') && self::current_user_can_route('finances')) {
            $items[] = ['label' => __('Finances', 'blr-backline'), 'url' => $base . 'finances/', 'icon' => 'dollar-sign', 'route' => 'finances', 'priority' => 75];
        }
        if (self::route_is_enabled('notifications') && self::current_user_can_route('notifications')) {
            $items[] = ['label' => __('Notifications', 'blr-backline'), 'url' => $base . 'notifications/', 'icon' => 'bell', 'route' => 'notifications', 'priority' => 80];
        }

        $items = apply_filters('blr_backline_nav_items', $items, $base, $slug);
        if (!is_array($items)) {
            return [];
        }

        $normalized = [];
        foreach ($items as $index => $item) {
            if (!is_array($item)) {
                continue;
            }

            $label = isset($item['label']) ? (string) $item['label'] : '';
            $url = isset($item['url']) ? (string) $item['url'] : '';
            if ($label === '' || $url === '') {
                continue;
            }

            $normalized[] = [
                'label'    => $label,
                'url'      => $url,
                'icon'     => isset($item['icon']) ? (string) $item['icon'] : 'circle',
                'route'    => isset($item['route']) ? trim((string) $item['route'], '/') : '',
                'priority' => isset($item['priority']) ? (int) $item['priority'] : 100,
                '_index'   => (int) $index,
            ];
        }

        usort($normalized, static function (array $a, array $b): int {
            if ($a['priority'] === $b['priority']) {
                return $a['_index'] <=> $b['_index'];
            }

            return $a['priority'] <=> $b['priority'];
        });

        foreach ($normalized as &$item) {
            unset($item['_index']);
        }
        unset($item);

        return $normalized;
    }

    // ----- Handlers (front-end CRUD) -----
    public static function handle_releases_list(array $ctx): string {
        return Views::render('pages/discography-releases', $ctx);
    }

    public static function handle_release_form(array $ctx): string {
        return Views::render('pages/discography-release-form', $ctx);
    }

    public static function handle_release_view(array $ctx): string {
        return Views::render('pages/view-release', $ctx);
    }

    public static function handle_tracks_list(array $ctx): string {
        return Views::render('pages/discography-tracks', $ctx);
    }

    public static function handle_track_form(array $ctx): string {
        return Views::render('pages/discography-track-form', $ctx);
    }

    public static function handle_track_view(array $ctx): string {
        return Views::render('pages/view-track', $ctx);
    }

    public static function handle_contacts_list(array $ctx): string {
        return Views::render('pages/contacts', $ctx);
    }

    public static function handle_contact_form(array $ctx): string {
        return Views::render('pages/contact-form', $ctx);
    }

    public static function handle_contact_view(array $ctx): string {
        return Views::render('pages/view-contact', $ctx);
    }

    public static function handle_outreach_list(array $ctx): string {
        return Views::render('pages/outreach-campaigns', $ctx);
    }

    public static function handle_outreach_form(array $ctx): string {
        return Views::render('pages/outreach-form', $ctx);
    }

    public static function handle_outreach_view(array $ctx): string {
        return Views::render('pages/view-outreach', $ctx);
    }

    public static function handle_events_list(array $ctx): string {
        return Views::render('pages/events', $ctx);
    }

    public static function handle_event_form(array $ctx): string {
        return Views::render('pages/event-form', $ctx);
    }

    public static function handle_event_view(array $ctx): string {
        return Views::render('pages/view-event', $ctx);
    }

    public static function handle_tasks_list(array $ctx): string {
        return Views::render('pages/tasks', $ctx);
    }

    public static function handle_task_form(array $ctx): string {
        return Views::render('pages/task-form', $ctx);
    }

    public static function handle_task_view(array $ctx): string {
        return Views::render('pages/view-task', $ctx);
    }

    public static function handle_notifications_list(array $ctx): string {
        return Views::render('pages/notifications', $ctx);
    }

    // ----- Delete handlers -----
    public static function handle_before_delete_post(int $post_id): void {
        $post_id = absint($post_id);
        if ($post_id <= 0) {
            return;
        }

        $post = get_post($post_id);
        if (!$post instanceof \WP_Post) {
            return;
        }

        switch ($post->post_type) {
            case 'blr_track':
                Media::cleanup_post_owned_featured_image($post_id);
                self::cleanup_track_related_media($post_id);
                break;

            case 'blr_release':
            case 'blr_event':
                Media::cleanup_post_owned_featured_image($post_id);
                break;

            case 'blr_outreach':
                self::cleanup_outreach_related_data($post_id);
                break;
        }
    }

    private static function cleanup_track_related_media(int $track_id): void {
        $track_id = absint($track_id);
        if ($track_id <= 0) {
            return;
        }

        $audio_attachment_id = absint(get_post_meta($track_id, 'blr_audio_attachment_id', true));
        if ($audio_attachment_id > 0 && Media::is_post_owned_attachment($audio_attachment_id, $track_id)) {
            CrudHelpers::delete_attachment($audio_attachment_id);
        }

        self::cleanup_track_release_relationships($track_id);
    }

    private static function cleanup_track_release_relationships(int $track_id): void {
        $track_id = absint($track_id);
        if ($track_id <= 0) {
            return;
        }

        $batch_size = 100;
        $offset = 0;

        do {
            $release_ids = get_posts([
                'post_type' => 'blr_release',
                'post_status' => ['publish', 'draft', 'private', 'trash'],
                'posts_per_page' => $batch_size,
                'offset' => $offset,
                'orderby' => 'ID',
                'order' => 'ASC',
                'fields' => 'ids',
                'no_found_rows' => true,
            ]);

            $release_ids = array_values(array_unique(array_map('absint', is_array($release_ids) ? $release_ids : [])));
            foreach ($release_ids as $release_id) {
                if ($release_id <= 0) {
                    continue;
                }

                $track_ids = array_values(array_filter(array_map('absint', (array) get_post_meta($release_id, 'blr_track_ids', true))));
                if (!$track_ids || !in_array($track_id, $track_ids, true)) {
                    continue;
                }

                update_post_meta($release_id, 'blr_track_ids', array_values(array_diff($track_ids, [$track_id])));
            }

            $offset += count($release_ids);
        } while (!empty($release_ids));
    }

    private static function cleanup_outreach_related_data(int $campaign_id): void {
        OutreachModule::cleanup_campaign_related_data($campaign_id);
    }

    public static function maybe_hide_admin_bar(bool $show): bool {
        if (is_admin()) {
            return $show;
        }

        if ((string) get_query_var('blr_band_admin') === '1') {
            return false;
        }

        return $show;
    }


}
