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

use BLR\Backline\Core\Access;
use BLR\Backline\Core\CrudHelpers;
use BLR\Backline\Core\ListPage;
use BLR\Backline\Core\Request;
use BLR\Backline\Core\Router;
use BLR\Backline\Core\Views;

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

final class Pages {
    public static function render_list(array $ctx): string {
        $ctx['tasks_list'] = self::list_data($ctx);
        return Views::render('pages/tasks', $ctx);
    }

    public static function render_form(array $ctx): string {
        $ctx['task_form'] = self::form_data($ctx);
        return Views::render('pages/task-form', $ctx);
    }

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

    public static function handle_delete(array $ctx): string {
        return self::handle_post_delete($ctx, 'blr_task', 'tasks');
    }

    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();
        $status_filter = Request::query_text('status');

        $args = [
            'post_type'      => 'blr_task',
            'post_status'    => ['publish'],
            'posts_per_page' => 25,
            'paged'          => $page_num,
            'meta_key'       => 'blr_task_due_date',
            'orderby'        => ['meta_value' => 'ASC', 'date' => 'DESC'],
        ];

        if ($status_filter !== '') {
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Task archive intentionally filters by task status meta.
            $args['meta_query'] = [[
                'key'   => 'blr_task_status',
                'value' => $status_filter,
            ]];
        }

        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Task archive intentionally sorts by due-date meta.
        $tasks = new \WP_Query($args);
        $summary = Views::pagination_summary_data($tasks, 'pg');

        $persist_args = [];
        if ($status_filter !== '') {
            $persist_args['status'] = $status_filter;
        }

        $task_items = [];
        foreach ((array) $tasks->posts as $task) {
            if (!$task instanceof \WP_Post) {
                continue;
            }

            $task_id = (int) $task->ID;
            $status = (string) get_post_meta($task_id, 'blr_task_status', true);
            $priority = (string) get_post_meta($task_id, 'blr_task_priority', true);
            $due_date = (string) get_post_meta($task_id, 'blr_task_due_date', true);
            $related_id = (int) get_post_meta($task_id, 'blr_task_related_post_id', true);
            $description = trim((string) $task->post_content) !== ''
                ? wp_trim_words(wp_strip_all_tags((string) $task->post_content), 12)
                : '';

            $task_items[] = [
                'id'              => $task_id,
                'title'           => get_the_title($task),
                'description'     => $description,
                'status'          => $status,
                'priority'        => $priority,
                'due_date'        => $due_date,
                'related_id'      => $related_id,
                'related_label'   => $related_id ? Module::related_label($related_id) : '',
                'due_state_class' => Module::due_state_class($due_date, $status),
                'status_badge'    => Module::badge($status),
                'priority_badge'  => Module::badge($priority, 'priority'),
                'view_url'        => $base . 'tasks/view/' . $task_id . '/',
                'edit_url'        => $base . 'tasks/edit/' . $task_id . '/',
                'delete_url'      => $base . 'tasks/delete/' . $task_id . '/',
            ];
        }

        return array_merge(ListPage::notices(), ListPage::view_urls($base, 'tasks', $persist_args, $view_mode), [
            'base'                => $base,
            'page_num'            => $page_num,
            'status_filter'       => $status_filter,
            'view_mode'           => $view_mode,
            'tasks'               => $tasks,
            'summary'             => $summary,
            'task_items'          => $task_items,
            'pagination_base_url' => add_query_arg(array_merge($persist_args, ['view' => $view_mode]), $base . 'tasks/'),
        ]);
    }

    public static function form_data(array $ctx): array {
        $base = ListPage::base_url($ctx);
        $is_edit = ($ctx['action'] ?? '') === 'edit';
        $post_id = $is_edit ? (int) ($ctx['id'] ?? 0) : 0;
        $post = $post_id ? get_post($post_id) : null;
        $errors = isset($ctx['errors']) && is_array($ctx['errors']) ? $ctx['errors'] : [];
        $submitted_nonce = isset($_POST['_wpnonce']) ? sanitize_text_field((string) wp_unslash($_POST['_wpnonce'])) : '';
        $failed_post = !empty($errors) && Request::method() === 'POST' && wp_verify_nonce($submitted_nonce, 'blr_ba_save_task');

        $posted_values = [];
        if ($failed_post) {
            $posted_values = [
                'title'                         => Request::post_text('title'),
                'content'                       => Request::post_kses('content'),
                'blr_task_checklist'            => Request::post_kses('blr_task_checklist'),
                'blr_task_status'               => Request::post_text('blr_task_status'),
                'blr_task_priority'             => Request::post_text('blr_task_priority'),
                'blr_task_start_date'           => Request::post_text('blr_task_start_date'),
                'blr_task_due_date'             => Request::post_text('blr_task_due_date'),
                'blr_task_assignee_user_id'     => Request::post_absint('blr_task_assignee_user_id'),
                'blr_task_related_post_id'      => Request::post_absint('blr_task_related_post_id'),
            ];
        }

        $related_selected_id = (int) self::task_meta_value($post_id, 'blr_task_related_post_id', $failed_post, $posted_values);

        return [
            'base'                => $base,
            'is_edit'             => $is_edit,
            'post_id'             => $post_id,
            'post'                => $post,
            'saved_notice'        => Request::query_absint('saved'),
            'errors'              => $errors,
            'failed_post'         => $failed_post,
            'posted_values'       => $posted_values,
            'title_v'             => $failed_post ? (string) ($posted_values['title'] ?? '') : ($post instanceof \WP_Post ? (string) $post->post_title : ''),
            'content_v'           => $failed_post ? (string) ($posted_values['content'] ?? '') : ($post instanceof \WP_Post ? (string) $post->post_content : ''),
            'users'               => Module::assignable_users(),
            'related_selected_id' => $related_selected_id,
            'related_options'     => Module::related_options(['include_post_ids' => $related_selected_id > 0 ? [$related_selected_id] : []]),
        ];
    }

    public static function view_data(array $ctx): array {
        $base = ListPage::base_url($ctx);
        $id = (int) ($ctx['id'] ?? 0);
        $post = $id ? get_post($id) : null;
        if (!$post instanceof \WP_Post || $post->post_type !== 'blr_task') {
            return ['not_found' => true, 'base' => $base, 'id' => $id, 'post' => null];
        }

        $status = (string) get_post_meta($id, 'blr_task_status', true);
        $priority = (string) get_post_meta($id, 'blr_task_priority', true);
        $start_date = (string) get_post_meta($id, 'blr_task_start_date', true);
        $due_date = (string) get_post_meta($id, 'blr_task_due_date', true);
        $completed_at = (string) get_post_meta($id, 'blr_task_completed_at', true);
        $assignee_id = (int) get_post_meta($id, 'blr_task_assignee_user_id', true);
        $related_id = (int) get_post_meta($id, 'blr_task_related_post_id', true);

        return [
            'not_found'   => false,
            'base'        => $base,
            'id'          => $id,
            'post'        => $post,
            'status'      => $status,
            'priority'    => $priority,
            'start_date'  => $start_date,
            'due_date'    => $due_date,
            'completed_at'=> $completed_at,
            'assignee_id' => $assignee_id,
            'related_id'  => $related_id,
            'checklist'   => (string) get_post_meta($id, 'blr_task_checklist', true),
            'assignee'    => $assignee_id ? get_userdata($assignee_id) : null,
            'related_post'=> $related_id ? get_post($related_id) : null,
            'edit_url'    => $base . 'tasks/edit/' . $id . '/',
            'delete_url'  => $base . 'tasks/delete/' . $id . '/',
        ];
    }

    public static function task_meta_value(int $post_id, string $key, bool $failed_post, array $posted_values) {
        if ($failed_post && array_key_exists($key, $posted_values)) {
            return $posted_values[$key];
        }

        return $post_id ? get_post_meta($post_id, $key, true) : '';
    }

    private static function handle_post_delete(array $ctx, string $post_type, string $section): string {
        $id = (int) ($ctx['id'] ?? 0);
        $redirect_to = rtrim((string) ($ctx['base_url'] ?? Router::base_url()), '/') . '/' . $section . '/?deleted=1';

        if ($id <= 0) {
            CrudHelpers::redirect(add_query_arg(['delete_error' => 'missing_id'], $redirect_to));
            return '';
        }

        if (Request::method() !== 'POST') {
            CrudHelpers::redirect(add_query_arg(['delete_error' => 'invalid_method'], $redirect_to));
            return '';
        }

        $nonce_action = 'blr_ba_delete_' . $post_type . '_' . $id;
        $nonce = isset($_POST['_wpnonce']) ? sanitize_text_field((string) wp_unslash($_POST['_wpnonce'])) : '';
        if ($nonce === '' || !wp_verify_nonce($nonce, $nonce_action)) {
            CrudHelpers::redirect(add_query_arg(['delete_error' => 'invalid_nonce'], $redirect_to));
            return '';
        }

        $post = get_post($id);
        if (!$post instanceof \WP_Post || $post->post_type !== $post_type) {
            return Views::render('pages/404', $ctx);
        }

        if (!Access::can_delete_post($id, $post_type)) {
            CrudHelpers::redirect(add_query_arg(['delete_error' => 'forbidden'], $redirect_to));
            return '';
        }

        if (!wp_delete_post($id, true)) {
            CrudHelpers::redirect(add_query_arg(['delete_error' => 'delete_failed'], $redirect_to));
            return '';
        }

        CrudHelpers::redirect($redirect_to);
        return '';
    }
}
