import {useState} from 'react';
import {Link} from 'react-router-dom';
import {useMutation, useQuery} from '@tanstack/react-query';
import {toast} from 'sonner';
import {
    AlertTriangle,
    ChevronLeft,
    ChevronRight,
    Plus,
    User,
    UserRoundX,
    X,
} from 'lucide-react';
import {
    projectInviteUser,
    projectMembers,
    projectRemoveMember,
    projectUpdateMemberRole,
} from '@/client';
import {useProject} from '@/contexts';
import {Avatar, AvatarFallback, AvatarImage} from '@/components/ui/avatar';
import {Button} from '@/components/ui/button';
import {Input} from '@/components/ui/input';
import {Label} from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import {Spinner} from '@/components/ui/spinner';
import {getApiErrorMessage} from '@/lib/api-error';

const RoleBadge = ({role}: {role: string}) => {
    const colors: Record<string, string> = {
        Owner: 'bg-yellow-100 text-yellow-800 border-yellow-300 dark:bg-yellow-900/30 dark:text-yellow-400 dark:border-yellow-700',
        Admin: 'bg-blue-100 text-blue-800 border-blue-300 dark:bg-blue-900/30 dark:text-blue-400 dark:border-blue-700',
        Member: 'bg-gray-100 text-gray-700 border-gray-300 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600',
    };
    return (
        <span className={`inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium border ${colors[role] || colors.Member}`}>
            {role}
        </span>
    );
};

export function ProjectMembers() {
    const {project} = useProject();

    const [searchInput, setSearchInput] = useState('');
    const [page, setPage] = useState(1);
    const perPage = 10;

    const [inviteOpen, setInviteOpen] = useState(false);
    const [removeOpen, setRemoveOpen] = useState(false);
    const [memberToRemove, setMemberToRemove] = useState<{user_id: string; username: string} | null>(null);
    const [inviteEmail, setInviteEmail] = useState('');
    const [inviteRole, setInviteRole] = useState('Member');

    const currentRole = project?.role || 'Member';
    const canInvite = currentRole === 'Owner' || currentRole === 'Admin';
    const inviteRoleOptions =
        currentRole === 'Owner' ? ['Admin', 'Member'] : currentRole === 'Admin' ? ['Member'] : [];

    const {data: membersData, isLoading, isError, error, refetch} = useQuery({
        queryKey: ['projectMembers', project?.name, page, perPage],
        queryFn: async () => {
            const resp = await projectMembers({
                path: {project_name: project!.name},
                query: {page, per_page: perPage},
            });
            return resp.data?.data ?? null;
        },
        enabled: !!project?.name,
    });

    const members: {
        user_id: string;
        username: string;
        display_name?: string | null;
        avatar_url?: string | null;
        scope: string;
        joined_at?: string;
    }[] = membersData?.members || [];
    const total = membersData?.total || 0;

    const filteredMembers = searchInput.trim()
        ? members.filter(
              (m) =>
                  m.username.toLowerCase().includes(searchInput.trim().toLowerCase()) ||
                  (m.display_name || '').toLowerCase().includes(searchInput.trim().toLowerCase()),
          )
        : members;

    const updateRoleMutation = useMutation({
        mutationFn: async (vars: {user_id: string; scope: string}) => {
            await projectUpdateMemberRole({
                path: {project_name: project!.name},
                body: {user_id: vars.user_id, scope: vars.scope as 'Admin' | 'Member'},
            });
        },
        onSuccess: () => {
            toast.success('Role updated');
            refetch();
        },
        onError: (err: unknown) => {
            toast.error(
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                getApiErrorMessage(err, 'Failed to update role'),
            );
        },
    });

    const removeMemberMutation = useMutation({
        mutationFn: async (userId: string) => {
            await projectRemoveMember({
                path: {project_name: project!.name, user_id: userId},
            });
        },
        onSuccess: () => {
            toast.success('Member removed');
            setRemoveOpen(false);
            setMemberToRemove(null);
            refetch();
        },
        onError: (err: unknown) => {
            toast.error(
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                getApiErrorMessage(err, 'Failed to remove member'),
            );
        },
    });

    const inviteMutation = useMutation({
        mutationFn: async (vars: {email: string; scope: string}) => {
            await projectInviteUser({
                path: {project_name: project!.name},
                body: {email: vars.email, scope: vars.scope as 'Admin' | 'Member'},
            });
        },
        onSuccess: () => {
            toast.success('Invitation sent');
            setInviteEmail('');
            setInviteOpen(false);
        },
        onError: (err: unknown) => {
            toast.error(
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                getApiErrorMessage(err, 'Failed to send invitation'),
            );
        },
    });

    if (!project) return null;

    return (
        <div className="flex-1 overflow-auto">
            {/* ── Header bar ── */}
            <div className="border-b">
                <div className="flex items-center justify-between px-6 py-3">
                    {/* Breadcrumb */}
                    <div className="flex items-center gap-1.5 text-sm text-muted-foreground">
                        <Link to="/" className="hover:text-foreground transition-colors">
                            Projects
                        </Link>
                        <span>/</span>
                        <Link
                            to={`/project/${project.name}`}
                            className="hover:text-foreground font-medium transition-colors"
                        >
                            {project.name}
                        </Link>
                        <span>/</span>
                        <span className="text-foreground">Members</span>
                    </div>

                    {/* Controls */}
                    <div className="flex items-center gap-2">
                        <div className="relative">
                            <input
                                type="text"
                                value={searchInput}
                                onChange={(e) => {
                                    setSearchInput(e.target.value);
                                    setPage(1);
                                }}
                                onKeyDown={(e) => e.key === 'Enter' && setPage(1)}
                                placeholder="Search members…"
                                className="h-8 pl-8 pr-3 text-sm border rounded-md w-44 bg-background focus:outline-none focus:ring-2 focus:ring-ring"
                            />
                            <svg
                                className="absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground pointer-events-none"
                                fill="none"
                                viewBox="0 0 24 24"
                                stroke="currentColor"
                            >
                                <path
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                    strokeWidth={2}
                                    d="M21 21l-4.35-4.35M17 11A6 6 0 1 1 5 11a6 6 0 0 1 12 0z"
                                />
                            </svg>
                        </div>

                        {canInvite && (
                            <Button size="sm" onClick={() => setInviteOpen(true)}>
                                <Plus className="mr-1.5 h-3.5 w-3.5"/>
                                Invite
                            </Button>
                        )}
                    </div>
                </div>
            </div>

            {/* ── Stats row ── */}
            <div className="border-b px-6 py-3">
                <p className="text-sm text-muted-foreground font-semibold text-foreground">
                    {total} {total === 1 ? 'member' : 'members'}
                </p>
            </div>

            {/* ── Members table ── */}
            {isLoading ? (
                <div className="flex items-center justify-center h-48">
                    <Spinner/>
                </div>
            ) : isError ? (
                <div className="p-6">
                    <div className="rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-destructive text-sm flex items-center gap-2">
                        <AlertTriangle className="h-4 w-4 flex-shrink-0"/>
                        <strong>Error:</strong>{' '}
                        {error instanceof Error ? error.message : 'Failed to load members'}
                    </div>
                </div>
            ) : filteredMembers.length === 0 ? (
                <div className="flex flex-col items-center justify-center py-20 text-center">
                    <User className="mb-4 h-10 w-10 text-muted-foreground/40"/>
                    <p className="text-sm font-medium text-muted-foreground">
                        {searchInput ? 'No members match your search' : 'No members found'}
                    </p>
                    {searchInput && (
                        <button
                            onClick={() => setSearchInput('')}
                            className="mt-2 text-xs text-primary hover:underline"
                        >
                            Clear search
                        </button>
                    )}
                </div>
            ) : (
                <div className="overflow-x-auto">
                    <table className="w-full min-w-[560px]">
                        <thead>
                            <tr className="border-b bg-muted/30">
                                <th className="px-4 py-2.5 text-left text-xs font-medium text-muted-foreground">
                                    User
                                </th>
                                <th className="px-4 py-2.5 text-left text-xs font-medium text-muted-foreground w-28">
                                    Role
                                </th>
                                <th className="px-4 py-2.5 text-left text-xs font-medium text-muted-foreground w-36">
                                    Joined
                                </th>
                                <th className="px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-36">
                                    Actions
                                </th>
                            </tr>
                        </thead>
                        <tbody className="divide-y divide-border">
                            {filteredMembers.map((member) => {
                                const canChangeRole =
                                    (currentRole === 'Owner' && member.scope !== 'Owner') ||
                                    (currentRole === 'Admin' && member.scope === 'Member');

                                return (
                                    <tr key={member.user_id} className="hover:bg-muted/40 transition-colors">
                                        <td className="px-4 py-3.5">
                                            <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="text-sm font-medium">
                                                        {member.display_name || member.username}
                                                    </div>
                                                    <div className="text-xs text-muted-foreground">
                                                        @{member.username}
                                                    </div>
                                                </div>
                                            </div>
                                        </td>
                                        <td className="px-4 py-3.5">
                                            <RoleBadge role={member.scope}/>
                                        </td>
                                        <td className="px-4 py-3.5 text-xs text-muted-foreground">
                                            {member.joined_at
                                                ? new Date(member.joined_at).toLocaleDateString('en-US', {
                                                      year: 'numeric',
                                                      month: 'short',
                                                      day: 'numeric',
                                                  })
                                                : '—'}
                                        </td>
                                        <td className="px-4 py-3.5">
                                            <div className="flex items-center justify-end gap-2">
                                                {canChangeRole && (
                                                    <Select
                                                        onValueChange={(val) =>
                                                            updateRoleMutation.mutate({
                                                                user_id: member.user_id,
                                                                scope: val as string,
                                                            })
                                                        }
                                                        disabled={updateRoleMutation.isPending}
                                                    >
                                                        <SelectTrigger className="h-8 w-28">
                                                            <SelectValue/>
                                                        </SelectTrigger>
                                                        <SelectContent>
                                                            {(currentRole === 'Owner'
                                                                ? ['Admin', 'Member']
                                                                : ['Member']
                                                            ).map((r) => (
                                                                <SelectItem key={r} value={r}>
                                                                    {r}
                                                                </SelectItem>
                                                            ))}
                                                        </SelectContent>
                                                    </Select>
                                                )}
                                                {member.scope !== 'Owner' && (
                                                    <button
                                                        onClick={() => {
                                                            setMemberToRemove({
                                                                user_id: member.user_id,
                                                                username: member.username,
                                                            });
                                                            setRemoveOpen(true);
                                                        }}
                                                        className="p-1.5 text-muted-foreground hover:text-destructive transition-colors"
                                                    >
                                                        <UserRoundX className="h-4 w-4"/>
                                                    </button>
                                                )}
                                            </div>
                                        </td>
                                    </tr>
                                );
                            })}
                        </tbody>
                    </table>
                </div>
            )}

            {/* ── Pagination ── */}
            {filteredMembers.length > 0 && (
                <div className="flex items-center justify-between border-t px-6 py-4">
                    <p className="text-sm text-muted-foreground">
                        Showing {(page - 1) * perPage + 1}–{Math.min(page * perPage, total)} of{' '}
                        {total}
                    </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="mr-1 h-4 w-4"/>
                            Previous
                        </Button>
                        <span className="text-sm text-muted-foreground px-1">Page {page}</span>
                        <Button
                            variant="outline"
                            size="sm"
                            onClick={() => setPage((p) => p + 1)}
                            disabled={filteredMembers.length < perPage}
                        >
                            Next
                            <ChevronRight className="ml-1 h-4 w-4"/>
                        </Button>
                    </div>
                </div>
            )}

            {/* ── Invite Dialog ── */}
            {inviteOpen && (
                <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
                    <div className="w-full max-w-md rounded-xl border bg-background p-6 shadow-xl">
                        <div className="flex items-center justify-between mb-4">
                            <h3 className="text-sm font-semibold">Invite Member</h3>
                            <button
                                onClick={() => setInviteOpen(false)}
                                className="text-muted-foreground hover:text-foreground"
                            >
                                <X className="h-5 w-5"/>
                            </button>
                        </div>
                        <div className="space-y-4">
                            <div className="space-y-2">
                                <Label htmlFor="invite-email">Email</Label>
                                <Input
                                    id="invite-email"
                                    type="email"
                                    placeholder="teammate@example.com"
                                    value={inviteEmail}
                                    onChange={(e) => setInviteEmail(e.target.value)}
                                    disabled={inviteMutation.isPending}
                                />
                            </div>
                            <div className="space-y-2">
                                <Label htmlFor="invite-role">Role</Label>
                                <Select value={inviteRole} onValueChange={(v) => v && setInviteRole(v)}>
                                    <SelectTrigger>
                                        <SelectValue/>
                                    </SelectTrigger>
                                    <SelectContent>
                                        {inviteRoleOptions.map((r) => (
                                            <SelectItem key={r} value={r}>
                                                {r}
                                            </SelectItem>
                                        ))}
                                    </SelectContent>
                                </Select>
                            </div>
                        </div>
                        <div className="flex justify-end gap-2 mt-6">
                            <Button variant="outline" onClick={() => setInviteOpen(false)}>
                                Cancel
                            </Button>
                            <Button
                                onClick={() => {
                                    if (!inviteEmail.trim()) {
                                        toast.error('Email is required');
                                        return;
                                    }
                                    inviteMutation.mutate({email: inviteEmail, scope: inviteRole});
                                }}
                                disabled={inviteMutation.isPending}
                            >
                                {inviteMutation.isPending ? 'Sending…' : 'Send Invite'}
                            </Button>
                        </div>
                    </div>
                </div>
            )}

            {/* ── Remove Dialog ── */}
            {removeOpen && memberToRemove && (
                <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
                    <div className="w-full max-w-md rounded-xl border bg-background p-6 shadow-xl">
                        <div className="flex items-center gap-3 mb-4">
                            <AlertTriangle className="h-5 w-5 text-destructive"/>
                            <h3 className="text-sm font-semibold">Remove Member</h3>
                        </div>
                        <p className="text-sm text-muted-foreground">
                            Are you sure you want to remove{' '}
                            <strong>{memberToRemove.username}</strong> from this project?
                        </p>
                        <div className="flex justify-end gap-2 mt-6">
                            <Button variant="outline" onClick={() => setRemoveOpen(false)}>
                                Cancel
                            </Button>
                            <Button
                                variant="destructive"
                                onClick={() => removeMemberMutation.mutate(memberToRemove.user_id)}
                                disabled={removeMemberMutation.isPending}
                            >
                                {removeMemberMutation.isPending ? 'Removing…' : 'Remove'}
                            </Button>
                        </div>
                    </div>
                </div>
            )}
        </div>
    );
}
