'use client';

import React, { useEffect, useMemo, useState } from 'react';

import 'reactflow/dist/style.css';
import {
  Accordion,
  Card,
  Code,
  Group,
  Loader,
  Popover,
  SegmentedControl,
  Skeleton,
  Tabs,
  Text,
} from '@mantine/core';
import { useQuery } from '@tanstack/react-query';
import { IconBraces, IconInfoCircle, IconPencilPlus, IconPlus } from '@tabler/icons-react';
import { useDisclosure } from '@mantine/hooks';
import { PreviewComponent } from '@/src/components/PreviewComponent/PreviewComponent';
import { CodeComponent } from '@/src/components/CodeComponent/CodeComponent';
import { TestComponent } from '@/src/components/TestComponent/TestComponent';
import { InputManager } from '@/src/components/InputsManager';
import { getEchoHeaders } from '@/src/components/utils';
import classes from './CssModules.module.css';

export default function HomePage({ params }: { params: { workflowId: string; stepId: string } }) {
  const [payloadVariableData, setPayloadVariableData] = useState<any>({});
  const [variableData, setVariableData] = useState<any>({});
  const [loading, setLoading] = useState(true);
  const { isLoading: loadingWorkflow, data: workflow } = useQuery({
    queryKey: ['workflow', params.workflowId],
    queryFn: () =>
      fetch(`/api/workflows/${params.workflowId}`, {
        method: 'GET',
        headers: { ...getEchoHeaders() },
      })
        .then(async (res) => {
          const json = await res.json();

          return json;
        })
        .catch(async (e) => {
          const error = await e.response.json();

          return error;
        }),
  });

  useEffect(() => {
    if (loading) {
      setLoading(false);
    }
  }, [workflow]);

  const {
    isLoading: loadingPreview,
    data: preview,
    error,
  } = useQuery({
    queryKey: ['preview', params.workflowId, params.stepId, variableData, payloadVariableData],
    refetchOnWindowFocus: 'always',
    refetchInterval: false,
    queryFn: async ({ queryKey }) => {
      const inputs = queryKey[3];
      const payload = queryKey[4];

      return fetch(`/api/workflows/${params.workflowId}/preview/${params.stepId}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...getEchoHeaders(),
        },
        body: JSON.stringify({
          inputs,
          payload,
        }),
      })
        .then((res) => res.json())
        .then((res) => res)
        .catch(async (e) => {
          const jsonError = await e.response.json();

          return jsonError;
        });
    },
  });

  const [mode, setMode] = useState('Preview');

  async function onSubmit(data: any) {
    setVariableData(data.formData);
  }

  async function onSubmitWorkflowPayload(data: any) {
    setPayloadVariableData(data.formData);
  }

  function onVariableModeChangeWorkflowPayload(data: any) {
    console.log({ data }, 'workflow');
    setPayloadVariableData(data.formData);
  }

  function onVariableModeChange(data: any) {
    console.log({ data }, 'step');

    setVariableData(data.formData);
  }

  const step = workflow?.steps.find((item) => item.stepId === params.stepId);
  const iconStyle = { width: 14, height: 14 };

  return (
    <div style={{ width: '100%', height: '100vh', display: 'flex' }}>
      <div style={{ padding: 20, width: '100%' }}>
        <div
          style={{
            width: '100%',
            alignItems: 'center',
            display: 'flex',
            justifyContent: 'center',
            marginBottom: 30,
          }}
        >
          <SegmentedControl value={mode} data={['Preview', 'Code', 'Test']} onChange={setMode} />
        </div>

        {mode === 'Preview' ? (
          <PreviewComponent loading={loading} step={step} preview={preview} error={error} />
        ) : null}
        {mode === 'Code' ? <CodeComponent code={step.code} format /> : null}
        {mode === 'Test' ? (
          <TestComponent step={step} onSubmit={onSubmit} onChange={onVariableModeChange} />
        ) : null}
      </div>

      <div
        style={{
          width: 450,
          minWidth: 450,
          paddingLeft: 30,
          paddingRight: 30,
        }}
      >
        {loading || !step ? (
          <Skeleton visible style={{ marginBottom: 10 }}>
            <div style={{ height: '440px' }} />
          </Skeleton>
        ) : (
          <>
            <Card shadow="sm" radius={5} m={0} p={0} pt={10} pb={0}>
              <Tabs defaultValue="form">
                <Tabs.List grow>
                  <Tabs.Tab
                    color="var(--mantine-color-dark-0)"
                    value="form"
                    leftSection={<IconPencilPlus style={iconStyle} />}
                  >
                    Form
                  </Tabs.Tab>
                  <Tabs.Tab
                    color="var(--mantine-color-dark-0)"
                    value="json"
                    leftSection={<IconBraces style={iconStyle} />}
                  >
                    JSON
                  </Tabs.Tab>
                </Tabs.List>

                <Accordion multiple defaultValue={['workflow', 'step']}>
                  <Accordion.Item value="workflow">
                    <Accordion.Control>
                      <RenderToolTipHeader
                        title="Workflow Payload"
                        tooltip={<WorkflowSchemaExample />}
                      />
                    </Accordion.Control>
                    <Accordion.Panel>
                      <Tabs.Panel value="form">
                        <InputManager
                          view="form"
                          json={payloadVariableData}
                          title="Workflow Payload"
                          tooltip={<WorkflowSchemaExample />}
                          schema={workflow?.options?.payloadSchema || {}}
                          onSubmit={onSubmitWorkflowPayload}
                          onChange={onVariableModeChangeWorkflowPayload}
                        />
                      </Tabs.Panel>
                      <Tabs.Panel value="json">
                        <InputManager
                          view="json"
                          json={payloadVariableData}
                          title="Workflow Payload"
                          tooltip={<WorkflowSchemaExample />}
                          schema={workflow?.options?.payloadSchema || {}}
                          onSubmit={onSubmitWorkflowPayload}
                          onChange={onVariableModeChangeWorkflowPayload}
                        />
                      </Tabs.Panel>
                    </Accordion.Panel>
                  </Accordion.Item>

                  <Accordion.Item value="step">
                    <Accordion.Control>
                      <RenderToolTipHeader title="Step Inputs" tooltip={<InputStepExample />} />
                    </Accordion.Control>
                    <Accordion.Panel>
                      <Tabs.Panel value="form">
                        <InputManager
                          title="Step Inputs"
                          json={variableData}
                          schema={step?.inputs?.schema || {}}
                          onSubmit={onSubmit}
                          tooltip={<InputStepExample />}
                          onChange={onVariableModeChange}
                        />
                      </Tabs.Panel>
                      <Tabs.Panel value="json">
                        <InputManager
                          view="json"
                          json={variableData}
                          title="Step Inputs"
                          schema={step?.inputs?.schema || {}}
                          onSubmit={onSubmit}
                          tooltip={<InputStepExample />}
                          onChange={onVariableModeChange}
                        />
                      </Tabs.Panel>
                    </Accordion.Panel>
                  </Accordion.Item>
                </Accordion>
              </Tabs>
            </Card>
          </>
        )}
      </div>
    </div>
  );
}

function RenderToolTipHeader({ tooltip, title }) {
  const [opened, { close, open }] = useDisclosure(false);

  return (
    <Group>
      <Text fw={500}>{title}</Text>
      <Popover opened={opened} width={300}>
        <Popover.Target>
          <IconInfoCircle
            style={{ position: 'relative', right: 8 }}
            onMouseEnter={open}
            onMouseLeave={close}
            size={18}
          />
        </Popover.Target>
        <Popover.Dropdown>{tooltip}</Popover.Dropdown>
      </Popover>
    </Group>
  );
}

function WorkflowSchemaExample() {
  const inputsCodeSnippet = `payloadSchema: {
  type: "object", 
  properties: {
     showButton: { 
      type: "boolean",
      default: true
    }
  }
}`;

  return (
    <>
      <Text size="xs">
        Step Inputs are used to control the behaviour of a step from the Web UI.
      </Text>
      <Text size="xs">
        <br /> They can be used for things like: Content, Hiding and showing elements, control the
        order of elements or change parameters like digest length and type. <br /> <br />
      </Text>
      <Text size="xs">Inputs are defined using JSON Schema:</Text>
      <Code block>{inputsCodeSnippet}</Code>
    </>
  );
}

function InputStepExample() {
  const inputsCodeSnippet = `inputs: {
  type: "object", 
  properties: {
     showButton: { 
      type: "boolean",
      default: true
    }
  }
}`;

  return (
    <>
      <Text size="xs">
        Step Inputs are used to control the behaviour of a step from the Web UI.
      </Text>
      <Text size="xs">
        <br /> They can be used for things like: Content, Hiding and showing elements, control the
        order of elements or change parameters like digest length and type. <br /> <br />
      </Text>
      <Text size="xs">Inputs are defined using JSON Schema:</Text>
      <Code block>{inputsCodeSnippet}</Code>
    </>
  );
}
