/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import { useEffect, useState } from 'react';
import { Row, Col } from 'react-bootstrap';
import {
  useParams,
  useSearchParams,
  useNavigate,
  useLocation,
} from 'react-router-dom';
import { useTranslation } from 'react-i18next';

import { Pagination, CustomSidebar } from '@/components';
import { loggedUserInfoStore, toastStore } from '@/stores';
import { scrollToElementTop, scrollToDocTop } from '@/utils';
import { usePageTags, usePageUsers, useSkeletonControl } from '@/hooks';
import type {
  ListResult,
  QuestionDetailRes,
  AnswerItem,
} from '@/common/interface';
import { questionDetail, getAnswers } from '@/services';

import {
  Question,
  Answer,
  AnswerHead,
  RelatedQuestions,
  WriteAnswer,
  Alert,
  ContentLoader,
  InviteToAnswer,
  LinkedQuestions,
} from './components';

import './index.scss';

const Index = () => {
  const navigate = useNavigate();
  const { t } = useTranslation('translation');
  const { qid = '', slugPermalink = '' } = useParams();
  /**
   * Note: Compatible with Permalink
   */
  let { aid = '' } = useParams();
  if (!aid && slugPermalink) {
    aid = slugPermalink;
  }

  const [urlSearch] = useSearchParams();
  const page = Number(urlSearch.get('page') || 0);
  const order = urlSearch.get('order') || '';
  const [question, setQuestion] = useState<QuestionDetailRes | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const { isSkeletonShow } = useSkeletonControl(isLoading);
  const [answers, setAnswers] = useState<ListResult<AnswerItem>>({
    count: -1,
    list: [],
  });
  const { setUsers } = usePageUsers();
  const userInfo = loggedUserInfoStore((state) => state.user);
  const isAuthor = userInfo?.username === question?.user_info?.username;
  const isAdmin = userInfo?.role_id === 2;
  const isModerator = userInfo?.role_id === 3;
  const isLogged = Boolean(userInfo?.access_token);
  const loggedUserRank = userInfo?.rank;
  const location = useLocation();

  useEffect(() => {
    if (location.state?.isReview) {
      toastStore.getState().show({
        msg: t('review', { keyPrefix: 'toast' }),
        variant: 'warning',
      });

      // remove state isReview
      const newLocation = { ...location };
      delete newLocation.state;
      window.history.replaceState(null, '', newLocation.pathname);
    }
  }, [location.state]);

  const requestAnswers = async () => {
    const res = await getAnswers({
      order: order === 'updated' || order === 'created' ? order : 'default',
      question_id: qid,
      page: 1,
      page_size: 999,
    });

    if (res) {
      res.list = res.list?.filter((v) => {
        // delete answers only show to author and admin and has search params aid
        if (v.status === 10) {
          if (
            (v?.user_info?.username === userInfo?.username || isAdmin) &&
            aid === v.id
          ) {
            return v;
          }
          return null;
        }

        return v;
      });

      setAnswers({ ...res, count: res.list.length });
      if (page > 0 || order) {
        // scroll into view;
        const element = document.getElementById('answerHeader');
        scrollToElementTop(element);
      }

      res.list.forEach((item) => {
        setUsers([
          {
            displayName: item.user_info?.display_name,
            userName: item.user_info?.username,
          },
          {
            displayName: item?.update_user_info?.display_name,
            userName: item?.update_user_info?.username,
          },
        ]);
      });
    }
  };

  const getDetail = async () => {
    setIsLoading(true);
    try {
      const res = await questionDetail(qid);
      if (res) {
        setUsers([
          {
            id: res.user_info?.id,
            displayName: res.user_info?.display_name,
            userName: res.user_info?.username,
            avatar_url: res.user_info?.avatar,
          },
          {
            id: res?.update_user_info?.id,
            displayName: res?.update_user_info?.display_name,
            userName: res?.update_user_info?.username,
            avatar_url: res?.update_user_info?.avatar,
          },
          {
            id: res?.last_answered_user_info?.id,
            displayName: res?.last_answered_user_info?.display_name,
            userName: res?.last_answered_user_info?.username,
            avatar_url: res?.last_answered_user_info?.avatar,
          },
        ]);
        setQuestion(res);
      }
      setIsLoading(false);
    } catch (e) {
      setIsLoading(false);
    }
  };

  const initPage = (type: string) => {
    if (type === 'delete_question') {
      setTimeout(() => {
        navigate('/', { replace: true });
      }, 1000);
      return;
    }
    if (type === 'default') {
      scrollToDocTop();
      getDetail();
      return;
    }
    if (type === 'delete_answer') {
      getDetail();
    }
    requestAnswers();
  };

  const writeAnswerCallback = (obj: AnswerItem) => {
    setAnswers({
      count: answers.count + 1,
      list: [...answers.list, obj],
    });

    if (question) {
      setQuestion({
        ...question,
        answered: true,
        first_answer_id: question.first_answer_id
          ? question.first_answer_id
          : obj.id,
      });
    }
  };

  useEffect(() => {
    if (!qid) {
      return;
    }
    getDetail();
    requestAnswers();
  }, [qid]);

  useEffect(() => {
    if (page || order) {
      requestAnswers();
    }
  }, [page, order]);
  usePageTags({
    title: question?.title,
    description: question?.description,
    keywords: question?.tags.map((_) => _.slug_name).join(','),
  });

  const showInviteToAnswer = question?.id;
  const showLinkedQuestions = question?.id && question.id !== '';
  let canInvitePeople = false;
  if (showInviteToAnswer && Array.isArray(question.extends_actions)) {
    const inviteAct = question.extends_actions.find((op) => {
      return op.action === 'invite_other_to_answer';
    });
    if (inviteAct) {
      canInvitePeople = true;
    }
  }

  return (
    <Row className="questionDetailPage pt-4 mb-5">
      <Col className="page-main flex-auto">
        {question?.operation?.level && <Alert data={question.operation} />}
        {isSkeletonShow ? (
          <ContentLoader />
        ) : (
          <Question
            data={question}
            initPage={initPage}
            hasAnswer={answers.count > 0}
            isLogged={isLogged}
          />
        )}
        {!isLoading && answers.count > 0 && (
          <>
            <AnswerHead count={answers.count} order={order} />
            {answers?.list?.map((item) => {
              return (
                <Answer
                  aid={aid}
                  key={item?.id}
                  data={item}
                  questionTitle={question?.title || ''}
                  canAccept={isAuthor || isAdmin || isModerator}
                  callback={initPage}
                  isLogged={isLogged}
                />
              );
            })}
          </>
        )}

        {!isLoading && Math.ceil(answers.count / 15) > 1 && (
          <div className="d-flex justify-content-center answer-item pt-4">
            <Pagination
              currentPage={Number(page || 1)}
              pageSize={15}
              totalSize={answers?.count || 0}
            />
          </div>
        )}

        {!isLoading &&
          Number(question?.status) !== 2 &&
          !question?.operation?.type && (
            <WriteAnswer
              data={{
                qid,
                answered: question?.answered,
                loggedUserRank,
                first_answer_id: question?.first_answer_id,
              }}
              callback={writeAnswerCallback}
            />
          )}
      </Col>
      <Col className="page-right-side mt-4 mt-xl-0">
        <CustomSidebar />
        {showInviteToAnswer ? (
          <InviteToAnswer
            questionId={question.id}
            readOnly={!canInvitePeople}
          />
        ) : null}
        {showLinkedQuestions ? <LinkedQuestions id={question.id} /> : null}
        <RelatedQuestions id={question?.id || ''} />
      </Col>
    </Row>
  );
};

export default Index;
