<?php

declare(strict_types=1);

namespace App\Http\Controllers\Studio;

use App\Http\Controllers\Controller;
use App\Http\Requests\Groups\AttachArtworkToGroupReleaseRequest;
use App\Http\Requests\Groups\AttachContributorToGroupReleaseRequest;
use App\Http\Requests\Groups\StoreGroupMilestoneRequest;
use App\Http\Requests\Groups\StoreGroupReleaseRequest;
use App\Http\Requests\Groups\UpdateGroupMilestoneRequest;
use App\Http\Requests\Groups\UpdateGroupReleaseRequest;
use App\Http\Requests\Groups\UpdateGroupReleaseStageRequest;
use App\Models\Artwork;
use App\Models\Group;
use App\Models\GroupRelease;
use App\Models\GroupReleaseMilestone;
use App\Models\User;
use App\Services\GroupReleaseService;
use App\Services\GroupService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class GroupReleaseStudioController extends Controller
{
    public function __construct(
        private readonly GroupService $groups,
        private readonly GroupReleaseService $releases,
    ) {
    }

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

        return Inertia::render('Studio/StudioGroupReleases', [
            'title' => $group->name . ' Releases',
            'description' => 'Manage release pipelines, contributors, and publication stages for major group drops.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
            'listing' => $this->releases->studioListing($group, $request->only(['bucket', 'page', 'per_page'])),
            'createUrl' => route('studio.groups.releases.create', ['group' => $group]),
        ]);
    }

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

        return Inertia::render('Studio/StudioGroupReleaseEditor', [
            'title' => 'Create release',
            'description' => 'Build a release page and move it from concept through publishing.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
            'release' => null,
            'statusOptions' => collect((array) config('groups.releases.statuses', []))->map(fn (string $value): array => ['value' => $value, 'label' => str_replace('_', ' ', ucfirst($value))])->values()->all(),
            'stageOptions' => collect((array) config('groups.releases.stages', []))->map(fn (string $value): array => ['value' => $value, 'label' => ucfirst($value)])->values()->all(),
            'visibilityOptions' => collect((array) config('groups.releases.visibility_options', []))->map(fn (string $value): array => ['value' => $value, 'label' => ucfirst($value)])->values()->all(),
            'memberOptions' => $this->releases->memberOptions($group->loadMissing('owner.profile')),
            'projectOptions' => $group->projects()->orderBy('title')->get(['id', 'title'])->map(fn ($project): array => ['id' => (int) $project->id, 'title' => $project->title])->values()->all(),
            'collectionOptions' => $group->collections()->orderBy('title')->get(['id', 'title'])->map(fn ($collection): array => ['id' => (int) $collection->id, 'title' => $collection->title])->values()->all(),
            'artworkOptions' => $group->artworks()->whereNull('deleted_at')->latest('updated_at')->limit(30)->get(['id', 'title'])->map(fn ($artwork): array => ['id' => (int) $artwork->id, 'title' => $artwork->title])->values()->all(),
            'storeUrl' => route('studio.groups.releases.store', ['group' => $group]),
        ]);
    }

    public function store(StoreGroupReleaseRequest $request, Group $group): RedirectResponse
    {
        $this->authorize('manageReleases', $group);

        $release = $this->releases->create($group, $request->user(), $request->validated());

        return redirect()->route('studio.groups.releases.show', ['group' => $group, 'release' => $release])
            ->with('success', 'Release created.');
    }

    public function show(Request $request, Group $group, GroupRelease $release): Response
    {
        $this->authorize('manageReleases', $group);
        abort_unless((int) $release->group_id === (int) $group->id, 404);

        return Inertia::render('Studio/StudioGroupReleaseEditor', [
            'title' => 'Edit release',
            'description' => 'Update the release story, stage, contributors, and publish plan.',
            'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
            'release' => $this->releases->detailPayload($release, $request->user()),
            'statusOptions' => collect((array) config('groups.releases.statuses', []))->map(fn (string $value): array => ['value' => $value, 'label' => str_replace('_', ' ', ucfirst($value))])->values()->all(),
            'stageOptions' => collect((array) config('groups.releases.stages', []))->map(fn (string $value): array => ['value' => $value, 'label' => ucfirst($value)])->values()->all(),
            'visibilityOptions' => collect((array) config('groups.releases.visibility_options', []))->map(fn (string $value): array => ['value' => $value, 'label' => ucfirst($value)])->values()->all(),
            'memberOptions' => $this->releases->memberOptions($group->loadMissing('owner.profile')),
            'projectOptions' => $group->projects()->orderBy('title')->get(['id', 'title'])->map(fn ($project): array => ['id' => (int) $project->id, 'title' => $project->title])->values()->all(),
            'collectionOptions' => $group->collections()->orderBy('title')->get(['id', 'title'])->map(fn ($collection): array => ['id' => (int) $collection->id, 'title' => $collection->title])->values()->all(),
            'artworkOptions' => $group->artworks()->whereNull('deleted_at')->latest('updated_at')->limit(30)->get(['id', 'title'])->map(fn ($artwork): array => ['id' => (int) $artwork->id, 'title' => $artwork->title])->values()->all(),
            'updateUrl' => route('studio.groups.releases.update', ['group' => $group, 'release' => $release]),
            'stageUrl' => route('studio.groups.releases.stage', ['group' => $group, 'release' => $release]),
            'publishUrl' => route('studio.groups.releases.publish', ['group' => $group, 'release' => $release]),
            'attachArtworkUrl' => route('studio.groups.releases.attach-artwork', ['group' => $group, 'release' => $release]),
            'attachContributorUrl' => route('studio.groups.releases.attach-contributor', ['group' => $group, 'release' => $release]),
            'storeMilestoneUrl' => route('studio.groups.releases.milestones.store', ['group' => $group, 'release' => $release]),
            'updateMilestonePattern' => route('studio.groups.releases.milestones.update', ['group' => $group, 'release' => $release, 'milestone' => '__MILESTONE__']),
        ]);
    }

    public function update(UpdateGroupReleaseRequest $request, Group $group, GroupRelease $release): RedirectResponse
    {
        $this->authorize('manageReleases', $group);
        abort_unless((int) $release->group_id === (int) $group->id, 404);

        $this->releases->update($release, $request->user(), $request->validated());

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

    public function stage(UpdateGroupReleaseStageRequest $request, Group $group, GroupRelease $release): RedirectResponse
    {
        $this->authorize('moveReleaseStage', $group);
        abort_unless((int) $release->group_id === (int) $group->id, 404);

        $this->releases->updateStage($release, $request->user(), (string) $request->validated('current_stage'));

        return back()->with('success', 'Release stage updated.');
    }

    public function publish(Request $request, Group $group, GroupRelease $release): RedirectResponse
    {
        $this->authorize('publishReleases', $group);
        abort_unless((int) $release->group_id === (int) $group->id, 404);

        $this->releases->publish($release, $request->user());

        return back()->with('success', 'Release published.');
    }

    public function attachArtwork(AttachArtworkToGroupReleaseRequest $request, Group $group, GroupRelease $release): RedirectResponse
    {
        $this->authorize('manageReleases', $group);
        abort_unless((int) $release->group_id === (int) $group->id, 404);

        $artwork = Artwork::query()->findOrFail((int) $request->validated('artwork_id'));
        $this->releases->attachArtwork($release, $artwork, $request->user());

        return back()->with('success', 'Artwork attached to release.');
    }

    public function attachContributor(AttachContributorToGroupReleaseRequest $request, Group $group, GroupRelease $release): RedirectResponse
    {
        $this->authorize('manageReleases', $group);
        abort_unless((int) $release->group_id === (int) $group->id, 404);

        $contributor = User::query()->findOrFail((int) $request->validated('user_id'));
        $this->releases->attachContributor($release, $contributor, $request->user(), $request->validated('role_label'));

        return back()->with('success', 'Contributor attached to release.');
    }

    public function storeMilestone(StoreGroupMilestoneRequest $request, Group $group, GroupRelease $release): RedirectResponse
    {
        $this->authorize('manageMilestones', $group);
        abort_unless((int) $release->group_id === (int) $group->id, 404);

        $this->releases->createMilestone($release, $request->user(), $request->validated());

        return back()->with('success', 'Release milestone created.');
    }

    public function updateMilestone(UpdateGroupMilestoneRequest $request, Group $group, GroupRelease $release, GroupReleaseMilestone $milestone): RedirectResponse
    {
        $this->authorize('manageMilestones', $group);
        abort_unless((int) $release->group_id === (int) $group->id, 404);
        abort_unless((int) $milestone->group_release_id === (int) $release->id, 404);

        $this->releases->updateMilestone($milestone, $request->user(), $request->validated());

        return back()->with('success', 'Release milestone updated.');
    }
}