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

use BLR\Backline\Core\Access;
use BLR\Backline\Core\AdminMenu;
use BLR\Backline\Core\RelatedRecords;
use BLR\Backline\Core\Sanitizer;

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

final class Module {
    public static function register_feature_only(): void {
        add_action('init', [self::class, 'register_cpt']);
        add_action('init', [self::class, 'register_meta'], 11);
    }

    public static function register_cpt(): void {
        register_post_type('blr_task', array_merge([
            'labels' => [
                'name' => __('Tasks', 'blr-backline'),
                'singular_name' => __('Task', 'blr-backline'),
            ],
            'public' => false,
            'show_ui' => false,
            'show_in_menu' => false,
            'show_in_rest' => false,
            'supports' => ['title', 'editor', 'revisions', 'author'],
            'menu_icon' => 'dashicons-yes-alt',
        ], Access::post_type_registration_args('blr_task')));
    }

    public static function register_meta(): void {
        self::reg_meta('blr_task', 'blr_task_status', 'string');
        self::reg_meta('blr_task', 'blr_task_priority', 'string');
        self::reg_meta('blr_task', 'blr_task_due_date', 'string');
        self::reg_meta('blr_task', 'blr_task_start_date', 'string');
        self::reg_meta('blr_task', 'blr_task_completed_at', 'string');
        self::reg_meta('blr_task', 'blr_task_assignee_user_id', 'integer');
        self::reg_meta('blr_task', 'blr_task_related_post_id', 'integer');
        self::reg_meta('blr_task', 'blr_task_related_post_type', 'string');
        self::reg_meta('blr_task', 'blr_task_checklist', 'string');
    }

    private static function reg_meta(string $post_type, string $key, string $type): void {
        register_post_meta($post_type, $key, [
            'type' => $type,
            'single' => true,
            'show_in_rest' => false,
            'sanitize_callback' => static function ($value) use ($key, $type) {
                if ($key === 'blr_task_status') {
                    return self::normalize_status((string) $value);
                }

                if ($key === 'blr_task_priority') {
                    return self::normalize_priority((string) $value);
                }

                if (in_array($key, ['blr_task_due_date', 'blr_task_start_date'], true)) {
                    return Sanitizer::date_ymd($value);
                }

                return Sanitizer::meta_value($key, $value, $type);
            },
            'auth_callback' => Access::rest_meta_auth_callback($post_type),
        ]);
    }

    public static function statuses(): array {
        return ['Backlog', 'To Do', 'In Progress', 'Blocked', 'Done'];
    }

    public static function normalize_status(string $value): string {
        $value = trim(sanitize_text_field($value));
        if ($value === '') {
            return '';
        }

        $aliases = [
            'backlog' => 'Backlog',
            'todo' => 'To Do',
            'to do' => 'To Do',
            'inprogress' => 'In Progress',
            'in progress' => 'In Progress',
            'blocked' => 'Blocked',
            'done' => 'Done',
        ];

        $normalized = strtolower($value);
        $compact = preg_replace('/\s+/', ' ', $normalized);
        return $aliases[$compact] ?? $aliases[str_replace(' ', '', $compact)] ?? '';
    }

    public static function priorities(): array {
        return ['Low', 'Medium', 'High', 'Urgent'];
    }

    public static function normalize_priority(string $value): string {
        $value = trim(sanitize_text_field($value));
        if ($value === '') {
            return '';
        }

        foreach (self::priorities() as $option) {
            if (strcasecmp($option, $value) === 0) {
                return $option;
            }
        }

        return '';
    }

    public static function status_label(string $value): string {
        switch ($value) {
            case 'Backlog': return __('Backlog', 'blr-backline');
            case 'To Do': return __('To Do', 'blr-backline');
            case 'In Progress': return __('In Progress', 'blr-backline');
            case 'Blocked': return __('Blocked', 'blr-backline');
            case 'Done': return __('Done', 'blr-backline');
            default: return $value;
        }
    }

    public static function priority_label(string $value): string {
        switch ($value) {
            case 'Low': return __('Low', 'blr-backline');
            case 'Medium': return __('Medium', 'blr-backline');
            case 'High': return __('High', 'blr-backline');
            case 'Urgent': return __('Urgent', 'blr-backline');
            default: return $value;
        }
    }

    public static function badge(string $value, string $context = 'status'): string {
        $map = $context === 'priority'
            ? [
                'Low' => 'secondary',
                'Medium' => 'info',
                'High' => 'warning',
                'Urgent' => 'danger',
            ]
            : [
                'Backlog' => 'secondary',
                'To Do' => 'warning',
                'In Progress' => 'info',
                'Blocked' => 'danger',
                'Done' => 'success',
            ];

        $class = $map[$value] ?? 'secondary';
        $label = $value !== '' ? ($context === 'priority' ? self::priority_label($value) : self::status_label($value)) : __('—', 'blr-backline');
        return '<span class="badge bg-' . esc_attr($class) . '">' . esc_html($label) . '</span>';
    }

    public static function due_state_class(string $due_date, string $status = ''): string {
        if ($due_date === '' || $status === 'Done') {
            return 'text-muted';
        }

        $today = current_time('Y-m-d');
        if ($due_date < $today) {
            return 'text-danger';
        }
        if ($due_date === $today) {
            return 'text-warning';
        }

        return 'text-body';
    }

    public static function assignable_users(): array {
        $users = [];

        foreach (get_users(['role__in' => ['administrator']]) as $user) {
            if ($user instanceof \WP_User) {
                $users[(int) $user->ID] = $user;
            }
        }

        foreach ((array) \BLR\Backline\Core\SettingsPage::get_allowed_user_ids() as $user_id) {
            $user = get_userdata((int) $user_id);
            if ($user instanceof \WP_User) {
                $users[(int) $user->ID] = $user;
            }
        }

        uasort($users, static function (\WP_User $a, \WP_User $b): int {
            return strcasecmp($a->display_name, $b->display_name);
        });

        return $users;
    }

    public static function related_options(array $args = []): array {
        return RelatedRecords::options(array_merge([
            'exclude_post_types' => ['blr_task'],
            'include_woocommerce' => current_user_can('edit_products'),
        ], $args));
    }

    public static function related_label(int $post_id): string {
        return RelatedRecords::descriptor($post_id)['label'] ?? '';
    }
}
