import * as React from 'react';
import { useParams } from 'react-router-dom';
import { useContext, useEffect, useState } from 'react';
import Tab from '../../components/Tab';
import NamespaceHeader from '../../components/NamespaceHeader';
import NodeInfoTab from './NodeInfoTab';
import NodeColumnTab from './NodeColumnTab';
import NodeDataFlowTab from './NodeDataFlowTab';
import NodeDimensionsTab from './NodeDimensionsTab';
import NodeHistory from './NodeHistory';
import NotebookDownload from './NotebookDownload';
import DJClientContext from '../../providers/djclient';
import NodeMaterializationTab from './NodeMaterializationTab';
import NodePreAggregationsTab from './NodePreAggregationsTab';
import ClientCodePopover from './ClientCodePopover';
import WatchButton from './WatchNodeButton';
import NodesWithDimension from './NodesWithDimension';
import NodeColumnLineage from './NodeLineageTab';
import EditIcon from '../../icons/EditIcon';
import ChartIcon from '../../icons/ChartIcon';
import AlertIcon from '../../icons/AlertIcon';
import LoadingIcon from '../../icons/LoadingIcon';
import NodeDependenciesTab from './NodeDependenciesTab';
import { useNavigate } from 'react-router-dom';

export function NodePage() {
  const djClient = useContext(DJClientContext).DataJunctionAPI;
  const navigate = useNavigate();

  const { name, tab } = useParams();

  const [state, setState] = useState({
    selectedTab: tab || 'info',
  });

  const [node, setNode] = useState(null);
  // undefined = not yet known; NamespaceHeader reports the read-only verdict
  // (git_only, flat/root shape, or git-deployed) once its config + sources load.
  const [isReadOnly, setIsReadOnly] = useState(undefined);

  const onClickTab = id => () => {
    // Preview tab redirects to Query Planner instead of showing content
    if (id === 'preview') {
      const param = node?.type === 'cube' ? 'cube' : 'metrics';
      navigate(`/planner?${param}=${encodeURIComponent(name)}`);
      return;
    }
    navigate(`/nodes/${name}/${id}`);
    setState({ selectedTab: id });
  };

  const buildTabs = tab => {
    return tab.display ? (
      <Tab
        key={tab.id}
        id={tab.id}
        name={tab.name}
        icon={tab.icon}
        onClick={onClickTab(tab.id)}
        selectedTab={state.selectedTab}
      />
    ) : null;
  };

  useEffect(() => {
    const fetchData = async () => {
      const data = await djClient.node(name);
      if (data.message !== undefined) {
        // Error response
        setNode(data);
        return;
      }
      setNode({ ...data });
    };
    fetchData().catch(console.error);
  }, [djClient, name]);

  const tabsList = node => {
    return [
      {
        id: 'info',
        name: 'Info',
        display: true,
      },
      {
        id: 'columns',
        name: 'Columns',
        display: node?.type !== 'metric',
      },
      {
        id: 'data-flow',
        name: 'Data Flow',
        display: true,
      },
      {
        id: 'dimensions',
        name: 'Dimensions',
        display: node?.type !== 'source',
      },
      {
        id: 'history',
        name: 'History',
        display: true,
      },
      {
        id: 'materializations',
        name: 'Materializations',
        display: node?.type !== 'source' && node?.type !== 'metric',
      },
      {
        id: 'linked',
        name: 'Linked Nodes',
        display: node?.type === 'dimension',
      },
      {
        id: 'lineage',
        name: 'Lineage',
        display: node?.type === 'metric',
      },
      {
        id: 'dependencies',
        name: 'Dependencies',
        display: node?.type !== 'cube',
      },
      {
        id: 'preview',
        name: 'Preview →',
        icon: <ChartIcon size={18} />,
        display: node?.type === 'metric' || node?.type === 'cube',
      },
    ];
  };
  let tabToDisplay = null;

  switch (state.selectedTab) {
    case 'info':
      tabToDisplay = node ? <NodeInfoTab node={node} /> : '';
      break;
    case 'columns':
      tabToDisplay = (
        <NodeColumnTab
          node={node}
          djClient={djClient}
          readOnly={!!isReadOnly}
        />
      );
      break;
    case 'data-flow':
      tabToDisplay = <NodeDataFlowTab djNode={node} />;
      break;
    case 'dimensions':
      tabToDisplay = <NodeDimensionsTab djNode={node} />;
      break;
    case 'history':
      tabToDisplay = <NodeHistory node={node} djClient={djClient} />;
      break;
    case 'materializations':
      // Cube nodes use cube-specific materialization tab
      // Other nodes (transform, metric, dimension) use pre-aggregations tab
      tabToDisplay =
        node?.type === 'cube' ? (
          <NodeMaterializationTab node={node} djClient={djClient} />
        ) : (
          <NodePreAggregationsTab node={node} />
        );
      break;
    case 'linked':
      tabToDisplay = <NodesWithDimension node={node} djClient={djClient} />;
      break;
    case 'lineage':
      tabToDisplay = <NodeColumnLineage djNode={node} djClient={djClient} />;
      break;
    case 'dependencies':
      tabToDisplay = <NodeDependenciesTab node={node} djClient={djClient} />;
      break;
    default:
      /* istanbul ignore next */
      tabToDisplay = <NodeInfoTab node={node} />;
  }

  const buttonStyle = {
    height: '28px',
    padding: '0 10px',
    fontSize: '12px',
    border: '1px solid #e2e8f0',
    borderRadius: '4px',
    backgroundColor: '#ffffff',
    color: '#475569',
    cursor: 'pointer',
    display: 'flex',
    alignItems: 'center',
    gap: '4px',
    whiteSpace: 'nowrap',
  };

  const NodeButtons = () => {
    return (
      <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
        {isReadOnly === false && (
          <button
            style={buttonStyle}
            onClick={() => navigate(`/nodes/${node?.name}/edit`)}
          >
            <EditIcon /> Edit
          </button>
        )}

        <WatchButton node={node} buttonStyle={buttonStyle} />

        <ClientCodePopover nodeName={name} buttonStyle={buttonStyle} />
        {node?.type === 'cube' && (
          <NotebookDownload node={node} buttonStyle={buttonStyle} />
        )}
      </div>
    );
  };

  // @ts-ignore
  return (
    <div className="node__header">
      <NamespaceHeader
        namespace={name.split('.').slice(0, -1).join('.')}
        onReadOnlyChange={setIsReadOnly}
      />
      <div className="card">
        {node === undefined ? (
          <div style={{ padding: '2rem', textAlign: 'center' }}>
            <LoadingIcon />
          </div>
        ) : node?.message === undefined ? (
          <div className="card-header" style={{}}>
            <div
              style={{
                display: 'flex',
                flexDirection: 'row',
                justifyContent: 'space-between',
              }}
            >
              <h3
                className="card-title align-items-start flex-column"
                style={{ display: 'inline-block' }}
              >
                <span
                  className="card-label fw-bold text-gray-800"
                  role="dialog"
                  aria-hidden="false"
                  aria-label="DisplayName"
                >
                  {node?.display_name}{' '}
                  <span
                    className={'node_type__' + node?.type + ' badge node_type'}
                    role="dialog"
                    aria-hidden="false"
                    aria-label="NodeType"
                  >
                    {node?.type}
                  </span>
                  {isReadOnly === true && (
                    <span
                      style={{
                        display: 'inline-flex',
                        alignItems: 'center',
                        marginLeft: '4px',
                        color: '#92400e',
                        verticalAlign: 'middle',
                        cursor: 'help',
                      }}
                      aria-label="ReadOnly"
                      title="Read-only — edits must go through git."
                    >
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        width="14"
                        height="14"
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        strokeWidth="2"
                        strokeLinecap="round"
                        strokeLinejoin="round"
                      >
                        <rect
                          x="3"
                          y="11"
                          width="18"
                          height="11"
                          rx="2"
                          ry="2"
                        />
                        <path d="M7 11V7a5 5 0 0 1 10 0v4" />
                      </svg>
                    </span>
                  )}
                </span>
              </h3>
              <NodeButtons />
            </div>
            <div>
              <a
                href={'/nodes/' + node?.name}
                className="link-table"
                role="dialog"
                aria-hidden="false"
                aria-label="NodeName"
              >
                {node?.name}
              </a>
              <span
                className="rounded-pill badge bg-secondary-soft"
                style={{ marginLeft: '0.5rem' }}
              >
                {node?.version}
              </span>
            </div>
            <div className="dj-tabs-bar">{tabsList(node).map(buildTabs)}</div>
            {tabToDisplay}
          </div>
        ) : node?.message !== undefined ? (
          <div className="message alert" style={{ margin: '20px' }}>
            <AlertIcon />
            Node `{name}` does not exist!
          </div>
        ) : (
          ''
        )}
      </div>
    </div>
  );
}
