<?php

namespace App\Http\Controllers;

use App\Mail\TeamInvitationMail;
use App\Models\Team;
use App\Models\TeamInvitation;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\Response;

class WorkspaceController extends Controller
{
    public function members(): View
    {
        $team = Auth::user()->currentTeam;
        abort_unless($team, 404);

        $members = $team->members()->get();
        $owner = $team->owner;
        $invitations = TeamInvitation::where('team_id', $team->id)
            ->whereNull('accepted_at')
            ->latest()
            ->get();

        $isOwner = $team->owner_id === Auth::id();

        return view('workspace.members', compact('team', 'members', 'owner', 'invitations', 'isOwner'));
    }

    public function invite(Request $request): RedirectResponse
    {
        $team = Auth::user()->currentTeam;
        abort_unless($team && $team->owner_id === Auth::id(), 403);

        $data = $request->validate([
            'email' => ['required', 'email', 'max:255'],
            'role' => ['required', 'in:admin,member'],
        ]);

        if (User::where('email', $data['email'])->whereHas('teams', fn ($q) => $q->where('teams.id', $team->id))->exists()) {
            return back()->withErrors(['email' => 'This user is already a member.']);
        }

        if (TeamInvitation::where('team_id', $team->id)->where('email', $data['email'])->whereNull('accepted_at')->exists()) {
            return back()->withErrors(['email' => 'An invitation is already pending for this email.']);
        }

        $invitation = TeamInvitation::create([
            'team_id' => $team->id,
            'invited_by_user_id' => Auth::id(),
            'email' => $data['email'],
            'role' => $data['role'],
            'token' => Str::random(48),
            'expires_at' => now()->addDays(7),
        ]);

        Mail::to($data['email'])->queue(new TeamInvitationMail($invitation));

        return back()->with('toast', ['type' => 'success', 'message' => "Invitation sent to {$data['email']}."]);
    }

    public function revokeInvitation(TeamInvitation $invitation): RedirectResponse
    {
        $team = Auth::user()->currentTeam;
        abort_unless($team && $team->owner_id === Auth::id() && $invitation->team_id === $team->id, 403);

        $invitation->delete();

        return back()->with('toast', ['type' => 'success', 'message' => 'Invitation revoked.']);
    }

    public function removeMember(User $member): RedirectResponse
    {
        $team = Auth::user()->currentTeam;
        abort_unless($team && $team->owner_id === Auth::id(), 403);
        abort_if($member->id === $team->owner_id, 403, 'Cannot remove the workspace owner.');

        $team->members()->detach($member->id);

        // If their current_team_id is this team, reset it.
        if ($member->current_team_id === $team->id) {
            $personal = $member->ownedTeams()->where('personal', true)->first();
            $member->forceFill(['current_team_id' => $personal?->id])->save();
        }

        return back()->with('toast', ['type' => 'success', 'message' => "{$member->name} removed."]);
    }

    public function showInvitation(string $token): View|Response
    {
        $invitation = TeamInvitation::where('token', $token)->firstOrFail();

        if (! $invitation->isPending()) {
            return view('workspace.invitation-expired');
        }

        return view('workspace.invitation', compact('invitation'));
    }

    public function acceptInvitation(string $token): RedirectResponse
    {
        $invitation = TeamInvitation::where('token', $token)->firstOrFail();
        abort_unless($invitation->isPending(), 410, 'Invitation expired or already used.');

        $user = Auth::user();
        if (! $user || $user->email !== $invitation->email) {
            // Redirect to login with intended URL preserved
            return redirect()->guest(route('login'))->with('toast', [
                'type' => 'default',
                'message' => "Sign in as {$invitation->email} to accept the invitation.",
            ]);
        }

        DB::transaction(function () use ($invitation, $user) {
            $user->teams()->syncWithoutDetaching([
                $invitation->team_id => ['role' => $invitation->role],
            ]);
            $invitation->forceFill(['accepted_at' => now()])->save();
            $user->forceFill(['current_team_id' => $invitation->team_id])->save();
        });

        return redirect()->route('dashboard')->with('toast', [
            'type' => 'success',
            'message' => 'Welcome to '.$invitation->team->name.'.',
        ]);
    }

    public function switchTeam(Team $team): RedirectResponse
    {
        $user = Auth::user();
        if ($user->switchTeam($team)) {
            return back()->with('toast', ['type' => 'success', 'message' => 'Switched to '.$team->name.'.']);
        }
        abort(403);
    }
}
