<?php

namespace App\Http\Controllers;

use App\Concerns\AuthorizesPermissions;
use App\Concerns\HasWorkspaceScope;
use App\Enums\Permission;
use App\Enums\WorkspaceUserRole;
use App\Http\Requests\InviteTeamMemberRequest;
use App\Http\Requests\UpdatePermissionsRequest;
use App\Http\Requests\UpdateTeamMemberRoleRequest;
use App\Mail\TeamInvitationMail;
use App\Models\TeamInvitation;
use App\Models\User;
use App\Models\WorkspaceUser;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Inertia\Inertia;
use Inertia\Response;

class TeamController extends Controller
{
    use AuthorizesPermissions;
    use HasWorkspaceScope;

    /**
     * Display the team management page.
     */
    public function index(): Response
    {
        $workspaceUser = auth()->user()->currentWorkspaceUser();

        // Block Workers entirely — team page is Owner/Manager only
        if ($workspaceUser->role->is(WorkspaceUserRole::Worker)) {
            abort(404);
        }

        $workspace = $this->currentWorkspace();

        $isOwner = $workspaceUser->role->is(WorkspaceUserRole::Owner);

        // Load members with pivot data
        $members = $workspace->users()
            ->withPivot('id', 'role', 'permissions', 'created_at')
            ->get()
            ->map(function ($user) use ($isOwner) {
                $pivotRole = $user->pivot->role;
                $role = $pivotRole?->value ?? $pivotRole;
                $data = [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                    'role' => $role,
                    'joined_at' => $user->pivot->created_at,
                    'status' => 'active',
                    'workspace_user_id' => $user->pivot->id,
                    'updateRoleUrl' => route('team.updateRole', $user->pivot->id),
                    'removeUrl' => route('team.remove', $user->pivot->id),
                ];

                // Add permissions data for Manager members (only visible to Owners)
                if ($pivotRole instanceof WorkspaceUserRole && $pivotRole->is(WorkspaceUserRole::Manager) && $isOwner) {
                    $data['permissions'] = $user->pivot->permissions ?? [];
                    $data['permissionsUrl'] = route('team.updatePermissions', $user->pivot->id);
                }

                return $data;
            });

        // Load pending invitations
        $pendingInvitations = TeamInvitation::where('workspace_id', $workspace->id)
            ->whereNull('accepted_at')
            ->where('expires_at', '>', now())
            ->get()
            ->map(fn ($inv) => [
                'id' => $inv->id,
                'email' => $inv->email,
                'role' => $inv->role,
                'invited_at' => $inv->created_at,
                'status' => 'pending',
            ]);

        // Can manage team: Owner always, Manager checks permission
        $canManageTeam = $workspaceUser->role->is(WorkspaceUserRole::Owner)
            || ($workspaceUser->permissions[Permission::CanManageTeam] ?? false);

        return Inertia::render('team/Index', [
            'members' => $members,
            'pendingInvitations' => $pendingInvitations,
            'canManageTeam' => $canManageTeam,
            'isOwner' => $isOwner,
            'availablePermissions' => $isOwner ? $this->permissionLabels() : [],
            'authUserId' => auth()->id(),
            'inviteUrl' => route('team.invite'),
            'roles' => $this->roleLabels(),
        ]);
    }

    /**
     * Invite a new team member.
     */
    public function invite(InviteTeamMemberRequest $request): RedirectResponse
    {
        $workspace = $this->currentWorkspace();

        $invitation = TeamInvitation::create([
            'workspace_id' => $workspace->id,
            'email' => $request->validated('email'),
            'role' => $request->validated('role'),
            'invited_by' => auth()->id(),
            'expires_at' => now()->addDays(7),
        ]);

        Mail::to($invitation->email)->send(new TeamInvitationMail($workspace, $invitation));

        return redirect()->back()->with('success', 'Invitation envoyée');
    }

    /**
     * Update a team member's role.
     */
    public function updateRole(UpdateTeamMemberRoleRequest $request, int $workspaceUserId): RedirectResponse
    {
        $this->authorizePermission(Permission::CanManageTeam);

        $workspaceUser = WorkspaceUser::where('id', $workspaceUserId)
            ->where('workspace_id', session('current_workspace_id'))
            ->firstOrFail();

        if ($workspaceUser->role->is(WorkspaceUserRole::Owner)) {
            abort(404);
        }

        if ($workspaceUser->user_id === auth()->id()) {
            abort(404);
        }

        $oldRole = $workspaceUser->role->value;
        $newRole = $request->validated('role');

        DB::transaction(function () use ($workspaceUser, $oldRole, $newRole) {
            $workspaceUser->update([
                'role' => $newRole,
                'permissions' => config("permissions.defaults.{$newRole}", []),
            ]);

            $targetUser = User::findOrFail($workspaceUser->user_id);
            activity()
                ->performedOn($workspaceUser)
                ->withProperties([
                    'target_user' => $targetUser->name,
                    'old_role' => $oldRole,
                    'new_role' => $newRole,
                ])
                ->log('role_changed');
        });

        return redirect()->back()->with('success', 'Rôle mis à jour');
    }

    /**
     * Update a Manager's individual permissions.
     */
    public function updatePermissions(UpdatePermissionsRequest $request, int $workspaceUserId): RedirectResponse
    {
        $workspaceUser = WorkspaceUser::where('id', $workspaceUserId)
            ->where('workspace_id', session('current_workspace_id'))
            ->firstOrFail();

        // Only Manager permissions can be toggled
        if (! $workspaceUser->role->is(WorkspaceUserRole::Manager)) {
            abort(404);
        }

        $newPermissions = $request->validated('permissions');

        DB::transaction(function () use ($workspaceUser, $newPermissions) {
            $oldPermissions = $workspaceUser->permissions ?? [];

            $workspaceUser->update([
                'permissions' => $newPermissions,
            ]);

            $targetUser = User::findOrFail($workspaceUser->user_id);
            activity()
                ->performedOn($workspaceUser)
                ->withProperties([
                    'target_user' => $targetUser->name,
                    'old_permissions' => $oldPermissions,
                    'new_permissions' => $newPermissions,
                ])
                ->log('permissions_updated');
        });

        return redirect()->back()->with('success', 'Permissions mises à jour');
    }

    /**
     * Remove a team member from the workspace.
     */
    public function remove(int $workspaceUserId): RedirectResponse
    {
        $this->authorizePermission(Permission::CanManageTeam);

        $workspaceUser = WorkspaceUser::where('id', $workspaceUserId)
            ->where('workspace_id', session('current_workspace_id'))
            ->firstOrFail();

        if ($workspaceUser->role->is(WorkspaceUserRole::Owner)) {
            abort(404);
        }

        if ($workspaceUser->user_id === auth()->id()) {
            abort(404);
        }

        $targetUser = User::findOrFail($workspaceUser->user_id);

        DB::transaction(function () use ($workspaceUser, $targetUser) {
            $workspaceUser->delete();

            activity()
                ->withProperties([
                    'target_user' => $targetUser->name,
                    'target_email' => $targetUser->email,
                    'role' => $workspaceUser->role->value,
                ])
                ->log('member_removed');
        });

        return redirect()->back()->with('success', 'Membre retiré');
    }

    /**
     * Get role labels for the frontend.
     *
     * @return array<string, string>
     */
    protected function roleLabels(): array
    {
        return [
            'manager' => 'Gestionnaire',
            'worker' => 'Collaborateur',
        ];
    }

    /**
     * Get permission labels (French) for the frontend.
     *
     * @return array<string, string>
     */
    protected function permissionLabels(): array
    {
        return [
            Permission::CanManageTeam => "Gérer l'équipe",
            Permission::CanViewActivityLogs => "Voir les journaux d'activité",
            Permission::CanConfigurePortal => 'Configurer le portail client',
        ];
    }
}
