import * as React from 'react';
import type { NextPage } from 'next';
import { useRouter } from 'next/router';
import Link from 'next/link';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { useTranslation } from 'next-i18next';
import { useSnackbar } from 'notistack';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import CircularProgress from '@mui/material/CircularProgress';

import Layout from 'src/components/Layout';
import { Pages } from 'src/constants';
import SearchInput from 'src/components/Search/SearchInput';
import axios from 'src/lib/axios';
import logger from 'next-pino/logger';
import { calcPathnameFromHtmlUrl } from 'pages/articles';

import { zendeskDataState } from 'src/atom';
import { useRecoilValue } from 'recoil';

export interface ArticlesSearchResultItem {
  id: number;
  url: string;
  html_url: string;
  author_id: number;
  comments_disabled: boolean;
  draft: boolean;
  promoted: boolean;
  position: number;
  vote_sum: number;
  vote_count: number;
  section_id: number;
  created_at: string;
  updated_at: string;
  name: string;
  title: string;
  source_locale: string;
  locale: string;
  outdated: boolean;
  outdated_locales: any[];
  edited_at: string;
  user_segment_id: any;
  permission_group_id: number;
  content_tag_ids: any[];
  label_names: any[];
  body: string;
  snippet: string;
  result_type: 'article';
}

const Search: NextPage = () => {
  const [search, setSearch] = React.useState('');
  const [searchResults, setSearchResults] = React.useState<
    ArticlesSearchResultItem[] | null
  >(null);
  const [isloading, setIsLoading] = React.useState(false);

  const router = useRouter();
  const { t } = useTranslation();
  const zendeskData = useRecoilValue(zendeskDataState);
  const { enqueueSnackbar } = useSnackbar();

  const { query } = router.query;

  React.useEffect(() => {
    if (query) {
      setSearch(query as string);
    }
  }, [query]);

  React.useEffect(() => {
    const searchFunc = async () => {
      setIsLoading(true);
      setSearchResults(null);
      try {
        const data = await axios
          .get(`/api/zendesk/v2/articles/search`, {
            headers: {
              'Content-Type': 'application/json',
              Authorization: zendeskData.token,
            },
            params: {
              query: search,
            },
          })
          .then((res) => res.data);
        const results = data.results as ArticlesSearchResultItem[];
        setSearchResults(results);
      } catch (error: any) {
        logger.error(
          { name: `search`, error },
          `perform search error: ${search}`
        );
        enqueueSnackbar(
          `${error?.response?.data?.message || error?.message || error}`,
          { variant: 'error' }
        );
      } finally {
        setIsLoading(false);
      }
    };
    if (zendeskData.token && search) {
      searchFunc();
    }
  }, [enqueueSnackbar, search, zendeskData.token]);

  return (
    <Layout
      title="Search"
      description="Search for articles"
      authType="forced"
      breadcrumbs={[
        { id: 'home', path: Pages.Home, label: t('pages.home') },
        { id: 'search', label: t(`pages.search`) },
      ]}
    >
      <Box
        sx={{
          display: 'flex',
          flexDirection: 'column',
          gap: '2.5rem',
          pt: { xs: 0, md: '2.5rem' },
          pb: { xs: 0, md: '2.5rem' },
        }}
      >
        <SearchInput
          value={search}
          onChange={(text) => {
            router.push(`/${Pages.Search}?query=${encodeURIComponent(text)}`);
          }}
          disabled={isloading || !zendeskData.token}
        />
        {searchResults && <ResultsList results={searchResults} />}
        {isloading && (
          <Box sx={{ display: 'flex', justifyContent: 'center' }}>
            <CircularProgress />
          </Box>
        )}
      </Box>
    </Layout>
  );
};

function ResultsList(props: { results: ArticlesSearchResultItem[] }) {
  const { results } = props;

  const { t } = useTranslation();

  return (
    <Box
      sx={{
        display: 'flex',
        flexDirection: 'column',
        gap: '1rem',
      }}
    >
      {results.length > 1 && (
        <Typography color="text.secondary" variant="body2">
          {`${results.length} ${t('search.results_found')}...`}
        </Typography>
      )}
      {results.map((item) => {
        return <ResultItem key={item.id} item={item} />;
      })}
      {results.length === 0 && (
        <Typography>{t('search.no_results_found')}</Typography>
      )}
    </Box>
  );
}

function ResultItem(props: { item: ArticlesSearchResultItem }) {
  const { item } = props;

  return (
    <Box
      sx={{
        display: 'flex',
        flexDirection: 'column',
      }}
    >
      <Box
        sx={{
          display: 'flex',
        }}
      >
        <Link href={`/articles/${calcPathnameFromHtmlUrl(item.html_url)}`}>
          <Typography
            variant="h6"
            component="p"
            sx={{
              width: 'fit-content',
            }}
          >
            {item.title}
          </Typography>
        </Link>
      </Box>
      <Typography
        variant="body1"
        component="div"
        dangerouslySetInnerHTML={{ __html: item.snippet }}
        sx={{
          color: 'text.secondary',
          '& em': {
            color: 'primary.main',
            fontWeight: 'bold',
          },
        }}
      />
    </Box>
  );
}

export async function getStaticProps({ locale }: any) {
  return {
    props: {
      ...(await serverSideTranslations(locale, ['common'])),
      // Will be passed to the page component as props
    },
  };
}

export default Search;
