<?php

namespace App\Http\Controllers\Meet;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Meet\Concerns\ScopesToAccount;
use App\Models\Channel;
use App\Models\ChannelMessage;
use App\Services\Meet\ChannelService;
use App\Services\Meet\WorkspaceSearchService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class ChannelController extends Controller
{
    use ScopesToAccount;

    public function __construct(
        protected ChannelService $channels,
        protected WorkspaceSearchService $search,
    ) {}

    public function index(Request $request): View
    {
        $this->authorizeAbility($request, 'meetings.view');
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);

        $query = Channel::owned($owner)->where('organization_id', $organization->id);
        $this->scopeToBranch($request, $query);

        $channels = $query->orderBy('name')->get();

        return view('meet.channels.index', compact('channels', 'organization'));
    }

    public function create(Request $request): View
    {
        $this->authorizeAbility($request, 'meetings.manage');

        return view('meet.channels.create', [
            'organization' => $this->organization($request),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $this->authorizeAbility($request, 'meetings.manage');
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'visibility' => ['required', 'in:public,private'],
            'description' => ['nullable', 'string', 'max:2000'],
        ]);

        $channel = $this->channels->create(
            $request->user(),
            $this->organization($request),
            $validated,
        );

        return redirect()->route('meet.channels.show', $channel)->with('success', 'Channel created.');
    }

    public function show(Request $request, Channel $channel): View
    {
        $this->authorizeAbility($request, 'meetings.view');
        $this->authorizeOwner($request, $channel);
        abort_unless($this->channels->canAccess($channel, $this->ownerRef($request)), 403);

        $messages = $channel->messages()
            ->whereNull('parent_id')
            ->with('replies')
            ->orderBy('created_at')
            ->paginate(50);

        return view('meet.channels.show', compact('channel', 'messages'));
    }

    public function postMessage(Request $request, Channel $channel): RedirectResponse|JsonResponse
    {
        $this->authorizeAbility($request, 'meetings.view');
        $this->authorizeOwner($request, $channel);

        $validated = $request->validate([
            'body' => ['required', 'string', 'max:5000'],
            'parent_id' => ['nullable', 'integer', 'exists:meet_channel_messages,id'],
        ]);

        $message = $this->channels->postMessage(
            $channel,
            $request->user(),
            $validated['body'],
            $validated['parent_id'] ?? null,
        );

        if ($request->expectsJson()) {
            return response()->json(['message' => $message]);
        }

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

    public function react(Request $request, Channel $channel, ChannelMessage $message): JsonResponse
    {
        $this->authorizeOwner($request, $channel);
        abort_unless($message->channel_id === $channel->id, 404);

        $validated = $request->validate(['emoji' => ['required', 'string', 'max:16']]);

        return response()->json([
            'message' => $this->channels->react($message, $validated['emoji'], $this->ownerRef($request)),
        ]);
    }

    public function search(Request $request): JsonResponse
    {
        $this->authorizeAbility($request, 'meetings.view');
        $validated = $request->validate(['q' => ['required', 'string', 'min:2', 'max:100']]);

        return response()->json(
            $this->search->search(
                $this->organization($request),
                $this->ownerRef($request),
                $validated['q'],
            ),
        );
    }
}
