import {useState, useMemo} from 'react';
import {useParams} from 'react-router-dom';
import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query';
import {
    workspaceMembers,
    workspacePendingInvitations,
    workspaceInviteMember,
    workspaceRemoveMember,
    workspaceUpdateMemberRole,
    workspaceCancelInvitation,
} from '@/client';
import {useWorkspace} from '@/contexts';
import {Avatar, AvatarFallback, AvatarImage} from '@/components/ui/avatar';
import {Badge} from '@/components/ui/badge';
import {Button} from '@/components/ui/button';
import {Input} from '@/components/ui/input';
import {Spinner} from '@/components/ui/spinner';
import {
    Dialog,
    DialogContent,
    DialogHeader,
    DialogTitle,
    DialogDescription,
    DialogFooter,
} from '@/components/ui/dialog';
import {toast} from 'sonner';
import {Search, X, ChevronLeft, ChevronRight, Clock, UserCog, Mail} from 'lucide-react';

const PAGE_SIZE = 20;

export function WorkspaceMembers() {
    const {currentWorkspace} = useWorkspace();
    const {workspace_slug} = useParams<{workspace_slug: string}>();
    const queryClient = useQueryClient();

    const isAdmin = currentWorkspace?.my_role?.toLowerCase() === 'owner' || currentWorkspace?.my_role?.toLowerCase() === 'admin';

    const [search, setSearch] = useState('');
    const [roleFilter, setRoleFilter] = useState<string>('all');
    const [page, setPage] = useState(1);
    const [inviteOpen, setInviteOpen] = useState(false);
    const [inviteEmail, setInviteEmail] = useState('');
    const [inviteRole, setInviteRole] = useState('Member');
    const [editingRole, setEditingRole] = useState<string | null>(null);

    const {data, isLoading, isFetching} = useQuery({
        queryKey: ['workspaceMembers', workspace_slug, page],
        queryFn: async () => {
            const resp = await workspaceMembers({
                path: {slug: workspace_slug!},
                query: {page, per_page: PAGE_SIZE},
            });
            return resp.data?.data ?? null;
        },
        enabled: !!workspace_slug,
    });

    const {data: pendingData} = useQuery({
        queryKey: ['workspacePendingInvitations', workspace_slug],
        queryFn: async () => {
            const resp = await workspacePendingInvitations({path: {slug: workspace_slug!}});
            return resp.data?.data ?? [];
        },
        enabled: !!workspace_slug && isAdmin,
    });

    const filteredMembers = useMemo(() => {
        if (!data?.members) return [];
        return data.members.filter((m) => {
            const matchSearch =
                !search ||
                m.username.toLowerCase().includes(search.toLowerCase()) ||
                (m.display_name ?? '').toLowerCase().includes(search.toLowerCase());
            const matchRole = roleFilter === 'all' || m.role.toLowerCase() === roleFilter;
            return matchSearch && matchRole;
        });
    }, [data, search, roleFilter]);

    const inviteMutation = useMutation({
        mutationFn: async () => {
            await workspaceInviteMember({
                path: {slug: workspace_slug!},
                body: {email: inviteEmail, role: inviteRole},
            });
        },
        onSuccess: () => {
            toast.success('Invitation sent to ' + inviteEmail);
            setInviteEmail('');
            setInviteRole('Member');
            setInviteOpen(false);
            queryClient.invalidateQueries({queryKey: ['workspaceMembers', workspace_slug]});
            queryClient.invalidateQueries({queryKey: ['workspacePendingInvitations', workspace_slug]});
        },
        onError: (err: Error) => {
            toast.error(err.message || 'Failed to send invitation');
        },
    });

    const removeMutation = useMutation({
        mutationFn: async (userId: string) => {
            await workspaceRemoveMember({path: {slug: workspace_slug!, user_id: userId}});
        },
        onSuccess: () => {
            toast.success('Member removed');
            queryClient.invalidateQueries({queryKey: ['workspaceMembers', workspace_slug]});
        },
        onError: (err: Error) => {
            toast.error(err.message || 'Failed to remove member');
        },
    });

    const cancelInviteMutation = useMutation({
        mutationFn: async (userId: string) => {
            await workspaceCancelInvitation({path: {slug: workspace_slug!, user_id: userId}});
        },
        onSuccess: () => {
            toast.success('Invitation cancelled');
            queryClient.invalidateQueries({queryKey: ['workspacePendingInvitations', workspace_slug]});
        },
        onError: (err: Error) => {
            toast.error(err.message || 'Failed to cancel invitation');
        },
    });

    const changeRoleMutation = useMutation({
        mutationFn: async ({userId, role}: {userId: string; role: string}) => {
            await workspaceUpdateMemberRole({
                path: {slug: workspace_slug!},
                body: {user_id: userId, role},
            });
        },
        onSuccess: () => {
            toast.success('Role updated');
            setEditingRole(null);
            queryClient.invalidateQueries({queryKey: ['workspaceMembers', workspace_slug]});
        },
        onError: (err: Error) => {
            toast.error(err.message || 'Failed to update role');
        },
    });

    const totalPages = data ? Math.ceil((data.total ?? 0) / PAGE_SIZE) : 1;

    if (isLoading) {
        return (
            <div className="flex items-center justify-center h-64">
                <Spinner />
            </div>
        );
    }

    return (
        <div className="flex-1 p-6 space-y-6">
            {/* Header */}
            <div className="flex items-center justify-between">
                <div>
                    <h1 className="text-xl font-semibold">
                        Members <span className="text-muted-foreground font-normal text-sm">({data?.total ?? 0})</span>
                    </h1>
                    {isAdmin && pendingData && pendingData.length > 0 && (
                        <p className="text-xs text-muted-foreground mt-0.5">
                            {pendingData.length} pending invitation{pendingData.length > 1 ? 's' : ''}
                        </p>
                    )}
                </div>
                {isAdmin && (
                    <Button size="sm" onClick={() => setInviteOpen(true)}>
                        Invite Member
                    </Button>
                )}
            </div>

            {isAdmin && (
                <Dialog open={inviteOpen} onOpenChange={setInviteOpen}>
                    <DialogContent className="sm:max-w-md">
                        <DialogHeader>
                            <DialogTitle className="flex items-center gap-2">
                                <div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10">
                                    <Mail className="h-4 w-4 text-primary" />
                                </div>
                                Invite to {currentWorkspace?.name}
                            </DialogTitle>
                            <DialogDescription>
                                They'll receive an email with a link to join this workspace.
                                Invitations expire in 7 days.
                            </DialogDescription>
                        </DialogHeader>

                        <div className="space-y-4 py-2">
                            <div className="space-y-2">
                                <label className="text-sm font-medium" htmlFor="invite-email">
                                    Email address
                                </label>
                                <Input
                                    id="invite-email"
                                    type="email"
                                    placeholder="colleague@example.com"
                                    value={inviteEmail}
                                    onChange={(e) => setInviteEmail(e.target.value)}
                                />
                            </div>

                            <div className="space-y-2">
                                <label className="text-sm font-medium" htmlFor="invite-role">
                                    Role
                                </label>
                                <select
                                    id="invite-role"
                                    className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
                                    value={inviteRole}
                                    onChange={(e) => setInviteRole(e.target.value)}
                                >
                                    <option value="Member">Member — can view and contribute to projects</option>
                                    <option value="Admin">Admin — can manage members and settings</option>
                                </select>
                                <p className="text-xs text-muted-foreground">
                                    {inviteRole === 'Admin'
                                        ? 'Admins can manage workspace settings, members, and billing.'
                                        : 'Members can create and manage projects assigned to this workspace.'}
                                </p>
                            </div>
                        </div>

                        <DialogFooter>
                            <Button
                                variant="outline"
                                onClick={() => setInviteOpen(false)}
                            >
                                Cancel
                            </Button>
                            <Button
                                onClick={() => inviteMutation.mutate()}
                                disabled={!inviteEmail || inviteMutation.isPending}
                            >
                                {inviteMutation.isPending ? 'Sending...' : 'Send Invitation'}
                            </Button>
                        </DialogFooter>
                    </DialogContent>
                </Dialog>
            )}

            {/* Pending invitations */}
            {isAdmin && pendingData && pendingData.length > 0 && (
                <div className="border rounded-lg overflow-hidden">
                    <div className="px-4 py-2.5 bg-amber-50 dark:bg-amber-950/30 border-b flex items-center gap-2">
                        <Clock className="h-4 w-4 text-amber-600 dark:text-amber-400" />
                        <span className="text-sm font-medium text-amber-800 dark:text-amber-200">
                            Pending Invitations
                        </span>
                    </div>
                    <div className="divide-y">
                        {pendingData.map((inv) => (
                            <div key={inv.user_id} className="flex items-center justify-between px-4 py-3">
                                <div className="flex items-center gap-3 min-w-0">
                                    <Avatar className="h-8 w-8">
                                        <AvatarImage src={inv.avatar_url ?? ''} />
                                        <AvatarFallback>{inv.username.charAt(0).toUpperCase()}</AvatarFallback>
                                    </Avatar>
                                    <div className="min-w-0">
                                        <div className="font-medium text-sm truncate">
                                            {inv.display_name || inv.username}
                                        </div>
                                        <div className="text-xs text-muted-foreground truncate">
                                            {inv.email ?? `@${inv.username}`}
                                        </div>
                                    </div>
                                </div>
                                <div className="flex items-center gap-3 shrink-0">
                                    <Badge variant="outline">{inv.role}</Badge>
                                    {inv.invited_by_username && (
                                        <span className="text-xs text-muted-foreground hidden sm:inline">
                                            by @{inv.invited_by_username}
                                        </span>
                                    )}
                                    {inv.expires_at && (
                                        <span className="text-xs text-muted-foreground hidden md:inline">
                                            expires {new Date(inv.expires_at).toLocaleDateString()}
                                        </span>
                                    )}
                                    <Button
                                        variant="ghost"
                                        size="sm"
                                        className="text-muted-foreground hover:text-destructive"
                                        onClick={() => cancelInviteMutation.mutate(inv.user_id)}
                                        disabled={cancelInviteMutation.isPending}
                                    >
                                        Cancel
                                    </Button>
                                </div>
                            </div>
                        ))}
                    </div>
                </div>
            )}

            {/* Filters */}
            <div className="flex items-center gap-3">
                <div className="relative flex-1 max-w-sm">
                    <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
                    <Input
                        placeholder="Search members..."
                        value={search}
                        onChange={(e) => { setSearch(e.target.value); setPage(1); }}
                        className="pl-9"
                    />
                </div>
                <select
                    className="border rounded-md px-3 py-2 text-sm bg-background"
                    value={roleFilter}
                    onChange={(e) => { setRoleFilter(e.target.value); setPage(1); }}
                >
                    <option value="all">All roles</option>
                    <option value="owner">Owner</option>
                    <option value="admin">Admin</option>
                    <option value="member">Member</option>
                </select>
            </div>

            {/* Members table */}
            <div className="border rounded-lg overflow-hidden">
                {isFetching && (
                    <div className="h-1 bg-muted overflow-hidden">
                        <div className="h-full bg-primary animate-pulse w-full" />
                    </div>
                )}
                <table className="w-full text-sm">
                    <thead>
                        <tr className="border-b bg-muted/50">
                            <th className="text-left px-4 py-3 font-medium">Member</th>
                            <th className="text-left px-4 py-3 font-medium">Role</th>
                            <th className="text-left px-4 py-3 font-medium hidden md:table-cell">Invited by</th>
                            <th className="text-left px-4 py-3 font-medium hidden sm:table-cell">Joined</th>
                            {isAdmin && <th className="px-4 py-3" />}
                        </tr>
                    </thead>
                    <tbody>
                        {filteredMembers.length === 0 ? (
                            <tr>
                                <td colSpan={5} className="px-4 py-8 text-center text-muted-foreground">
                                    {search || roleFilter !== 'all' ? 'No members match your filters' : 'No members yet'}
                                </td>
                            </tr>
                        ) : (
                            filteredMembers.map((member) => (
                                <tr
                                    key={member.user_id}
                                    className="border-b last:border-0 hover:bg-muted/30 transition-colors"
                                >
                                    <td className="px-4 py-3">
                                        <div className="flex items-center gap-3">
                                            <Avatar className="h-8 w-8">
                                                <AvatarImage src={member.avatar_url ?? ''} />
                                                <AvatarFallback>
                                                    {member.username.charAt(0).toUpperCase()}
                                                </AvatarFallback>
                                            </Avatar>
                                            <div>
                                                <div className="font-medium">
                                                    {member.display_name || member.username}
                                                </div>
                                                <div className="text-muted-foreground text-xs">
                                                    @{member.username}
                                                </div>
                                            </div>
                                        </div>
                                    </td>
                                    <td className="px-4 py-3">
                                        {isAdmin && member.role !== 'Owner' && editingRole === member.user_id ? (
                                            <div className="flex items-center gap-2">
                                                <select
                                                    className="border rounded px-2 py-1 text-xs"
                                                    defaultValue={member.role}
                                                    onChange={(e) =>
                                                        changeRoleMutation.mutate({
                                                            userId: member.user_id,
                                                            role: e.target.value,
                                                        })
                                                    }
                                                    autoFocus
                                                >
                                                    <option value="Member">Member</option>
                                                    <option value="Admin">Admin</option>
                                                </select>
                                                <Button
                                                    variant="ghost"
                                                    size="sm"
                                                    className="h-6 px-2"
                                                    onClick={() => setEditingRole(null)}
                                                >
                                                    <X className="h-3 w-3" />
                                                </Button>
                                            </div>
                                        ) : isAdmin && member.role !== 'Owner' ? (
                                            <button
                                                className="group inline-flex items-center gap-1"
                                                onClick={() => setEditingRole(member.user_id)}
                                            >
                                                <Badge variant="outline" className="cursor-pointer hover:border-primary group-hover:text-primary transition-colors">
                                                    {member.role}
                                                </Badge>
                                                <UserCog className="h-3 w-3 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" />
                                            </button>
                                        ) : (
                                            <Badge variant="outline">{member.role}</Badge>
                                        )}
                                    </td>
                                    <td className="px-4 py-3 text-muted-foreground text-sm hidden md:table-cell">
                                        {member.invited_by_username ? (
                                            <span>@{member.invited_by_username}</span>
                                        ) : (
                                            <span className="text-xs">—</span>
                                        )}
                                    </td>
                                    <td className="px-4 py-3 text-muted-foreground hidden sm:table-cell">
                                        {new Date(member.joined_at).toLocaleDateString()}
                                    </td>
                                    {isAdmin && (
                                        <td className="px-4 py-3 text-right">
                                            {member.role !== 'Owner' && (
                                                <Button
                                                    variant="ghost"
                                                    size="sm"
                                                    className="text-muted-foreground hover:text-destructive"
                                                    onClick={() => removeMutation.mutate(member.user_id)}
                                                    disabled={removeMutation.isPending}
                                                >
                                                    Remove
                                                </Button>
                                            )}
                                        </td>
                                    )}
                                </tr>
                            ))
                        )}
                    </tbody>
                </table>
            </div>

            {/* Pagination */}
            {totalPages > 1 && (
                <div className="flex items-center justify-between">
                    <p className="text-sm text-muted-foreground">
                        Page {page} of {totalPages}
                        {' — '}
                        {data?.total ?? 0} total members
                    </p>
                    <div className="flex items-center gap-2">
                        <Button
                            variant="outline"
                            size="sm"
                            onClick={() => setPage((p) => Math.max(1, p - 1))}
                            disabled={page <= 1}
                        >
                            <ChevronLeft className="h-4 w-4" />
                        </Button>
                        <Button
                            variant="outline"
                            size="sm"
                            onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                            disabled={page >= totalPages}
                        >
                            <ChevronRight className="h-4 w-4" />
                        </Button>
                    </div>
                </div>
            )}
        </div>
    );
}
