'use client';

import '@mantine/code-highlight/styles.css';

import {
  Badge,
  Button,
  Card,
  Code,
  Container,
  Group,
  Image,
  Tooltip,
  Stepper,
  Text,
  Input,
  Divider,
  Loader,
} from '@mantine/core';
import { useEffect, useState } from 'react';
import { CodeHighlightTabs } from '@mantine/code-highlight';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useLocalStorage } from '@mantine/hooks';
import Link from 'next/link';
import Confetti from 'react-confetti';
import { useRouter } from 'next/navigation';
import { getEchoHeaders, setLocalStorageUrl } from '@/src/components/utils';
import { EdgeUrlInput } from '@/src/components/EdgeUrlInput';

export default function HomePage() {
  const router = useRouter();
  const [isEchoUrlValid, setIsEchoUrlValid] = useState(false);
  const [echoUrl, setEchoUrl] = useLocalStorage({ key: 'echo_url', defaultValue: '' });
  const [echoUrlForm, setEchoUrlForm] = useState(echoUrl);
  const [showConffetti, setShowConffetti] = useState(false);
  useEffect(() => {
    if (echoUrl) {
      setEchoUrlForm(echoUrl);
    }
  }, [echoUrl]);

  const { isLoading: loadingWorkflows, data: workflows } = useQuery<any[]>({
    queryKey: ['workflows'],
    enabled: !!echoUrl,
    refetchOnWindowFocus: 'always',
    refetchInterval: 1000,
    queryFn: () =>
      fetch('/api/workflows', {
        headers: {
          ...getEchoHeaders(),
        },
      }).then((res) => res.json()),
  });

  const [active, setActive] = useState(0);
  const nextStep = async () => {
    if (active === 0) {
      setEchoUrl(echoUrlForm);
    }

    setActive((current) => (current < 3 ? current + 1 : current));
  };
  const prevStep = () => setActive((current) => (current > 0 ? current - 1 : current));

  useEffect(() => {
    if (active === 1 && workflows?.length) {
      nextStep();
      setShowConffetti(true);

      setTimeout(() => {
        setShowConffetti(false);
      }, 5000);
    }
  }, [workflows, active]);

  function isNextButtonDisabled() {
    if (active === 0) {
      return !isEchoUrlValid;
    }

    if (active === 1) {
      return false;
    }
  }

  function onEdgeValidity(isValid: boolean) {
    setIsEchoUrlValid(isValid);
  }

  function onUrlChange(urlData: string) {
    setEchoUrlForm(urlData);
  }

  return (
    <Container size="sm">
      <Card shadow="sm" padding="lg" radius="md" withBorder style={{ marginTop: 15 }}>
        <Card.Section>
          <Image
            src="https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/images/bg-8.png"
            height={160}
            alt="Norway"
          />
        </Card.Section>

        <Group justify="space-between" mt="md" mb="xs">
          <Text fw={500}>Welcome to Novu Studio</Text>
        </Group>

        <Text size="sm" c="dimmed">
          Novu Studio is a companion app for Novu Echo. It allows you to develop your workflows
          locally, right in your IDE and preview the channel specific content in real-time.
        </Text>

        <Stepper active={active} onStepClick={setActive} style={{ marginTop: 40 }}>
          <Stepper.Step label="Install" description="Install Echo SDK">
            <Text style={{ marginTop: 20 }}>
              In your project directory, install the Echo SDK using your package manager.
            </Text>
            <CodeHighlightTabs
              style={{ marginTop: 20 }}
              code={[
                { fileName: 'npm', code: 'npm install @novu/echo', language: 'shell' },
                { fileName: 'pnpm', code: 'pnpm install @novu/echo', language: 'shell' },
                { fileName: 'yarn', code: 'yarn install @novu/echo', language: 'shell' },
              ]}
            />
            <Divider my="md" />

            <Text style={{ marginTop: 20 }}>
              After installation, create a new instance of Echo and export it from{' '}
              <Code>client.ts</Code>
            </Text>

            <CodeHighlightTabs
              style={{ marginTop: 15 }}
              code={[
                {
                  fileName: 'app/echo/client.ts',
                  code: `
import { Echo } from '@novu/echo';

export const echo = new Echo({
  /**
  * Enable this flag only during local development
  */
  devModeBypassAuthentication: process.env.NODE_ENV === 'development'
});

                `,
                  language: 'typescript',
                },
              ]}
            />

            <Divider my="md" />

            <Text style={{ marginTop: 20 }}>
              Now, we need to expose your workflows via API, so the Novu Worker Engine and Dev
              Studio can communicate with it.
            </Text>

            <CodeHighlightTabs
              style={{ marginTop: 15 }}
              code={[
                {
                  fileName: 'app/api/echo/route.ts (NextJS)',
                  code: `
import { serve } from "@novu/echo/next";
import { echo } from "../../echo/client";

export const { GET, POST, PUT } = serve({ client: echo });
  
                `,
                  language: 'typescript',
                },
                {
                  fileName: 'app/api/echo.ts (Express)',
                  code: `
import { serve } from "@novu/echo/express";
import { echo } from "../echo/client";

app.use(express.json()); // Required for Echo POST requests
app.use(
  "/api/echo",
  serve({ client: echo })
);
  
                `,
                  language: 'typescript',
                },
              ]}
            />

            <Divider my="md" />

            <EdgeUrlInput
              onEdgeValidity={onEdgeValidity}
              onUrlChange={onUrlChange}
              defaultUrl={echoUrl}
            />
          </Stepper.Step>
          <Stepper.Step label="Build" description="Create a workflow">
            <Text style={{ marginTop: 20 }}>
              Let's create a simple workflow that sends an e-mail.
            </Text>

            <CodeHighlightTabs
              style={{ marginTop: 15 }}
              code={[
                {
                  fileName: 'app/echo/client.ts',
                  code: `                  
echo.workflow('hello-world', async ({ step }) => {
  await step.email('send-email', async (inputs) => {
    return {
      subject: "This is an email subject",
      body: "E-mail body of hello " + inputs.world
    }
  }, {
     inputs: {
        type: 'object', properties: { world: { type: 'string', default: 'World' }} 
     }
  });
}, { payloadSchema: { type: 'object', properties: {} }});
                `,
                  language: 'typescript',
                },
              ]}
            />
          </Stepper.Step>
          <Stepper.Step label="Preview" description="Preview your step content">
            <Confetti numberOfPieces={showConffetti ? 200 : 0} />

            <Text style={{ marginTop: 20, marginBottom: 20 }}>
              Amazing! You have created your first workflow. Let's look at it in Studio.
            </Text>

            {workflows?.map((workflow) => (
              <Link
                href={`/workflow/${workflow.workflowId}`}
                style={{ textDecoration: 'none', color: 'initial' }}
              >
                <Card shadow="sm" padding="sm" radius="md" withBorder mb={10}>
                  <Group justify="space-between">
                    <Text fw={500}>{workflow.workflowId}</Text>
                    <Badge color="black">View</Badge>
                  </Group>
                </Card>
              </Link>
            ))}
          </Stepper.Step>
        </Stepper>

        <Group justify="space-between" mt="xl">
          <span>
            {active > 0 ? (
              <Button variant="default" onClick={prevStep}>
                Back
              </Button>
            ) : null}
          </span>

          <span>
            {active !== 2 ? (
              <Button onClick={nextStep} disabled={isNextButtonDisabled()}>
                Next step
              </Button>
            ) : null}
            {active === 2 && workflows ? (
              <Button onClick={() => router.push(`/workflow/${workflows[0].workflowId}`)}>
                Finish
              </Button>
            ) : null}
          </span>
        </Group>
      </Card>
    </Container>
  );
}
