<?php

namespace App\Http\Controllers\Admin;

use App\Exports\OctoparseRecordsExport;
use App\Http\Controllers\Controller;
use App\Models\Octoparse\OctoparseImportLog;
use App\Models\Octoparse\OctoparseRecord;
use BackendUserService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
use RequestContext;

class OctoparseController extends Controller
{
    public function getIndex()
    {
        $this->setBreadcrumb();

        $tasks = $this->resolveTasks();
        $taskIds = array_keys($tasks);

        $counts = OctoparseRecord::query()
            ->whereIn('task_id', $taskIds)
            ->selectRaw('task_id, COUNT(*) as total, MAX(imported_at) as last_import')
            ->groupBy('task_id')
            ->get()
            ->keyBy('task_id');

        $lastLogs = [];
        foreach ($taskIds as $taskId) {
            $lastLogs[$taskId] = OctoparseImportLog::forTask($taskId)
                ->orderByDesc('started_at')
                ->first();
        }

        return view('admin.octoparse.index', [
            'tasks' => $tasks,
            'counts' => $counts,
            'lastLogs' => $lastLogs,
            'syncEnabled' => (bool) config('octoparse.sync_enabled'),
            'canRun' => BackendUserService::getLoggedUser()->hasPermission('octoparse.run'),
        ]);
    }

    public function getTask(Request $request, string $taskId)
    {
        $tasks = $this->resolveTasks();
        if (!isset($tasks[$taskId])) {
            abort(404);
        }

        $this->setBreadcrumb();

        $search = trim((string) $request->input('q', ''));
        $query = OctoparseRecord::forTask($taskId);

        if ($search !== '') {
            $like = '%' . $search . '%';
            $query->where(function ($q) use ($like) {
                $q->where('external_key', 'like', $like)
                  ->orWhere('payload', 'like', $like);
            });
        }

        $allowedSorts = ['id', 'external_key', 'scraped_at', 'imported_at'];
        $sort = in_array($request->input('sort'), $allowedSorts, true)
            ? $request->input('sort')
            : 'external_key';
        $dir = strtolower((string) $request->input('dir')) === 'desc' ? 'desc' : 'asc';

        $records = $query->orderBy($sort, $dir)
            ->paginate(25)
            ->appends($request->only('q', 'sort', 'dir'));

        return view('admin.octoparse.task', [
            'taskId' => $taskId,
            'taskConfig' => $tasks[$taskId],
            'records' => $records,
            'search' => $search,
            'sort' => $sort,
            'dir' => $dir,
            'canRun' => BackendUserService::getLoggedUser()->hasPermission('octoparse.run'),
        ]);
    }

    public function getLogs()
    {
        $this->setBreadcrumb();

        $logs = OctoparseImportLog::orderByDesc('started_at')->paginate(50);
        $tasks = $this->resolveTasks();

        return view('admin.octoparse.logs', [
            'logs' => $logs,
            'tasks' => $tasks,
        ]);
    }

    public function getLogNewEntries(int $logId)
    {
        $log = OctoparseImportLog::findOrFail($logId);
        $tasks = $this->resolveTasks();

        $ids = is_array($log->new_record_ids) ? $log->new_record_ids : [];

        $recordsByTask = empty($ids)
            ? collect()
            : OctoparseRecord::whereIn('id', $ids)
                ->orderBy('task_id')
                ->orderBy('id')
                ->get()
                ->groupBy('task_id');

        $this->setBreadcrumb();

        return view('admin.octoparse.new-entries', [
            'log' => $log,
            'tasks' => $tasks,
            'recordsByTask' => $recordsByTask,
            'trackingAvailable' => $log->new_record_ids !== null,
        ]);
    }

    public function getExport()
    {
        return Excel::download(
            new OctoparseRecordsExport($this->resolveTasks()),
            'octoparse-entries-' . now()->format('Y-m-d') . '.xlsx',
            \Maatwebsite\Excel\Excel::XLSX
        );
    }

    public function postRun(?string $taskId = null): RedirectResponse
    {
        $tasks = $this->resolveTasks();

        if ($taskId !== null && !isset($tasks[$taskId])) {
            abort(404);
        }

        $options = ['--manual' => true];
        if ($taskId !== null) {
            $options['--task'] = $taskId;
        }

        try {
            Artisan::queue('octoparse:import', $options);
            $message = $taskId
                ? "Octoparse import queued for task {$taskId}."
                : 'Octoparse import queued for all enabled tasks.';
        } catch (\Throwable $e) {
            Log::error('[Octoparse] Failed to queue import: ' . $e->getMessage());
            return redirect()->back()->with('errorMessage', 'Failed to queue Octoparse import: ' . $e->getMessage());
        }

        return redirect()
            ->route('admin.octoparse.index')
            ->with('message', $message);
    }

    /**
     * @return array<string,array<string,mixed>>
     */
    private function resolveTasks(): array
    {
        $tasks = config('octoparse.tasks', []);
        return is_array($tasks) ? $tasks : [];
    }

    private function setBreadcrumb(): void
    {
        RequestContext::set('selected_menu', 'octoparse');
        RequestContext::set('selected_menu_option', 'octoparse_dashboard');
    }
}
