<?php

namespace App\Http\Controllers;

use App\Http\Resources\TeamResource;
use App\Models\Member;
use App\Models\Team;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class MemberController extends Controller
{
    private const MIN_MEMBERS = 2;

    private function normalizeName(string $raw): string
    {
        return mb_convert_case(trim(preg_replace('/\s+/', ' ', $raw)), MB_CASE_TITLE, 'UTF-8');
    }

    public function store(Request $request, Team $team): JsonResponse
    {
        $request->merge(['name' => $this->normalizeName((string) $request->input('name', ''))]);

        $data = $request->validate([
            'name' => [
                'required', 'string', 'max:120',
                Rule::unique('members')->where('team_id', $team->id)->whereNull('deleted_at'),
            ],
        ]);

        // If a soft-deleted member with the same name exists on this team, restore it.
        $existing = Member::withTrashed()->where('team_id', $team->id)->where('name', $data['name'])->first();
        if ($existing && $existing->trashed()) {
            $existing->restore();
            $existing->touch();
            $member = $existing;
        } else {
            $member = $team->members()->create(['name' => $data['name']]);
        }

        if (! $team->captain_id) {
            $team->captain_id = $member->id;
            $team->save();
        }

        return response()->json([
            'member' => ['id' => $member->id, 'name' => $member->name],
            'team' => new TeamResource($team->fresh(['members', 'captain', 'oneTimeCompletions'])),
        ], 201);
    }

    public function update(Request $request, Member $member): JsonResponse
    {
        $request->merge(['name' => $this->normalizeName((string) $request->input('name', ''))]);

        $data = $request->validate([
            'name' => [
                'required', 'string', 'max:120',
                Rule::unique('members')->where('team_id', $member->team_id)->ignore($member->id)->whereNull('deleted_at'),
            ],
        ]);

        $member->name = $data['name'];
        $member->save();

        return response()->json(['member' => ['id' => $member->id, 'name' => $member->name]]);
    }

    public function destroy(Member $member): JsonResponse
    {
        $team = $member->team;

        if ($team->members()->count() <= self::MIN_MEMBERS) {
            return response()->json(['message' => 'Team must keep at least '.self::MIN_MEMBERS.' members.'], 422);
        }

        if ($team->captain_id === $member->id) {
            $team->captain_id = $team->members()->where('id', '!=', $member->id)->value('id');
            $team->save();
        }

        $member->delete();

        return response()->json(['data' => new TeamResource($team->fresh(['members', 'captain', 'oneTimeCompletions']))]);
    }

    public function move(Request $request, Member $member): JsonResponse
    {
        $data = $request->validate([
            'to_team_id' => ['required', 'integer', 'different:'.$member->team_id, Rule::exists('teams', 'id')],
        ]);

        $sourceTeam = $member->team;
        if ($sourceTeam->captain_id === $member->id) {
            return response()->json(['message' => $member->name.' is the captain — assign another captain before moving.'], 422);
        }
        if ($sourceTeam->members()->count() <= self::MIN_MEMBERS) {
            return response()->json(['message' => 'Source team must keep at least '.self::MIN_MEMBERS.' members.'], 422);
        }

        $destTeam = Team::findOrFail($data['to_team_id']);

        $conflict = Member::withTrashed()->where('team_id', $destTeam->id)->where('name', $member->name)->first();
        if ($conflict && ! $conflict->trashed()) {
            return response()->json(['message' => 'A member with that name already exists in the destination team.'], 422);
        }
        if ($conflict && $conflict->trashed()) {
            $conflict->forceDelete(); // free the unique slot for the move
        }

        if ($sourceTeam->captain_id === $member->id) {
            $sourceTeam->captain_id = $sourceTeam->members()->where('id', '!=', $member->id)->value('id');
            $sourceTeam->save();
        }

        $member->team_id = $destTeam->id;
        $member->save();

        return response()->json([
            'source' => new TeamResource($sourceTeam->fresh(['members', 'captain', 'oneTimeCompletions'])),
            'destination' => new TeamResource($destTeam->fresh(['members', 'captain', 'oneTimeCompletions'])),
        ]);
    }
}
