<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\CommunityBan;
use App\Models\CommunityCategory;
use App\Models\CommunityComment;
use App\Models\CommunityMessage;
use App\Models\CommunityPost;
use App\Models\CommunityPostImage;
use App\Models\CommunityReport;
use App\Models\CommunitySetting;
use App\Models\User;
use App\Services\WeeklyTraderRankingService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class CommunityController extends Controller
{
    public function dashboard(WeeklyTraderRankingService $rankingService): View
    {
        return view('admin.community.dashboard', [
            'settings' => CommunitySetting::current(),
            'totalPosts' => CommunityPost::count(),
            'pendingPosts' => CommunityPost::where('status', CommunityPost::STATUS_PENDING)->count(),
            'reportedPosts' => CommunityReport::where('status', CommunityReport::STATUS_OPEN)->count(),
            'messagesCount' => CommunityMessage::count(),
            'bannedUsers' => CommunityBan::count(),
            'topTraders' => $rankingService->currentTopTraders(),
        ]);
    }

    public function settings(): View
    {
        return view('admin.community.settings', ['settings' => CommunitySetting::current()]);
    }

    public function updateSettings(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'community_enabled' => ['nullable', 'boolean'],
            'allow_public_viewing' => ['nullable', 'boolean'],
            'chat_enabled' => ['nullable', 'boolean'],
            'post_approval_enabled' => ['nullable', 'boolean'],
            'top_traders_enabled' => ['nullable', 'boolean'],
            'top_traders_count' => ['required', 'integer', Rule::in([3, 5])],
        ]);

        CommunitySetting::current()->update([
            'community_enabled' => $request->boolean('community_enabled'),
            'allow_public_viewing' => $request->boolean('allow_public_viewing'),
            'chat_enabled' => $request->boolean('chat_enabled'),
            'post_approval_enabled' => $request->boolean('post_approval_enabled'),
            'top_traders_enabled' => $request->boolean('top_traders_enabled'),
            'top_traders_count' => $data['top_traders_count'],
        ]);

        return back()->with('success', 'Community settings updated.');
    }

    public function posts(Request $request): View
    {
        return view('admin.community.posts', [
            'posts' => CommunityPost::query()
                ->with(['user', 'category'])
                ->with('images')
                ->withCount(['comments', 'likes', 'reports'])
                ->when($request->filled('status'), fn ($query) => $query->where('status', $request->string('status')))
                ->when($request->filled('search'), fn ($query) => $query->where('title', 'like', '%'.$request->string('search')->toString().'%'))
                ->latest()
                ->paginate(20)
                ->withQueryString(),
        ]);
    }

    public function approvePost(CommunityPost $post): RedirectResponse
    {
        $post->update(['status' => CommunityPost::STATUS_PUBLISHED, 'approved_at' => now(), 'approved_by' => auth()->id()]);

        return back()->with('success', 'Post approved.');
    }

    public function togglePostHidden(CommunityPost $post): RedirectResponse
    {
        $post->update(['is_hidden' => ! $post->is_hidden]);

        return back()->with('success', 'Post visibility updated.');
    }

    public function togglePostFeatured(CommunityPost $post): RedirectResponse
    {
        $post->update(['is_featured' => ! $post->is_featured]);

        return back()->with('success', 'Featured status updated.');
    }

    public function destroyPost(CommunityPost $post): RedirectResponse
    {
        $post->delete();

        return back()->with('success', 'Post deleted.');
    }

    public function destroyPostImage(CommunityPost $post, CommunityPostImage $image): RedirectResponse
    {
        abort_unless($image->community_post_id === $post->id, 404);

        $image->delete();

        return back()->with('success', 'Community post image deleted.');
    }

    public function categories(): View
    {
        CommunityCategory::seedDefaults();

        return view('admin.community.categories', [
            'categories' => CommunityCategory::orderBy('sort_order')->orderBy('name')->get(),
        ]);
    }

    public function storeCategory(Request $request): RedirectResponse
    {
        $data = $this->categoryData($request);
        $data['slug'] = Str::slug($data['name']);
        CommunityCategory::create($data);

        return back()->with('success', 'Community category created.');
    }

    public function updateCategory(Request $request, CommunityCategory $category): RedirectResponse
    {
        $data = $this->categoryData($request);
        $data['slug'] = Str::slug($data['name']);
        $category->update($data);

        return back()->with('success', 'Community category updated.');
    }

    public function destroyCategory(CommunityCategory $category): RedirectResponse
    {
        $category->delete();

        return back()->with('success', 'Community category deleted.');
    }

    public function reports(): View
    {
        return view('admin.community.reports', [
            'reports' => CommunityReport::with(['reporter', 'post.user', 'post.images', 'comment.user'])->latest()->paginate(20),
        ]);
    }

    public function updateReport(Request $request, CommunityReport $report): RedirectResponse
    {
        $data = $request->validate(['status' => ['required', Rule::in([CommunityReport::STATUS_OPEN, CommunityReport::STATUS_REVIEWED, CommunityReport::STATUS_DISMISSED])]]);
        $report->update($data);

        return back()->with('success', 'Report status updated.');
    }

    public function messages(): View
    {
        return view('admin.community.messages', [
            'messages' => CommunityMessage::with('user')->latest()->paginate(30),
        ]);
    }

    public function toggleMessageHidden(CommunityMessage $message): RedirectResponse
    {
        $message->update(['is_hidden' => ! $message->is_hidden]);

        return back()->with('success', 'Message visibility updated.');
    }

    public function destroyMessage(CommunityMessage $message): RedirectResponse
    {
        $message->delete();

        return back()->with('success', 'Message deleted.');
    }

    public function toggleCommentHidden(CommunityComment $comment): RedirectResponse
    {
        $comment->update(['is_hidden' => ! $comment->is_hidden]);

        return back()->with('success', 'Comment visibility updated.');
    }

    public function destroyComment(CommunityComment $comment): RedirectResponse
    {
        $comment->delete();

        return back()->with('success', 'Comment deleted.');
    }

    public function banUser(Request $request, User $user): RedirectResponse
    {
        $data = $request->validate([
            'reason' => ['nullable', 'string', 'max:255'],
            'expires_at' => ['nullable', 'date', 'after:now'],
        ]);

        CommunityBan::updateOrCreate(['user_id' => $user->id], $data + ['banned_by' => $request->user()->id]);

        return back()->with('success', 'User blocked from community.');
    }

    public function unbanUser(User $user): RedirectResponse
    {
        CommunityBan::where('user_id', $user->id)->delete();

        return back()->with('success', 'Community ban removed.');
    }

    public function refreshRankings(WeeklyTraderRankingService $rankingService): RedirectResponse
    {
        $rankingService->refresh();

        return back()->with('success', 'Weekly trader rankings refreshed.');
    }

    private function categoryData(Request $request): array
    {
        return $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'description' => ['nullable', 'string', 'max:1000'],
            'sort_order' => ['required', 'integer', 'min:0', 'max:9999'],
            'is_active' => ['nullable', 'boolean'],
        ]) + ['is_active' => $request->boolean('is_active')];
    }
}
