import React, { useEffect, useRef, useState } from 'react';
import {
  useKeywords,
  useCompetitorUrls,
  useExcludedCompetitorUrls,
  useAppStateDispatch,
  useAccountId,
  useRankSource,
} from '../Context.js';
import useSWR from 'swr';
import qs from 'qs';
import { ExternalLink } from 'lucide-react';
import { truncateText } from '../utilities/text.js';
import { get } from '../utilities/fetcher.js';
import Button from '../components/Button.js';
import ErrorMessage from '../components/ErrorMessage.js';
import Loading from '../components/Loading.js';
import InfoBar from '../components/InfoBar.js';
import './Competitors.css';

export interface Serp {
  rank: number;
  url: string;
  keyword: string;
  label: string;
}

const Competitors = ({
  setTab = (_: number) => {},
  nextTab = 0,
}: {
  setTab?: (index: number) => void;
  nextTab?: number;
}) => {
  const keywords = useKeywords();
  const competitorUrls = useCompetitorUrls();
  const excludedCompetitorUrls = useExcludedCompetitorUrls();
  const dispatch = useAppStateDispatch();

  const accountId = useAccountId();
  const rankSource = useRankSource();

  const [availableUrls, setAvailableUrls] = useState(competitorUrls);

  const competitorUrlsRef = useRef(competitorUrls);
  competitorUrlsRef.current = competitorUrls;
  const excludedCompetitorUrlsRef = useRef(excludedCompetitorUrls);
  excludedCompetitorUrlsRef.current = excludedCompetitorUrls;

  const params = {
    queries: keywords,
    first: 15,
    rankSourceId: rankSource.id,
  };

  const { data, isLoading, error, mutate } = useSWR(
    `/conductor/proxy/v3/accounts/${accountId}/batch-untracked-serp/serp-explorer?${qs.stringify(params)}`,
    get,
    { fallbackData: [] },
  );
  useEffect(() => {
    if (data?.length) {
      const urls = data.map((serp: Serp) => serp.url);
      const currentCompetitorUrls = competitorUrlsRef.current;
      const currentExcludedUrls = excludedCompetitorUrlsRef.current;

      // This was previously loaded, either as an existing draft or earlier in the application
      // flow, so any new URLs fetched after this should be added to excluded URLs.
      if (currentCompetitorUrls.length) {
        const newExcludedUrls = urls.filter(
          (url: string) =>
            !currentCompetitorUrls.includes(url) && !currentExcludedUrls.includes(url),
        );
        setAvailableUrls([...new Set([...currentCompetitorUrls, ...urls])]);
        dispatch({
          type: 'setExcludedCompetitorUrls',
          excludedCompetitorUrls: [...new Set([...currentExcludedUrls, ...newExcludedUrls])],
        });
      } else {
        dispatch({
          type: 'setCompetitorUrls',
          competitorUrls: urls,
        });
        setAvailableUrls(urls);
      }
    }
  }, [dispatch, data]);

  const handleCheckboxChange = (url: string, checked: boolean) => {
    if (checked) {
      dispatch({
        type: 'setExcludedCompetitorUrls',
        excludedCompetitorUrls: excludedCompetitorUrls.filter(
          (unselectedSerp) => unselectedSerp !== url,
        ),
      });
      dispatch({
        type: 'setCompetitorUrls',
        competitorUrls: [...competitorUrls, url],
      });
    } else {
      dispatch({
        type: 'setExcludedCompetitorUrls',
        excludedCompetitorUrls: [...excludedCompetitorUrls, url],
      });
      dispatch({
        type: 'setCompetitorUrls',
        competitorUrls: competitorUrls.filter((deselectedUrl) => deselectedUrl !== url),
      });
    }
  };

  if (!keywords.length) {
    return (
      <div>
        <InfoBar>
          Keywords are required, please go back to the previous screen to select some.
        </InfoBar>
      </div>
    );
  }

  return (
    <div className="competitors">
      <div className="competitors__description">
        Content guidance comes from top competitors’ pages ranking for your keywords. Remove
        irrelevant ones for better results.
      </div>
      <InfoBar>A minimum of 10 competitors is required.</InfoBar>
      <ul className="competitors__list">
        {isLoading && (
          <div className="competitors__loading">
            <Loading />
          </div>
        )}
        {error && (
          <div className="competitors__error">
            <ErrorMessage>
              Something went wrong.{' '}
              <button
                onClick={() => {
                  mutate();
                }}
              >
                Please try again.
              </button>
            </ErrorMessage>
          </div>
        )}
        {!isLoading &&
          !error &&
          availableUrls.map((url) => (
            <li key={url}>
              <label className="competitors__item">
                <input
                  type="checkbox"
                  checked={!excludedCompetitorUrls.includes(url)}
                  onChange={(e) => handleCheckboxChange(url, e.target.checked)}
                />
                <a
                  className="competitors__external"
                  href={url}
                  target="_blank"
                  rel="noopener noreferrer"
                  title={url}
                >
                  {truncateText(url)} <ExternalLink size={16} />
                </a>
              </label>
            </li>
          ))}
      </ul>
      <div className="competitors__generate-guidance">
        <Button disabled={competitorUrls.length < 10} onClick={() => setTab(nextTab)}>
          Generate content guidance
        </Button>
      </div>
    </div>
  );
};

export default Competitors;
