'use client';

import Link from 'next/link';
import Image from 'next/image';
import {
  Alert,
  Badge,
  Button,
  Container,
  Input,
  Modal,
  Tooltip,
  Text,
  Code,
  Kbd,
} from '@mantine/core';
import { IconInfoCircle, IconRefresh, IconSearch } from '@tabler/icons-react';
import React, { useEffect, useMemo, useState } from 'react';
import { notifications } from '@mantine/notifications';
import { useQuery } from '@tanstack/react-query';
import { useDisclosure, useLocalStorage } from '@mantine/hooks';
import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer-continued';
import { modals } from '@mantine/modals';
import { spotlight } from '@mantine/spotlight';
import { getEchoHeaders } from '@/src/components/utils';
import { SpotlightComponent } from '@/src/components/Spotlight/Spotlight';

export function TopNavBar({ echoUrl }: { echoUrl: string }) {
  const [echoUrlLocal] = useLocalStorage({ key: 'echo_url', defaultValue: '' });
  const [remoteEchoUrl, setRemoteEchoUrl] = useLocalStorage({
    key: 'remote_echo_url',
    defaultValue: '',
  });

  const [diffState, setDiffState] = useState<{ current?: string; new?: string }>({});
  const [opened, { open, close }] = useDisclosure(false);
  const [echoUrlFormState, setEchoUrlFormState] = useState<string>();

  useEffect(() => {
    setEchoUrlFormState(echoUrlLocal);
  }, [echoUrlLocal]);

  const { isLoading: loadingHealth, data: echoHealth } = useQuery<{ success: true }>({
    queryKey: ['health', echoUrl],
    refetchOnWindowFocus: 'always',
    refetchInterval: 2000,
    enabled: !!echoUrl,
    queryFn: () =>
      fetch('/api/echo/health', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...getEchoHeaders(),
        },
        body: JSON.stringify({ url: echoUrl }),
      }).then((res) => res.json()),
  });
  const [loadingSync, setLoadingSync] = useState(false);
  const [loadingDeploy, setLoadingDeploy] = useState(false);

  async function syncState() {
    setLoadingSync(true);

    try {
      const result = await fetch('/api/state/diff', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...getEchoHeaders(),
        },
        body: JSON.stringify({ echoUrl: echoUrlFormState }),
      }).then(async (response) => {
        if (response.ok) {
          return response.json();
        }

        const jsonError = await response.json();

        notifications.show({
          color: 'red',
          title: 'Oh oh... Something went wrong',
          message: jsonError.message || 'Something bad happened',
        });

        throw new Error(jsonError.message);
      });

      setDiffState({
        current: JSON.stringify(result.data?.current, null, 2),
        new: JSON.stringify(result.data?.new, null, 2),
      });
      open();
    } catch (e: any) {
      console.error(e.message);
    }

    setLoadingSync(false);
  }

  async function deployState() {
    if (!echoUrlFormState) return null;

    if (echoUrlFormState?.includes('localhost')) {
      const port = echoUrlFormState.match(/:(\d+)/) || ['', '<PORT>'];

      const openModal = () =>
        modals.openConfirmModal({
          title: 'localhost is not allowed for sync',
          children: (
            <div>
              <Text size="sm">
                Novu Cloud Will not be able to communicate with your {echoUrlFormState} endpoint, as
                its running on your local machine.
                <br /> Please use <Code>npx localtunnel --port {port[1]}</Code> to expose your local
                server to the internet.
              </Text>
              <br />
              <Text>For production environments we recommend syncing state using CI.</Text>
            </div>
          ),
          labels: { confirm: 'Ok', cancel: 'Cancel' },
          onCancel: () => console.log('Cancel'),
          onConfirm: () => console.log('Confirmed'),
        });

      openModal();
      return;
    }

    setLoadingDeploy(true);

    try {
      const result = await fetch('/api/state/sync', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...getEchoHeaders(),
        },
        body: JSON.stringify({
          echoUrl: echoUrlFormState,
        }),
      }).then(async (response) => {
        if (response.ok) {
          return response.json();
        }

        const jsonError = await response.json();

        notifications.show({
          color: 'red',
          title: 'Oh oh... Something went wrong',
          message: jsonError.message || 'Something bad happened',
        });

        throw new Error(jsonError.message);
      });

      close();
      notifications.show({
        color: 'green',
        title: 'Sync Complete',
        message: 'We have successfully synced your state to Novu Cloud',
      });
    } catch (e: any) {
      console.error(e.message);
    }

    setLoadingDeploy(false);
  }

  async function changeUrl(url: string) {
    setEchoUrlFormState(url);
    setRemoteEchoUrl(url);
  }

  const isIdentical = useMemo(
    () => JSON.stringify(diffState?.current) === JSON.stringify(diffState?.new),
    [diffState]
  );

  return (
    <div
      style={{
        height: '100%',
        padding: '0 20px',
        width: '100%',
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
      }}
    >
      <SpotlightComponent />

      <div style={{}}>
        <Link href="/" style={{ textDecoration: 'none', color: 'initial' }}>
          <Image
            src="/logo/novu-logo-white-dark-background.svg"
            alt="Logo"
            width={110}
            height={40}
          />
          <span style={{ fontSize: 11, position: 'relative', left: -56 }}>dev studio.</span>
        </Link>
      </div>
      <Input
        onClick={(e) => {
          e.preventDefault();
          spotlight.open();
        }}
        onKeyDown={(e) => {
          e.preventDefault();
        }}
        onFocus={(e) => {
          e.preventDefault();
        }}
        placeholder="Search"
        leftSection={<IconSearch size={14} />}
        rightSection={
          <div style={{ minWidth: 70, display: 'flex' }}>
            <Kbd size="xs">⌘ + K</Kbd>
          </div>
        }
      />

      {echoUrl ? (
        <div>
          {echoHealth?.success || loadingHealth ? (
            <Tooltip label={`Echo successfully running at: ${echoUrl}`}>
              <Badge color="#a4a4a4" variant="outline" style={{ marginRight: 15, fontSize: 9 }}>
                <Badge
                  color="green"
                  variant="dot"
                  style={{
                    backgroundColor: 'transparent',
                    padding: 0,
                    border: 0,
                    position: 'relative',
                  }}
                />
                Connected
              </Badge>
            </Tooltip>
          ) : (
            <Tooltip label={`Could not connect at: ${echoUrl}`}>
              <Badge color="#a4a4a4" variant="outline" style={{ marginRight: 15, fontSize: 9 }}>
                <Badge
                  color="red"
                  variant="dot"
                  style={{
                    backgroundColor: 'transparent',
                    padding: 0,
                    border: 0,
                    position: 'relative',
                  }}
                />
                Disconnected
              </Badge>
            </Tooltip>
          )}

          <Button
            loading={loadingSync}
            onClick={syncState}
            leftSection={<IconRefresh size={14} />}
            variant="default"
            size="xs"
            gradient={{
              from: 'rgba(122, 39, 39, 1)',
              to: 'rgba(191, 10, 10, 1)',
              deg: 91,
            }}
          >
            Sync
          </Button>
        </div>
      ) : null}
      <Modal
        opened={opened}
        onClose={close}
        title="Diff local and remote state"
        size={isIdentical ? '600px' : '90%'}
      >
        {isIdentical ? (
          <Container>
            <div style={{ width: '100%', marginTop: 30, marginBottom: 30 }}>
              <Alert
                variant="outline"
                color="grey"
                title="Identical State"
                icon={<IconInfoCircle />}
              >
                <div style={{ color: '#cdcdcd' }}>
                  No Changes were detected between your local and remote state.
                </div>
              </Alert>
            </div>
          </Container>
        ) : (
          <ReactDiffViewer
            oldValue={diffState?.current}
            newValue={diffState?.new}
            splitView
            useDarkTheme
            compareMethod={DiffMethod.WORDS}
          />
        )}
        <div
          style={{
            position: 'sticky',
            bottom: 0,
            left: 0,
            right: 0,
            zIndex: 1,
            background: 'var(--mantine-color-body)',
            padding: '15px 0',
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
          }}
        >
          <Input.Wrapper
            label="Edge Endpoint"
            withAsterisk
            description="Syncing to Cloud will overwrite your dev state. We suggest using GitOps for syncing state!"
          >
            <Input
              onChange={(e) => changeUrl(e.target.value)}
              value={remoteEchoUrl}
              placeholder="Your Cloud Edge Endpoint"
            />
          </Input.Wrapper>

          <div
            style={{
              display: 'flex',
              alignItems: 'flex-end',
              alignSelf: 'flex-end',
              paddingLeft: 20,
            }}
          >
            <Button
              loading={loadingDeploy}
              onClick={deployState}
              leftSection={<IconRefresh size={14} />}
              variant="default"
              size="sm"
              gradient={{
                from: 'rgba(122, 39, 39, 1)',
                to: 'rgba(191, 10, 10, 1)',
                deg: 91,
              }}
            >
              Deploy Changes
            </Button>
          </div>
        </div>
      </Modal>
    </div>
  );
}
