"use client"

import { InviteCard } from "@/components/cards/InviteCard";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { Command, CommandItem } from "@/components/ui/command";
import { Input } from "@/components/ui/input";
import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover";
import { toast } from "@/components/ui/use-toast";
import { bulkDeleteInvites, createInvite } from "@/lib/actions";
import { ChannelInvite } from "@/lib/db";
import { ChevronsUpDown } from "lucide-react";
import { useMemo, useState } from "react";
import { Channel, Server, User } from "revolt-api";

export default function ServerInviteList({ server, invites: invitesInput, channels, users }: {
  server: Server,
  invites: ChannelInvite[],
  channels?: Channel[],
  users?: User[],
}) {
  const [invites, setInvites] = useState(invitesInput);
  const [selectVanityOnly, setSelectVanityOnly] = useState(false);
  const [selectChannel, setSelectChannel] = useState(false);
  const [selectUser, setSelectUser] = useState(false);
  const [vanityFilter, setVanityFilter] = useState<boolean | null>(null);
  const [channelFilter, setChannelFilter] = useState("");
  const [userFilter, setUserFilter] = useState("");
  const [inviteDraft, setInviteDraft] = useState("");
  const [inviteChannelDraft, setInviteChannelDraft] = useState("");
  
  const filteredInvites = useMemo(() => {
    return invites
      ?.filter(invite => vanityFilter === true ? invite.vanity : vanityFilter === false ? !invite.vanity : true)
      ?.filter(invite => channelFilter ? invite.channel == channelFilter : true)
      ?.filter(invite => userFilter ? invite.creator == userFilter : true)
      ?.reverse();
  }, [vanityFilter, channelFilter, userFilter, invites]);

  return (
    <div>
      <div className="flex gap-2">
        <Popover open={selectVanityOnly} onOpenChange={setSelectVanityOnly}>
          <PopoverTrigger asChild>
            <Button
              variant="outline"
              role="combobox"
              aria-expanded={selectVanityOnly}
              className="flex-1 justify-between"
            >
              {vanityFilter === true ? "Vanity" : vanityFilter === false ? "Not vanity" : "All"}
              <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
            </Button>
          </PopoverTrigger>
          <PopoverContent className="w-[200px] p-0">
            <Command>
              {[
                { value: null, label: "All" },
                { value: true, label: "Vanity" },
                { value: false, label: "Not vanity" },
              ].map((option) => (
                <CommandItem
                  key={String(option.value)}
                  onSelect={async () => {
                    setSelectVanityOnly(false);
                    setVanityFilter(option.value);
                  }}
                >{option.label}</CommandItem>
              ))}
            </Command>
          </PopoverContent>
        </Popover>

        <Popover open={selectChannel} onOpenChange={setSelectChannel}>
          <PopoverTrigger asChild>
            <Button
              variant="outline"
              role="combobox"
              aria-expanded={selectChannel}
              className="flex-1 justify-between"
            >
              {channelFilter
                ? '#' + (channels?.find(c => c._id == channelFilter) as any)?.name
                : "Select channel"}
              <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
            </Button>
          </PopoverTrigger>
          <PopoverContent className="w-[200px] p-0">
            <Command>
              <CommandItem onSelect={async () => {
                    setSelectChannel(false);
                    setChannelFilter("");
                  }}
                >All channels</CommandItem>
              {channels?.map((channel) => (
                <CommandItem
                  key={String(channel._id)}
                  onSelect={async () => {
                    setSelectChannel(false);
                    setChannelFilter(channel._id);
                  }}
                >{'#' + (channel as any).name}</CommandItem>
              ))}
            </Command>
          </PopoverContent>
        </Popover>

        <Popover open={selectUser} onOpenChange={setSelectUser}>
          <PopoverTrigger asChild>
            <Button
              variant="outline"
              role="combobox"
              aria-expanded={selectUser}
              className="flex-1 justify-between"
            >
              {userFilter
                ? `${users?.find(c => c._id == userFilter)?.username}#${users?.find(c => c._id == userFilter)?.discriminator}`
                : "Select user"}
              <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
            </Button>
          </PopoverTrigger>
          <PopoverContent className="w-[200px] p-0">
            <Command>
            <CommandItem onSelect={async () => {
                    setSelectUser(false);
                    setUserFilter("");
                  }}
                >All users</CommandItem>
              {users?.map((user) => (
                <CommandItem
                  key={String(user._id)}
                  onSelect={async () => {
                    setSelectUser(false);
                    setUserFilter(user._id);
                  }}
                >{user.username}#{user.discriminator}</CommandItem>
              ))}
            </Command>
          </PopoverContent>
        </Popover>

        <AlertDialog>
          <AlertDialogTrigger asChild>
            <Button disabled={!filteredInvites.length} variant="destructive">Bulk delete</Button>
          </AlertDialogTrigger>
          <AlertDialogContent>
            <AlertDialogHeader>
              <AlertDialogTitle>
                Bulk delete invites
              </AlertDialogTitle>
            </AlertDialogHeader>
            <AlertDialogDescription>
              This will delete all invites that match your filter options.
              <br />
              <b>{filteredInvites.length}</b> invite{filteredInvites.length == 1 ? '' : 's'} will be deleted.
            </AlertDialogDescription>
            <AlertDialogFooter>
              <AlertDialogAction
                onClick={async () => {
                  try {
                    await bulkDeleteInvites(filteredInvites.map(i => i._id));
                    setInvites(invites.filter(invite => !filteredInvites.find(i => i._id == invite._id)));
                    toast({ title: "Selected invites have been deleted" });
                  } catch(e) {
                    toast({
                      title: "Failed to delete invites",
                      description: String(e),
                      variant: "destructive",
                    });
                  }
                }}
              >Bulk delete</AlertDialogAction>
              <AlertDialogCancel>Cancel</AlertDialogCancel>
            </AlertDialogFooter>
          </AlertDialogContent>
        </AlertDialog>

        <AlertDialog>
          <AlertDialogTrigger asChild>
            <Button disabled={!filteredInvites.length}>Create vanity invite</Button>
          </AlertDialogTrigger>
          <AlertDialogContent>
            <AlertDialogHeader>
              <AlertDialogTitle>
                Create vanity invite
              </AlertDialogTitle>
            </AlertDialogHeader>
            <AlertDialogDescription>
              <p className="mb-2">Invites are case sensitive.</p>
              <div className="flex gap-2">
                <Input
                  value={inviteDraft}
                  onChange={(e) => setInviteDraft(e.currentTarget.value)}
                  placeholder="fortnite"
                />
                <ChannelDropdown
                  channels={channels ?? []}
                  value={inviteChannelDraft}
                  setValue={setInviteChannelDraft}
                />
              </div>
              </AlertDialogDescription>
              <AlertDialogFooter>
                <AlertDialogAction
                  disabled={!inviteDraft || !inviteChannelDraft}
                  onClick={async () => {
                    try {
                      const newInvite: ChannelInvite = {
                        _id: inviteDraft,
                        channel: inviteChannelDraft,
                        creator: server.owner,
                        server: server._id,
                        type: "Server",
                        vanity: true,
                      };
                      await createInvite(newInvite);
                      setInvites([...invites, newInvite]);
                      setInviteDraft("");
                      toast({
                        title: "Vanity invite created",
                        description: <a href={`https://rvlt.gg/${inviteDraft}`}>rvlt.gg/{inviteDraft}</a>
                      });
                    } catch(e) {
                      toast({
                        title: "Failed to create invite",
                        description: String(e),
                        variant: "destructive",
                      });
                    }
                  }}
                >Create</AlertDialogAction>
                <AlertDialogCancel>Cancel</AlertDialogCancel>
              </AlertDialogFooter>
            </AlertDialogContent>
        </AlertDialog>
      </div>

      {filteredInvites.map(invite => (<InviteCard
        invite={invite}
        channel={channels?.find(c => c._id == invite.channel)}
        channelList={channels}
        user={users?.find(c => c._id == invite.creator)}
        key={invite._id}
      />))}
    </div>
  )
}

export function ChannelDropdown({ channels, value, setValue }: {
  channels: Channel[],
  value: string,
  setValue: (value: string) => any,
}) {
  const [expanded, setExpanded] = useState(false);

  return (
  <Popover open={expanded} onOpenChange={setExpanded}>
    <PopoverTrigger asChild>
      <Button
        variant="outline"
        role="combobox"
        aria-expanded={expanded}
        className="flex-1 justify-between"
      >
        {value
          ? '#' + (channels?.find(c => c._id == value) as any)?.name
          : "Channel"}
        <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
      </Button>
    </PopoverTrigger>
    <PopoverContent className="w-[200px] p-0">
      <Command>
        {channels?.map((channel) => (
          <CommandItem
            key={String(channel._id)}
            onSelect={async () => {
              setExpanded(false);
              setValue(channel._id);
            }}
          >{'#' + (channel as any).name}</CommandItem>
        ))}
      </Command>
    </PopoverContent>
  </Popover>
  );
}
