import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Check, Plus, Settings, Users } from 'lucide-react';
import { toast } from 'sonner';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Small } from '@/components/ui/typography';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Separator } from '@/components/ui/separator';
import { useNetworks } from '@/hooks/use-networks';
import {
  useMyInvitations,
  useAcceptInvitation,
} from '@/hooks/use-member-management';
import { apiClient } from '@/api/client';
import { Progress } from '@/components/ui/progress';
import { toUserMessage } from '@/lib/errors';
import type { Network, Invitation } from '@/api/types';

function NetworkRow({
  network,
  onClick,
  onSettingsClick,
}: {
  network: Network;
  onClick: () => void;
  onSettingsClick: () => void;
}) {
  const initials = network.name.slice(0, 2).toUpperCase();
  const memberCount = network.humans.length;

  return (
    <button
      type="button"
      onClick={onClick}
      className="group flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-accent"
    >
      <Avatar>
        <AvatarFallback className="bg-primary/10 text-primary font-medium">
          {initials}
        </AvatarFallback>
      </Avatar>
      <div className="min-w-0 flex-1">
        <p className="truncate text-sm font-medium">{network.name}</p>
        <div className="text-muted-foreground flex items-center gap-1">
          <Users className="size-3" />
          <Small className="text-muted-foreground">
            {memberCount} {memberCount === 1 ? 'member' : 'members'}
          </Small>
        </div>
      </div>
      <span
        role="button"
        tabIndex={0}
        className="text-muted-foreground hover:text-foreground opacity-0 transition-opacity group-hover:opacity-100"
        onClick={(e) => {
          e.stopPropagation();
          onSettingsClick();
        }}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.stopPropagation();
            onSettingsClick();
          }
        }}
      >
        <Settings className="size-4" />
      </span>
    </button>
  );
}

function InvitationRow({ invitation }: { invitation: Invitation }) {
  const acceptInvitation = useAcceptInvitation();
  const initials = invitation.network_name.slice(0, 2).toUpperCase();

  const handleAccept = () => {
    acceptInvitation.mutate(invitation.network_id, {
      onSuccess: () => {
        toast.success(`Joined ${invitation.network_name}`);
      },
    });
  };

  return (
    <div className="flex w-full items-center gap-3 px-4 py-3">
      <Avatar>
        <AvatarFallback className="bg-primary/10 text-primary font-medium">
          {initials}
        </AvatarFallback>
      </Avatar>
      <div className="min-w-0 flex-1">
        <p className="truncate text-sm font-medium">
          {invitation.network_name}
        </p>
        <Small className="text-muted-foreground">You've been invited</Small>
      </div>
      <Button
        size="sm"
        onClick={handleAccept}
        disabled={acceptInvitation.isPending}
      >
        <Check className="mr-1 size-3.5" />
        {acceptInvitation.isPending ? 'Joining...' : 'Accept'}
      </Button>
    </div>
  );
}

function CreateNetworkDialog({
  open,
  onOpenChange,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const [name, setName] = useState('');
  const navigate = useNavigate();
  const queryClient = useQueryClient();

  const createNetwork = useMutation({
    mutationFn: (networkName: string) =>
      apiClient.createNetwork({ name: networkName }),
    onSuccess: (network) => {
      queryClient.invalidateQueries({ queryKey: ['networks'] });
      toast.success(`Created ${network.name}`);
      onOpenChange(false);
      setName('');
      navigate(`/${network.id}/settings?section=members&add=1`);
    },
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const trimmed = name.trim();
    if (!trimmed) return;
    createNetwork.mutate(trimmed);
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Create a Network</DialogTitle>
          <DialogDescription>
            Caution: creating a network will create a new billing account. If
            your team already has a network, ask them for an invite.
          </DialogDescription>
        </DialogHeader>
        <form onSubmit={handleSubmit}>
          <div className="py-4">
            <Input
              placeholder="Network name"
              value={name}
              onChange={(e) => setName(e.target.value)}
              autoFocus
            />
          </div>
          <DialogFooter>
            <Button
              type="button"
              variant="outline"
              onClick={() => onOpenChange(false)}
            >
              Cancel
            </Button>
            <Button
              type="submit"
              disabled={!name.trim() || createNetwork.isPending}
            >
              {createNetwork.isPending ? 'Creating...' : 'Create'}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

export default function NetworkSelector() {
  const navigate = useNavigate();
  const [createDialogOpen, setCreateDialogOpen] = useState(false);

  const { data: networks, isPending, error, refetch } = useNetworks();
  const { data: invitations } = useMyInvitations();

  if (isPending) {
    return <Progress />;
  }

  if (error) {
    return (
      <div className="flex h-full flex-col items-center justify-center gap-3 p-6 text-center">
        <p className="text-sm font-medium">Couldn't load your networks</p>
        <p className="text-muted-foreground text-xs">{toUserMessage(error)}</p>
        <Button size="sm" variant="outline" onClick={() => refetch()}>
          Try again
        </Button>
      </div>
    );
  }

  const hasInvitations = invitations && invitations.length > 0;
  const hasNetworks = networks && networks.length > 0;

  if (!hasNetworks && !hasInvitations) {
    return (
      <div className="mx-auto flex h-full max-w-sm flex-col items-center justify-center gap-4 px-4 text-center">
        <p className="text-muted-foreground">
          You don't have access to any networks yet. Create one or ask your
          admin for an invite.
        </p>
        <div className="flex flex-row gap-1">
          <Button variant="outline" onClick={() => refetch()}>
            Refresh
          </Button>
          <Button onClick={() => setCreateDialogOpen(true)}>
            <Plus className="mr-1 size-3.5" />
            Create Network
          </Button>
        </div>
        <CreateNetworkDialog
          open={createDialogOpen}
          onOpenChange={setCreateDialogOpen}
        />
      </div>
    );
  }

  return (
    <>
      <ScrollArea className="h-full">
        <div className="py-1">
          {hasInvitations && (
            <>
              <div className="flex items-center gap-2 px-4 pb-1 pt-4">
                <p className="text-muted-foreground text-xs font-medium uppercase tracking-wider">
                  Pending Invitations
                </p>
                <Badge variant="secondary" className="text-xs">
                  {invitations.length}
                </Badge>
              </div>
              {invitations.map((inv, index) => (
                <div key={`${inv.network_id}-${inv.email}`}>
                  <InvitationRow invitation={inv} />
                  {index < invitations.length - 1 && (
                    <Separator className="mx-4" />
                  )}
                </div>
              ))}
              <Separator className="mx-4 mt-2" />
            </>
          )}

          {hasNetworks && (
            <>
              {hasInvitations && (
                <p className="text-muted-foreground px-4 pb-1 pt-4 text-xs font-medium uppercase tracking-wider">
                  Your Networks
                </p>
              )}
              {networks.map((network, index) => (
                <div key={network.id}>
                  <NetworkRow
                    network={network}
                    onClick={() => navigate(`/${network.id}`)}
                    onSettingsClick={() => navigate(`/${network.id}/settings`)}
                  />
                  {index < networks.length - 1 && (
                    <Separator className="mx-4" />
                  )}
                </div>
              ))}
            </>
          )}

          <Separator className="mx-4 mt-2" />
          <div className="px-4 py-3">
            <Button
              variant="outline"
              size="sm"
              onClick={() => setCreateDialogOpen(true)}
            >
              <Plus className="mr-1 size-3.5" />
              New Network
            </Button>
          </div>
        </div>
      </ScrollArea>

      <CreateNetworkDialog
        open={createDialogOpen}
        onOpenChange={setCreateDialogOpen}
      />
    </>
  );
}
