<?php

namespace WPSN\Modules\ImportExport;

defined('ABSPATH') || exit;

final class ImportAssistGuidedReviewPlanner
{
    /**
     * @param array<int,array<string,mixed>> $tasks
     * @return array{entry_id:string,entry_title:string,task_key:string,label:string,url:string,url_label:string,priority:string,index:int}|null
     */
    public function nextTask(array $tasks, string $entryId = '', string $entryTitle = ''): ?array
    {
        $entry = [
            'entry_id' => $entryId,
            'entry_title' => $entryTitle,
            'tasks' => $tasks,
        ];

        return $this->nextTaskAcrossEntries([$entry]);
    }

    /**
     * @param array<int,array<string,mixed>> $entries
     * @return array{entry_id:string,entry_title:string,task_key:string,label:string,url:string,url_label:string,priority:string,index:int}|null
     */
    public function nextTaskAcrossEntries(array $entries): ?array
    {
        $best = null;

        foreach ($entries as $entryIndex => $entry) {
            if (!is_array($entry)) {
                continue;
            }

            $entryId = isset($entry['entry_id']) ? strtolower(trim((string) $entry['entry_id'])) : '';
            $entryTitle = isset($entry['entry_title']) ? trim((string) $entry['entry_title']) : '';
            $tasks = isset($entry['tasks']) && is_array($entry['tasks']) ? $entry['tasks'] : [];
            foreach ($tasks as $taskIndex => $task) {
                $candidate = $this->normalizeCandidate($task, $entryId, $entryTitle, ($entryIndex * 1000) + $taskIndex);
                if ($candidate === null) {
                    continue;
                }
                if ($best === null || $this->isBetterCandidate($candidate, $best)) {
                    $best = $candidate;
                }
            }
        }

        return $best;
    }

    /**
     * @param mixed $task
     * @return array{entry_id:string,entry_title:string,task_key:string,label:string,url:string,url_label:string,priority:string,index:int}|null
     */
    private function normalizeCandidate($task, string $entryId, string $entryTitle, int $index): ?array
    {
        if (!is_array($task)) {
            return null;
        }

        $checked = !empty($task['checked']);
        $url = isset($task['url']) ? trim((string) $task['url']) : '';
        $taskKey = isset($task['key']) ? sanitize_key((string) $task['key']) : '';
        if ($checked || $url === '' || $taskKey === '') {
            return null;
        }

        $priority = isset($task['priority']) ? sanitize_key((string) $task['priority']) : 'medium';
        if (!in_array($priority, ['high', 'medium', 'low'], true)) {
            $priority = 'medium';
        }

        return [
            'entry_id' => $entryId,
            'entry_title' => $entryTitle,
            'task_key' => $taskKey,
            'label' => isset($task['label']) ? (string) $task['label'] : '',
            'url' => $url,
            'url_label' => isset($task['url_label']) ? (string) $task['url_label'] : '',
            'priority' => $priority,
            'index' => $index,
        ];
    }

    /**
     * @param array{priority:string,index:int} $candidate
     * @param array{priority:string,index:int} $best
     */
    private function isBetterCandidate(array $candidate, array $best): bool
    {
        $candidateWeight = $this->priorityWeight((string) $candidate['priority']);
        $bestWeight = $this->priorityWeight((string) $best['priority']);

        if ($candidateWeight !== $bestWeight) {
            return $candidateWeight < $bestWeight;
        }

        return (int) $candidate['index'] < (int) $best['index'];
    }

    private function priorityWeight(string $priority): int
    {
        switch (sanitize_key($priority)) {
            case 'high':
                return 0;
            case 'low':
                return 2;
            case 'medium':
            default:
                return 1;
        }
    }
}
