"use client";

import { aliasAvailable, createAliasSelf, deleteAlias, fetchOwnAliases } from "@/lib/actions";
import { ALIAS_DOMAINS } from "@/lib/constants";
import { AliasEntry } from "@/lib/db";
import { aliasesNeedApproval } from "@/lib/util";
import { Badge, Box, Button, Callout, Card, Code, Dialog, DropdownMenu, Flex, Heading, ScrollArea, Table, Text, TextField } from "@radix-ui/themes";
import { ChevronDownIcon, InfoIcon, UsersRoundIcon } from "lucide-react";
import { useSession } from "next-auth/react";
import { useContext, useEffect, useState } from "react";
import LoadingSpinner from "../LoadingSpinner";
import GhostMessage from "../GhostMessage";
import { ToastContext } from "@/lib/providers/ToastProvider";

export default function OwnAliasesCard() {
  const session = useSession().data;
  const [aliases, setAliases] = useState<AliasEntry[] | null>(null);
  const [newAliasUsername, setNewAliasUsername] = useState("");
  const [newAliasDomain, setNewAliasDomain] = useState(ALIAS_DOMAINS[0]);
  const [allowAlias, setAllowAlias] = useState(false);
  const toast = useContext(ToastContext);

  useEffect(() => {
    fetchOwnAliases(false).then(setAliases);
  }, []);

  useEffect(() => {
    if (!newAliasUsername || !newAliasDomain) return setAllowAlias(false);

    aliasAvailable(`${newAliasUsername}@${newAliasDomain}`)
      .then((res) => {
        setAllowAlias(res);
      });
  }, [newAliasUsername, newAliasDomain]);

  return (
    <Card className="h-fit">
      <Flex direction="row" justify="between" mb="2">
        <Heading size="3">Email aliases</Heading>
        <Dialog.Root>
          <Dialog.Trigger>
            <Button size="1" variant="outline">New alias</Button>
          </Dialog.Trigger>

          <Dialog.Content>
            <Dialog.Title>Create alias</Dialog.Title>
            {(aliasesNeedApproval(session)) && (
              <Box pt="2" pb="5">
                <Callout.Root>
                  <Callout.Icon>
                    <InfoIcon />
                  </Callout.Icon>
                  <Callout.Text>Aliases you create will have to be approved by an administrator first</Callout.Text>
                </Callout.Root>
              </Box>
            )}

            <Flex gap="2">
              <TextField.Input
                placeholder={session?.user?.email?.split('@')[0] || "username"}
                value={newAliasUsername}
                onChange={(e) => setNewAliasUsername(e.currentTarget.value.toLowerCase())}
              />
              <Text>@</Text>
              <DropdownMenu.Root>
                <DropdownMenu.Trigger>
                  <Button variant="outline" color="gray">{newAliasDomain} <ChevronDownIcon /></Button>
                </DropdownMenu.Trigger>

                <DropdownMenu.Content>
                  {ALIAS_DOMAINS.map((alias) => (
                    <DropdownMenu.Item
                      onClick={() => setNewAliasDomain(alias)}
                      key={alias}
                    >
                      {alias}
                    </DropdownMenu.Item>
                  ))}
                </DropdownMenu.Content>
              </DropdownMenu.Root>
            </Flex>

            <Flex gap="3" mt="4" justify="end">
              <Dialog.Close>
                <Button
                  variant="outline"
                  onClick={() => {
                    setNewAliasUsername("");
                    setNewAliasDomain(ALIAS_DOMAINS[0]);
                  }}>Cancel</Button>
              </Dialog.Close>
              <Dialog.Close>
                <Button
                  variant="soft"
                  disabled={!allowAlias}
                  onClick={async () => {
                    setNewAliasUsername("");
                    setNewAliasDomain(ALIAS_DOMAINS[0]);

                    try {
                      const alias = await createAliasSelf(`${newAliasUsername}@${newAliasDomain}`);
                      setAliases([...(aliases ?? []), alias]);
                      toast({
                        title: "Alias created",
                        description: alias.pending ? "Administrator approval pending" : undefined,
                        variant: "success",
                      });
                    } catch(e) {
                      console.error(e);
                      toast({
                        title: "Failed to create alias",
                        description: `${e}`,
                        variant: "error",
                      });
                    }
                  }}>Create</Button>
              </Dialog.Close>
            </Flex>
          </Dialog.Content>
        </Dialog.Root>
      </Flex>
      {
        aliases == null
          ? <GhostMessage icon={<LoadingSpinner />} header="Loading..." />
          : aliases.length
            ? <Box className="h-60">
              <ScrollArea>
                <Table.Root>
                  <Table.Header>
                    <Table.Row>
                      <Table.ColumnHeaderCell justify='start'>Alias</Table.ColumnHeaderCell>
                      <Table.ColumnHeaderCell justify='end'>Manage</Table.ColumnHeaderCell>
                    </Table.Row>
                  </Table.Header>

                  <Table.Body>
                    {
                      aliases.map((alias => <Table.Row key={alias.id}>
                        <Table.Cell justify='start'>
                          {alias.alias}
                          {alias.pending && <Badge variant="soft" ml="2" color="orange">Pending</Badge>}
                        </Table.Cell>
                        <Table.Cell justify='end'>
                          <Dialog.Root>
                            <Dialog.Trigger>
                              <Button variant="soft" size="1" mr="2">Delete</Button>
                            </Dialog.Trigger>

                            <Dialog.Content>
                              <Dialog.Title>Delete alias</Dialog.Title>
                              <Dialog.Description>
                                Are you sure you want to delete the alias <Code>{alias.alias}</Code>?
                                It will become available for other users to claim immediately.
                              </Dialog.Description>

                              <Flex gap="3" mt="4" justify="end">
                                <Dialog.Close>
                                  <Button variant="outline">Cancel</Button>
                                </Dialog.Close>
                                <Dialog.Close>
                                  <Button
                                    variant="soft"
                                    onClick={async () => {
                                      try {
                                        await deleteAlias(alias.alias);
                                        setAliases(aliases.filter((a) => a.id != alias.id));
                                        toast({
                                          title: "Alias deleted",
                                          description: alias.alias,
                                          variant: "success",
                                        });
                                      } catch (e) {
                                        console.error(e);
                                        toast({
                                          title: "Failed to delete alias",
                                          description: `${e}`,
                                          variant: "error",
                                        });
                                      }
                                    }}
                                  >
                                    Delete
                                  </Button>
                                </Dialog.Close>
                              </Flex>
                            </Dialog.Content>
                          </Dialog.Root>
                        </Table.Cell>
                      </Table.Row>))
                    }
                  </Table.Body>
                </Table.Root>
              </ScrollArea>
            </Box>
            : <GhostMessage icon={<UsersRoundIcon />} header="No aliases" message="Create an alias to begin" />
      }
    </Card>
  );
}
