<?php

declare(strict_types=1);

namespace App\Http\Controllers\Studio;

use App\Http\Controllers\Controller;
use App\Http\Requests\Groups\StoreGroupRequest;
use App\Http\Requests\Groups\UpdateGroupRequest;
use App\Models\Group;
use App\Services\GroupMembershipService;
use App\Services\GroupService;
use App\Services\GroupArtworkReviewService;
use App\Services\GroupJoinRequestService;
use App\Services\GroupReputationService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class GroupStudioController extends Controller
{
    public function __construct(
        private readonly GroupService $groups,
        private readonly GroupMembershipService $memberships,
        private readonly GroupJoinRequestService $joinRequests,
        private readonly GroupArtworkReviewService $artworkReviews,
        private readonly GroupReputationService $reputation,
    ) {
    }

    public function index(Request $request): Response
    {
        $user = $request->user();

        $groups = Group::query()
            ->with(['owner.profile', 'members'])
            ->where(function ($query) use ($user): void {
                $query->where('owner_user_id', $user->id)
                    ->orWhereHas('members', function ($memberQuery) use ($user): void {
                        $memberQuery->where('user_id', $user->id)
                            ->where('status', Group::STATUS_ACTIVE);
                    });
            })
            ->orderBy('name')
            ->get()
            ->map(fn (Group $group): array => $this->groups->mapGroupCard($group, $user))
            ->values()
            ->all();

        return Inertia::render('Studio/StudioGroupsIndex', [
            'title' => 'Groups',
            'description' => 'Create collective publishing identities, manage memberships, and switch into shared artwork and collection workflows.',
            'groups' => $groups,
            'pendingInvites' => $this->memberships->pendingInvitationsForUser($user),
            'endpoints' => [
                'create' => route('studio.groups.create'),
            ],
        ]);
    }

    public function create(): Response
    {
        $this->authorize('create', Group::class);

        return Inertia::render('Studio/StudioGroupCreate', [
            'title' => 'Create Group',
            'description' => 'Set up a shared publishing identity for collaborative uploads and collections.',
            'visibilityOptions' => [
                ['value' => Group::VISIBILITY_PUBLIC, 'label' => 'Public'],
                ['value' => Group::VISIBILITY_UNLISTED, 'label' => 'Unlisted'],
                ['value' => Group::VISIBILITY_PRIVATE, 'label' => 'Private'],
            ],
            'membershipPolicyOptions' => [
                ['value' => Group::MEMBERSHIP_INVITE_ONLY, 'label' => 'Invite only'],
            ],
            'endpoints' => [
                'store' => route('studio.groups.store'),
            ],
        ]);
    }

    public function store(StoreGroupRequest $request): RedirectResponse
    {
        $this->authorize('create', Group::class);

        $group = $this->groups->createGroup($request->user(), $request->validated());

        return redirect()->route('studio.groups.show', ['group' => $group]);
    }

    public function show(Request $request, Group $group): Response
    {
        $this->authorize('viewStudio', $group);

        $viewer = $request->user();

        return Inertia::render('Studio/StudioGroupDashboard', [
            'title' => $group->name,
            'description' => $group->headline ?: 'Shared publishing overview for this group.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $viewer),
            'dashboard' => $this->groups->studioDashboardSummary($group),
            'draftsPendingAction' => $this->groups->studioArtworkPreviewItems($group, 'drafts', 4),
            'recentArtworks' => $this->groups->studioArtworkPreviewItems($group, 'published', 6),
            'recentCollections' => $this->groups->studioCollectionPreviewItems($group, 4),
            'members' => $this->memberships->mapMembers($group, $viewer),
            'recentPosts' => $this->groups->recentPostCards($group, 3),
            'recentProjects' => $this->groups->recentProjectCards($group, $viewer, 3),
            'recentReleases' => $this->groups->recentReleaseCards($group, $viewer, 3),
            'recentChallenges' => $this->groups->recentChallengeCards($group, $viewer, 3),
            'recentEvents' => $this->groups->recentEventCards($group, $viewer, 3),
            'recentActivity' => $this->groups->studioActivityFeed($group, $viewer, 8),
            'recruitment' => $this->groups->recruitmentPayload($group),
            'reputationSummary' => $this->reputation->summary($group),
            'trustSignals' => $this->reputation->trustSignals($group),
            'pendingJoinRequests' => $group->canReviewJoinRequests($viewer)
                ? $this->joinRequests->mapRequests($group, $viewer, ['bucket' => 'pending', 'per_page' => 4])['items']
                : [],
            'reviewQueuePreview' => $this->artworkReviews->listing($group, $viewer, ['bucket' => 'submitted', 'per_page' => 4])['items'],
            'recentHistory' => $this->groups->recentHistory($group, 6),
        ]);
    }

    public function artworks(Request $request, Group $group): Response
    {
        $this->authorize('viewStudio', $group);

        return Inertia::render('Studio/StudioGroupArtworks', [
            'title' => $group->name . ' Artworks',
            'description' => 'Browse every artwork published through this shared identity.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
            'listing' => $this->groups->studioArtworkListing($group, $request->only(['bucket', 'q', 'page', 'per_page'])),
            'uploadUrl' => route('upload', ['group' => $group->slug]),
        ]);
    }

    public function collections(Request $request, Group $group): Response
    {
        $this->authorize('viewStudio', $group);

        return Inertia::render('Studio/StudioGroupCollections', [
            'title' => $group->name . ' Collections',
            'description' => 'Manage collections published under this group identity.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
            'listing' => $this->groups->studioCollectionListing($group, $request->only(['bucket', 'q', 'page', 'per_page'])),
            'createUrl' => route('settings.collections.create', ['group' => $group->slug]),
        ]);
    }

    public function members(Request $request, Group $group): Response
    {
        $this->authorize('viewStudio', $group);
        $viewer = $request->user();
        $canManageMembers = $group->canManageMembers($viewer);

        return Inertia::render('Studio/StudioGroupMembers', [
            'title' => $group->name . ' Members',
            'description' => 'Invite, remove, and promote the people who can publish and curate under this group.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $viewer),
            'members' => $this->memberships->mapMembers($group, $viewer),
            'canManageMembers' => $canManageMembers,
            'permissionOverrideOptions' => array_map(static fn (string $permission): array => [
                'value' => $permission,
                'label' => str_replace('_', ' ', $permission),
            ], Group::allowedPermissionOverrides()),
            'endpoints' => $canManageMembers ? [
                'invite' => route('studio.groups.members.store', ['group' => $group]),
                'invitations' => route('studio.groups.invitations', ['group' => $group]),
                'updatePattern' => route('studio.groups.members.update', ['group' => $group, 'member' => '__MEMBER__']),
                'permissionsPattern' => route('studio.groups.members.permissions.update', ['group' => $group, 'member' => '__MEMBER__']),
                'transferPattern' => route('studio.groups.members.transfer', ['group' => $group, 'member' => '__MEMBER__']),
                'deletePattern' => route('studio.groups.members.destroy', ['group' => $group, 'member' => '__MEMBER__']),
            ] : null,
        ]);
    }

    public function invitations(Request $request, Group $group): Response
    {
        $this->authorize('manageMembers', $group);

        return Inertia::render('Studio/StudioGroupInvitations', [
            'title' => $group->name . ' Invitations',
            'description' => 'Manage outstanding invites, resend collaboration roles, and review recent invite history for this group.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
            'members' => $this->memberships->mapMembers($group, $request->user()),
            'invitations' => $this->memberships->mapInvitations($group, $request->user()),
            'endpoints' => [
                'invite' => route('studio.groups.members.store', ['group' => $group]),
                'deletePattern' => route('studio.groups.invitations.destroy', ['group' => $group, 'invitation' => '__INVITATION__']),
            ],
        ]);
    }

    public function settings(Request $request, Group $group): Response
    {
        $this->authorize('update', $group);

        return Inertia::render('Studio/StudioGroupSettings', [
            'title' => $group->name . ' Settings',
            'description' => 'Update the public presentation and collaboration defaults for this group.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
            'featuredArtworkOptions' => $this->groups->studioFeaturedArtworkOptions($group),
            'visibilityOptions' => [
                ['value' => Group::VISIBILITY_PUBLIC, 'label' => 'Public'],
                ['value' => Group::VISIBILITY_UNLISTED, 'label' => 'Unlisted'],
                ['value' => Group::VISIBILITY_PRIVATE, 'label' => 'Private'],
            ],
            'membershipPolicyOptions' => [
                ['value' => Group::MEMBERSHIP_INVITE_ONLY, 'label' => 'Invite only'],
            ],
            'endpoints' => [
                'update' => route('studio.groups.update', ['group' => $group]),
                'archive' => route('studio.groups.archive', ['group' => $group]),
            ],
        ]);
    }

    public function update(UpdateGroupRequest $request, Group $group): RedirectResponse
    {
        $this->authorize('update', $group);

        $group = $this->groups->updateGroup($group, $request->validated(), $request->user());

        return redirect()->route('studio.groups.settings', ['group' => $group]);
    }

    public function archive(Request $request, Group $group): RedirectResponse
    {
        $this->authorize('archive', $group);

        $group = $this->groups->archiveGroup($group, $request->user());

        return redirect()->route('studio.groups.settings', ['group' => $group]);
    }
}