'use client';

import * as React from 'react';
import clsx from 'clsx';
import { Transition } from '@headlessui/react';
import NextImage from 'next/image';
import NextLink from 'next/link';

import styles from './developer.module.css';

import {
  GH_PINGCAP_TIDB,
  DOC_CLOUD_CHAT2QUERY,
  DOC_CLOUD_BRANCH,
  DOC_CLOUD_DATA_SERVICE,
  DOC_CLOUD_MONITOR,
} from '@/constant/url';
import {
  LightIcon,
  ArrowRightIcon,
  GitHubIcon,
  GHStarIcon,
  GHPullRequestIcon,
  GHPeopleIcon,
  TiDBTimelineIcon,
} from '@/components/Icon';
import {
  DeveloperAIEditorSchema,
  DeveloperAIEditor,
  DeveloperAIEditorRun,
  DeveloperAIEditorResult,
} from '@/app/_components/sections/Svg';
import { goToGitHubClick } from '@/components/GTM';

export default function Developer(props: any) {
  return (
    <section className="my-8 flex w-full flex-col">
      <h2 className="px-6 pb-4 pt-4 text-center font-bold leading-normal md:pt-8 lg:px-8 lg:pt-16">
        By Developers, for Developers
      </h2>
      <div className="flex justify-center px-6 pb-8 text-center text-sm leading-8 text-darkgrey-100 lg:px-8">
        <div className="max-w-5xl">
          We take pride in our{' '}
          <span className="bg-[#01ECB0] px-1 font-bold text-black">
            open-source
          </span>{' '}
          roots. With the developer community, we align our product, to make
          sure it perfectly fits modern application developer{`'`}s needs.
        </div>
      </div>
      <div className="flex flex-col items-center justify-center gap-8 px-6 pb-10 md:pb-20 lg:px-8 lg:pb-40">
        <NextLink
          href={GH_PINGCAP_TIDB}
          target="_blank"
          onClick={() => {
            goToGitHubClick({
              page_category: '',
              page_category2: '',
              position: 'section-developer',
            });
          }}
        >
          <GitHubIcon className="h-auto w-16 fill-current text-darkgrey-300 hover:text-white" />
        </NextLink>
        <GHMetric />
      </div>
      <DevXTimeline />
    </section>
  );
}

const GHMetricItem = (props: {
  value: number;
  label: string | React.ReactNode;
}) => {
  const { value, label } = props;
  const [isAnimated, setIsAnimated] = React.useState(false);

  const elRef = React.useRef(null);

  React.useEffect(() => {
    const el = elRef?.current;

    if (el && !isAnimated) {
      const observer = new IntersectionObserver(
        (entries) => {
          if (entries[0].isIntersecting) {
            animateValue(el, value - 100, value, 2000);
            setIsAnimated(true);
            observer.disconnect();
          }
        },
        { threshold: 0.1 },
      );
      observer.observe(el);
    }
  }, [elRef, isAnimated, value]);

  return (
    <div className="flex min-w-[200px] flex-row items-center justify-center gap-4 md:flex-col">
      <div className="flex items-center justify-center">
        <span
          className="font-lexend text-[40px] font-bold leading-relaxed text-darkgrey-300"
          ref={elRef}
        >
          {value.toLocaleString()}
        </span>
      </div>
      <div className="text-xl">{label}</div>
    </div>
  );
};

const GHMetric = (props: any) => {
  const [stars, setStars] = React.useState(30000);
  const [pr, setPR] = React.useState(30000);
  const [contributors, setContributors] = React.useState(800);

  const elRef = React.useRef(null);

  React.useEffect(() => {
    const getEdgeCfg = async () => {
      const res = await fetch('/api/org/overview');
      const data = await res.json();
      setStars(data?.data?.stars || 0);
      setPR(data?.data?.pull_requests || 0);
      setContributors(data?.data?.participants || 0);
    };

    const el = elRef?.current;

    // scroll into view and load data
    if (el) {
      const observer = new IntersectionObserver(
        (entries) => {
          if (entries[0].isIntersecting) {
            getEdgeCfg();
            observer.disconnect();
          }
        },
        { threshold: 0.1 },
      );
      observer.observe(el);
    }
  }, [elRef]);

  return (
    <div
      className="flex w-full max-w-5xl flex-col items-center justify-between md:flex-row md:flex-nowrap"
      ref={elRef}
    >
      {stars > 0 && (
        <GHMetricItem
          key={`stars-${stars}`}
          value={stars}
          label={
            <div className="flex items-center gap-2 text-[#01ECB0]">
              <GHStarIcon className="inline-flex h-6 w-auto fill-current" />
              GitHub Stars
            </div>
          }
        />
      )}
      {pr > 0 && (
        <GHMetricItem
          key={`pr-${pr}`}
          value={pr}
          label={
            <div className="flex items-center gap-2 text-[#0CA6F2]">
              <GHPullRequestIcon className="inline-flex h-6 w-auto fill-current" />
              Pull Requests
            </div>
          }
        />
      )}
      {contributors > 0 && (
        <GHMetricItem
          key={`contributors-${contributors}`}
          value={contributors}
          label={
            <div className="flex items-center gap-2 text-[#00F6FF]">
              <GHPeopleIcon className="inline-flex h-6 w-auto fill-current" />
              Contributors
            </div>
          }
        />
      )}
    </div>
  );
};

function animateValue(
  ele: HTMLElement | null,
  start: number,
  end: number,
  duration: number,
) {
  // assumes integer values for start and end

  const range = end - start;
  // no timer shorter than 50ms (not really visible any way)
  const minTimer = 50;
  // calc step time to show all interediate values
  let stepTime = Math.abs(Math.floor(duration / range));

  // never go below minTimer
  stepTime = Math.max(stepTime, minTimer);

  // get current time and calculate desired end time
  const startTime = new Date().getTime();
  const endTime = startTime + duration;
  let timer: any;

  function run() {
    var now = new Date().getTime();
    var remaining = Math.max((endTime - now) / duration, 0);
    var value = Math.round(end - remaining * range);
    ele && (ele.innerHTML = value.toLocaleString());
    if (value == end) {
      clearInterval(timer);
    }
  }

  timer = setInterval(run, stepTime);
  run();
}

const DevXTimelineItems = [
  {
    id: 'ai-assisted-sql-editor',
    label: 'AI Assisted SQL Editor',
    icon: TiDBTimelineIcon,
    document: DOC_CLOUD_CHAT2QUERY,
    children: (
      <>
        <p className="px-6 pb-3 pt-10 md:px-12 xl:px-44">
          <b className="text-white">
            Efficiently and intelligently construct SQL queries.
          </b>{' '}
          Seamlessly generate intuitive queries, conduct thorough analyses of
          existing code, and receive tailored function recommendations - all
          powered by <b className="text-white">AI</b>.
        </p>
        <div
          className={clsx(
            'flex w-full items-center justify-center gap-4 px-6 pb-10 md:px-12',
            styles.aiEditor,
          )}
        >
          <div>
            <DeveloperAIEditorSchema
              height={306}
              width={220}
              className="h-auto w-full"
            />
          </div>

          <div>
            <DeveloperAIEditor
              height={304}
              width={450}
              className={clsx('h-auto w-full', styles.editor)}
            />
          </div>

          <div className="flex h-full flex-col justify-between">
            <DeveloperAIEditorRun
              height={72}
              width={354}
              className={clsx('h-auto w-full', styles.editorRun)}
            />
            <DeveloperAIEditorResult
              height={222}
              width={354}
              className={clsx('h-auto w-full', styles.editorResult)}
            />
          </div>
        </div>
      </>
    ),
  },
  {
    id: 'branching',
    label: 'Branching',
    icon: TiDBTimelineIcon,
    document: DOC_CLOUD_BRANCH,
    children: (
      <>
        <p className="px-6 pb-3 pt-10 md:px-12">
          Manage your database as meticulously as your source code. Effortlessly{' '}
          <b className="text-white">branch out with CLI</b>, and sync changes
          with the team effortlessly. Confidently conduct{' '}
          <b className="text-white">
            &apos;what-if&apos; experiments in isolated environments
          </b>{' '}
          ensuring no disruption to the main data stream.
        </p>
        <NextImage
          src="/developer/branching-01.svg"
          alt="developer/branching"
          width={1221}
          height={247}
          className="h-auto w-full pb-10"
        />
      </>
    ),
  },
  {
    id: 'data-service',
    label: 'Data Service',
    icon: TiDBTimelineIcon,
    document: DOC_CLOUD_DATA_SERVICE,
    children: (
      <>
        <p className="px-6 pb-3 pt-10 md:px-12">
          Experience an all-in-one,{' '}
          <b className="text-white">low-code solution</b> that streamlines
          backend development and data access. Our platform offers seamless
          integration of <b className="text-white">RESTful APIs</b> and{' '}
          <b className="text-white">SQL-to-HTTP</b>, simplifying complex
          processes into efficient, user-friendly operations.
        </p>
        <NextImage
          src="/developer/data-service-01.svg"
          alt="developer/data-service"
          width={1046}
          height={270}
          className="h-auto w-full px-6 pb-10 md:px-12"
        />
      </>
    ),
  },
  {
    id: 'built-in-monitoring',
    label: 'Built-in monitoring',
    icon: TiDBTimelineIcon,
    document: DOC_CLOUD_MONITOR,
    children: (
      <>
        <p className="px-6 pb-3 pt-10 md:px-12 xl:px-36">
          What keeps you in control. Instantly identify slow queries, resource
          bottlenecks, and potential issues. Delve deep into{' '}
          <b className="text-white">SQL statements</b>, visualize{' '}
          <b className="text-white">emerging trends</b>, and enhance performance
          using <b className="text-white">real-time</b> analytics.
        </p>
        <div className="flex w-full justify-center gap-4 px-6 pb-10 md:px-12 xl:justify-between">
          <div>
            <NextImage
              src="/developer/monitor-01.svg"
              alt="developer/built-in-monitoring"
              width={361}
              height={257}
              className="h-auto"
            />
          </div>
          <div>
            <NextImage
              src="/developer/monitor-02.svg"
              alt="developer/built-in-monitoring"
              width={361}
              height={257}
              className=""
            />
          </div>
          <div>
            <NextImage
              src="/developer/monitor-03.svg"
              alt="developer/built-in-monitoring"
              width={506}
              height={256}
              className=""
            />
          </div>
        </div>
      </>
    ),
  },
];

const DevXTimeline = (props: any) => {
  const [activeItem, setActiveItem] = React.useState('ai-assisted-sql-editor');
  const [paused, setPaused] = React.useState(false);

  React.useEffect(() => {
    if (paused) return;
    const interval = setInterval(() => {
      const index = DevXTimelineItems.findIndex(
        (item) => item.id === activeItem,
      );
      const nextIndex = (index + 1) % DevXTimelineItems.length;
      setActiveItem(DevXTimelineItems[nextIndex].id);
    }, 5000);

    return () => clearInterval(interval);
  }, [activeItem, paused]);

  const handleItemClick = (id: string) => {
    setActiveItem(id);
    setPaused(true);
  };

  return (
    <div className={clsx('flex flex-col items-center gap-8', styles.devX)}>
      <div
        className="flex w-full items-center justify-center border-t-4 border-solid"
        style={{
          borderImage: 'var(--DevX-bar-Gradient) 1',
        }}
      >
        <ol className="flex w-full max-w-7xl justify-around gap-4 px-6 md:items-center md:gap-6 lg:px-8">
          {DevXTimelineItems.map((item) => (
            <li
              key={item.id}
              onClick={() => handleItemClick(item.id)}
              className="group cursor-pointer"
            >
              <div className="flex-start flex items-center pt-2 md:block md:pt-0">
                {item.id !== activeItem && (
                  <div className="mx-auto -mt-[33px] hidden h-[64px] w-[64px] p-4 md:block">
                    <div className="mx-auto mt-2 h-4 w-4 rounded-full bg-neutral-300 transition-transform group-hover:scale-105" />
                  </div>
                )}
                {item.id === activeItem && (
                  <TiDBTimelineIcon className="mx-auto -mt-[33px] hidden h-[64px] w-[64px] md:block" />
                )}
                <p
                  className={clsx(
                    'mt-2 text-sm text-lightgrey-300 transition-colors md:text-xl',
                    {
                      ['group-hover:text-darkgrey-300']: item.id !== activeItem,
                      [styles.selectedText]: item.id === activeItem,
                      'text-transparent': item.id === activeItem,
                    },
                  )}
                >
                  {item.label}
                </p>
              </div>
            </li>
          ))}
        </ol>
      </div>

      {DevXTimelineItems.map((item) => (
        <Transition
          key={item.id + activeItem}
          appear={true}
          show={item.id === activeItem}
        >
          <div className="transition duration-500 ease-in-out data-[closed]:opacity-0">
            <DevXTimelineContent>{item.children}</DevXTimelineContent>

            <NextLink
              href={item.document}
              target="_blank"
              className="mx-auto mt-4 flex w-fit items-center gap-2 text-sm text-darkgrey-300 hover:text-white"
            >
              <LightIcon className="inline-flex h-5 w-auto" /> How to use{' '}
              {item.label}
              <ArrowRightIcon className="inline-flex h-5 w-auto" />
            </NextLink>
          </div>
        </Transition>
      ))}
    </div>
  );
};

const DevXTimelineContent = (props: {
  className?: string;
  style?: React.CSSProperties;
  children?: React.ReactNode;
}) => {
  const { className, style, children } = props;

  return (
    <div
      className={clsx(
        'mx-6 flex h-auto w-auto max-w-7xl flex-col justify-between overflow-hidden rounded-3xl border-2 border-lightgrey-300 bg-black text-center font-lexend text-sm text-darkgrey-400 sm:h-[352px] md:h-[400px] md:text-xl lg:mx-8 lg:h-[540px] lg:leading-loose',
        className,
      )}
      style={style}
    >
      {children}
    </div>
  );
};
