"use client";

import { createApiKey, deleteOwnApikey, fetchOwnApiKeys } from "@/lib/actions";
import GenericConfirmationDialog from "@/lib/components/ui/GenericConfirmationDialog";
import GhostMessage from "@/lib/components/ui/GhostMessage";
import LoadingSpinner from "@/lib/components/ui/LoadingSpinner";
import { ApiKeyEntry } from "@/lib/db";
import { ToastContext } from "@/lib/providers/ToastProvider";
import { Box, Button, Card, Dialog, Flex, Heading, Table, Text, TextField } from "@radix-ui/themes";
import { ExternalLinkIcon, KeyIcon, PencilIcon, PlusIcon } from "lucide-react";
import Link from "next/link";
import { useContext, useEffect, useState } from "react";

export default function ApiKeys() {
  const [keys, setKeys] = useState<(ApiKeyEntry & { copyable?: true })[] | null>(null);
  const [keyLabel, setKeyLabel] = useState("");
  const toast = useContext(ToastContext);

  useEffect(() => {
    fetchOwnApiKeys().then(setKeys);
  }, []);

  return (
    <>
      <Flex justify="between" align="center" direction="row" gap="5">
        <Flex direction="column">
          <Heading>API keys</Heading>
          <Text size="3" weight="light">Generate long lasting API keys that can be used to perform certain actions programatically.</Text>
        </Flex>
        <Flex direction="row" gap="3">
          <Dialog.Root onOpenChange={(open) => !open && setKeyLabel("")}>
            <Dialog.Trigger>
              <Button variant="outline"><PlusIcon size="16" /> New key</Button>
            </Dialog.Trigger>
            <Dialog.Content>
              <Dialog.Title>New API key</Dialog.Title>
              <Flex mt="2" direction="column" gap="2">
                <Text size="1" color="gray">What is this key for?</Text>
                <TextField.Root>
                  <TextField.Slot>
                    <PencilIcon size="16" />
                  </TextField.Slot>
                  <TextField.Input
                    placeholder="Alias generator shortcut on my phone"
                    value={keyLabel}
                    onChange={(e) => setKeyLabel(e.currentTarget.value.substring(0, 64))}
                  />
                </TextField.Root>
              </Flex>

              <Flex gap="3" mt="4" justify="end">
                <Dialog.Close>
                  <Button variant="outline">Cancel</Button>
                </Dialog.Close>
                <Dialog.Close>
                  <Button
                    variant="soft"
                    disabled={!keyLabel.length}
                    onClick={async () => {
                      try {
                        const key = await createApiKey(keyLabel);
                        setKeys([ { ...key, copyable: true }, ...(keys ?? []) ]);
                        toast({
                          title: "API key created",
                          description: "The token will only be displayed once",
                          variant: "success",
                        });
                      } catch (e) {
                        toast({
                          title: "Failed to create key",
                          description: `${e}`,
                          variant: "error",
                        });
                      }
                    }}
                  >Create</Button>
                </Dialog.Close>
              </Flex>
            </Dialog.Content>
          </Dialog.Root>
          <Link href="/api-doc" target="_blank">
            <Button variant="outline">API docs <ExternalLinkIcon size="16" /></Button>
          </Link>
        </Flex>
      </Flex>

      <Box mt="4">
        {
          keys
            ? keys.length
              ? <Table.Root variant="surface">
                <Table.Header>
                  <Table.Row>
                    <Table.ColumnHeaderCell>Label</Table.ColumnHeaderCell>
                    <Table.ColumnHeaderCell>Key</Table.ColumnHeaderCell>
                    <Table.ColumnHeaderCell justify="end">Actions</Table.ColumnHeaderCell>
                  </Table.Row>
                </Table.Header>

                <Table.Body>
                  {
                    keys.map((key) => (
                      <Table.Row key={key.id}>
                        <Table.Cell>{key.label}</Table.Cell>
                        <Table.Cell>{key.token}</Table.Cell>
                        <Table.Cell justify="end">
                          <Flex gap="2" direction="row" justify="end">
                            {key.copyable && (
                              <Button
                                variant="outline"
                                onClick={() => navigator.clipboard.writeText(key.token)}
                                size="1"
                              >
                                Copy
                              </Button>
                            )}
                            <GenericConfirmationDialog
                              title="Delete key?"
                              description="It will be invalidated immediately. You cannot restore deleted keys."
                              action={async () => {
                                try {
                                  await deleteOwnApikey(key.id);
                                  setKeys(keys.filter((k) => k.id != key.id));
                                  toast({
                                    title: "Key deleted",
                                    variant: "success",
                                  });
                                } catch(e) {
                                  toast({
                                    title: "Failed to delete key",
                                    description: `${e}`,
                                    variant: "error",
                                  });
                                }
                              }}
                              labelConfirm="Delete"
                            >
                              <Button variant="soft" size="1">
                                Delete
                              </Button>
                            </GenericConfirmationDialog>
                          </Flex>
                        </Table.Cell>
                      </Table.Row>
                    ))
                  }
                </Table.Body>
              </Table.Root>
              : <Card>
                <GhostMessage icon={<KeyIcon />} header="No API keys" message="You don't have any API keys right now" />
              </Card>
            : <GhostMessage icon={<LoadingSpinner />} header="Loading" />
        }
      </Box>
    </>
  );
}