<?php

namespace App\Http\Controllers;

use App\Models\News;
use App\Support\CrmModuleManager;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;

class NewsController extends Controller
{
    public function index(Request $request): View
    {
        $user = $request->user();
        $newsFeed = News::query()
            ->with(['author:id,name,email'])
            ->orderByDesc('published_at')
            ->orderByDesc('id')
            ->paginate(20)
            ->withQueryString();

        $viewerNames = [];
        $newsIds = $newsFeed->getCollection()
            ->pluck('id')
            ->map(fn ($id) => (int) $id)
            ->values()
            ->all();

        if ($user && $newsIds !== []) {
            $now = now();
            $rows = array_map(static fn (int $newsId): array => [
                'news_id' => $newsId,
                'user_id' => (int) $user->id,
                'viewed_at' => $now,
                'created_at' => $now,
                'updated_at' => $now,
            ], $newsIds);

            DB::table('news_views')->insertOrIgnore($rows);
        }

        if ($newsIds !== []) {
            $newsFeed->getCollection()->loadCount('views');

            foreach ($newsFeed->getCollection() as $news) {
                $names = $news->views()
                    ->with('user:id,name')
                    ->latest('viewed_at')
                    ->limit(8)
                    ->get()
                    ->pluck('user.name')
                    ->filter()
                    ->unique()
                    ->values()
                    ->all();

                $viewerNames[(int) $news->id] = $names;
            }
        }

        return view('news.index', [
            'newsFeed' => $newsFeed,
            'canCreateNews' => $user !== null,
            'newsViewerNames' => $viewerNames,
        ]);
    }

    public function create(Request $request): View
    {
        if ($request->boolean('sidepanel') || $request->header('X-Sidepanel') === '1') {
            return view('sidepanel.news.create');
        }

        return view('news.create');
    }

    public function store(Request $request, CrmModuleManager $moduleManager): RedirectResponse|JsonResponse
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:180'],
            'content' => ['required', 'string', 'max:10000'],
            'preview' => ['nullable', 'image', 'max:5120'],
        ]);
        $payload = Arr::except($validated, ['preview']);
        $payload = $moduleManager->applyPayloadHooks('news.store', $payload, [
            'hook' => 'news.store',
            'user_id' => $request->user()->id,
        ], array_keys($payload));

        $previewPath = null;
        if ($request->hasFile('preview')) {
            $previewPath = $request->file('preview')->store('news-previews', 'public');
        }

        $news = News::query()->create([
            'title' => trim((string) ($payload['title'] ?? $validated['title'])),
            'content' => trim((string) ($payload['content'] ?? $validated['content'])),
            'user_id' => $request->user()->id,
            'published_at' => now(),
            'preview_path' => $previewPath,
        ]);

        if ($request->expectsJson() || $request->boolean('sidepanel') || $request->header('X-Sidepanel') === '1') {
            return response()->json([
                'message' => 'The news has been published.',
                'news_id' => $news->id,
                'reload' => true,
                'redirect_url' => route('news.index'),
            ]);
        }

        return redirect()
            ->route('news.index')
            ->with('success', 'The news has been published.');
    }
}
