import { ArrowPathIcon, XMarkIcon } from '@heroicons/react/24/outline';
import { t } from 'i18next';
import { useEffect, useState } from 'react';
import { toast, Toaster } from 'sonner';

import PrimaryButton from '../../../components/button/PrimaryButton';
import SelectDropdown from '../../../components/dropdown/SelectDropdown';
import SimpleInput from '../../../components/input/SimpleInput';
import Modal from '../../../components/modal/Modal';
import RichText from '../../../components/text/RichText';
import TextArea from '../../../components/text/TextArea';
import GetCWENameByLanguage from '../../../services/getCWEName';
import {
  postDescriptionCWE,
  postVulnerability,
} from '../../../services/vulnerabilities';
import CVSSCalculator from '../components/CVSSCalculator';
import MultiCheckboxButton from '../components/MultiCheckboxButton';

type CWEData = {
  priority: number;
  label: string;
  score: number;
};

type CWERelated = {
  cwe: string;
  cweParent?: string;
  cweGrandParent?: string;
};

type Details = {
  locale: string;
  title: string;
  vulnType: string;
  description: string;
  observation: string;
  remediation: string;
  cwes: string[];
  references: string[];
  customFields: string[];
};

type AddVulnerabilityData = {
  priority: number | '';
  remediationComplexity: number | '';
  details: Details[];
  category: string | null;
};

type ListItem = {
  id: number;
  value: string;
  label?: string;
  locale?: string;
};

type AddVulnerabilityProps = {
  isOpen: boolean;
  handlerIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
  categoryVuln: ListItem | null;
  currentLang: ListItem | null;
  languages: ListItem[];
  types: ListItem[];
  refreshVulns: () => void;
  handleOnSuccess: (message: string) => void;
};

type PostDescription = {
  vuln: string;
};

const AddVulnerability: React.FC<AddVulnerabilityProps> = ({
  isOpen,
  handlerIsOpen,
  categoryVuln,
  currentLang,
  languages,
  types,
  refreshVulns,
  handleOnSuccess,
}) => {
  const [openModal, setOpenModal] = useState(false);
  const [changed, setChanged] = useState<boolean>(false);

  const [language, setLanguage] = useState<ListItem>(
    currentLang ?? languages[0],
  );

  const [selectedType, setSelectedType] = useState<ListItem | null>(null);
  const [typeListFiltered, setTypeListFiltered] = useState<ListItem[]>(
    types.filter(typeIter => typeIter.locale === language.value),
  );

  const [complexity, setComplexity] = useState<ListItem | null>(null);
  const [priority, setPriority] = useState<ListItem | null>(null);
  const [cweLoading, setCweLoading] = useState<boolean>(false);
  const [cweRecommendationSelected, setCweRecommendationSelected] = useState<
    string[]
  >([]);
  const [cweRecommended, setCweRecommended] = useState<CWERelated[]>([]);
  const [cvssVector, setCvssVector] = useState<string>('');

  const [titleRequiredAlert, setTitleRequiredAlert] = useState<boolean>(false);

  const complexityOptions = [
    { id: 1, value: t('easy') },
    { id: 2, value: t('medium') },
    { id: 3, value: t('complex') },
  ];

  const priorityOptions = [
    { id: 1, value: t('low') },
    { id: 2, value: t('medium') },
    { id: 3, value: t('high') },
    { id: 4, value: t('urgent') },
  ];

  const [data, setData] = useState<AddVulnerabilityData>({
    remediationComplexity: '',
    details: [],
    category: categoryVuln ? categoryVuln.value : '',
    priority: '',
  });

  const [details, setDetails] = useState<Details[]>([]);

  const [detail, setDetail] = useState<Details>({
    locale: language.value,
    title: '',
    vulnType: '',
    description: '',
    observation: '',
    remediation: '',
    cwes: [],
    references: [],
    customFields: [],
  });

  const closeSlidingPage = () => {
    setOpenModal(false);
    handlerIsOpen(false);
  };

  const addNewDetail = (localeValue: string) => {
    const newDetail: Details = {
      locale: localeValue,
      title: '',
      vulnType: '',
      description: '',
      observation: '',
      remediation: '',
      cwes: [],
      references: [],
      customFields: [],
    };
    setDetail(newDetail);
  };

  const handleTypeChange = (item: ListItem) => {
    if (changed === false) {
      setChanged(true);
    }
    setDetail(prevDetail => ({
      ...prevDetail,
      vulnType: item.value,
    }));
    setSelectedType(item);
  };

  const handleLanguageChange = (item: ListItem) => {
    if (changed === false) {
      setChanged(true);
    }

    setCweRecommendationSelected([]);
    setCweRecommended([]);
    const findLangItem = details.findIndex(
      detailLocale => detailLocale.locale === item.value,
    );

    if (findLangItem !== -1) {
      setDetail(details[findLangItem]);
      setSelectedType(
        types.find(
          typeIter => typeIter.locale === details[findLangItem].locale,
        ) ?? null,
      );
    } else {
      addNewDetail(item.value);
      setSelectedType(null);
    }
    setLanguage(item);
    setTypeListFiltered(
      types.filter(typeIter => typeIter.locale === item.value),
    );
  };

  const handleDropdownChange = (name: string, item: ListItem) => {
    if (changed === false) {
      setChanged(true);
    }
    setData(prevData => ({
      ...prevData,
      [name]: item.id,
    }));
    name === 'priority' ? setPriority(item) : setComplexity(item);
  };

  const handleInputChange = (field: string, value: string) => {
    if (changed === false) {
      setChanged(true);
    }
    setDetail(prevDetail => ({
      ...prevDetail,
      [field]:
        field === 'cwes' || field === 'references' ? value.split('\n') : value,
    }));
  };

  const handleCWERecomendation = async () => {
    if (detail.description === '' || detail.description === '<p><br></p>') {
      toast.error(t('err.descriptionRequired'));
      // Cambiar el estado de required
      return;
    }
    const descriptionCWE: PostDescription = {
      vuln: detail.description,
    };

    try {
      setCweLoading(true);
      setCweRecommendationSelected([]);
      const responseCWE = await postDescriptionCWE(descriptionCWE);
      const sortedResult = responseCWE.result.sort(
        (a: CWEData, b: CWEData) => b.score - a.score,
      );
      const recommendedCWEs = GetCWENameByLanguage(detail.locale, sortedResult);
      setCweRecommended(recommendedCWEs);
    } catch (error) {
      console.error('Error:', error);
      toast.error(t('err.failedCWERecommendation'));
    } finally {
      setCweLoading(false);
    }
  };

  const handleCvssRecomendation = () => {
    if (detail.description === '' || detail.description === '<p><br></p>') {
      toast.error(t('err.descriptionRequired'));
      return '';
    } else {
      return detail.description;
    }
  };

  const handlerSubmitCWE = () => {
    setDetail(prevDetail => ({
      ...prevDetail,
      cwes: [...cweRecommendationSelected, ...prevDetail.cwes],
    }));
    setCweRecommendationSelected([]);
    setCweRecommended([]);
  };

  useEffect(() => {
    const findLang = details.findIndex(
      detailLocale => detailLocale.locale === detail.locale,
    );

    if (findLang !== -1) {
      const updatedDetails = [...details];

      if (JSON.stringify(updatedDetails[findLang]) !== JSON.stringify(detail)) {
        updatedDetails[findLang] = { ...detail };
        setDetails(updatedDetails);
      }
    } else {
      details.push(detail);
    }
  }, [detail, details]);

  const handleSubmitNewVulnerability = async () => {
    if (!details.some(detail => detail.title !== '')) {
      toast.error(t('err.titleRequired'));
      setTitleRequiredAlert(true);
      return;
    }

    const newVuln = {
      cvssv3: cvssVector !== 'CVSS:3.1/' ? cvssVector : '',
      remediationComplexity: data.remediationComplexity,
      details: [...details],
      category: data.category ?? null,
      priority: data.priority,
    };

    try {
      const response = await postVulnerability([newVuln]);
      if (response.status === 'success') {
        handleOnSuccess(t('msg.vulnerabilityCreatedOk'));
      }
    } catch (error) {
      if (
        error instanceof Error &&
        error.message === 'Vulnerability title already exists'
      ) {
        toast.error(t('vulnerabilityTitleAlreadyExists'));
      } else {
        toast.error(t('err.failedUpdateVulnerability'));
      }
      console.error('Error:', error);
      return;
    }
    refreshVulns();
    handlerIsOpen(!isOpen);
  };

  return (
    <>
      <div
        aria-hidden="true"
        className={`fixed inset-0 bg-black bg-opacity-50 transition-opacity duration-300 ${isOpen ? 'opacity-100' : 'opacity-0'}`}
        onClick={() => (changed ? setOpenModal(true) : closeSlidingPage())}
      />
      <div className="fixed z-10">
        <Modal
          cancelText={t('btn.stay')}
          disablehr
          isOpen={openModal}
          onCancel={() => setOpenModal(false)}
          onSubmit={closeSlidingPage}
          submitText={t('btn.confirm')}
          title={t('msg.doYouWantToLeave')}
        >
          <span />
        </Modal>
      </div>
      <Toaster />
      <div
        className={`fixed top-0 right-0 h-full w-1/2 bg-gray-700 shadow-lg transform transition-transform duration-300 ${
          isOpen ? 'translate-x-0 overflow-y-auto' : 'translate-x-full'
        }`}
      >
        <div className="ml-3 mt-2 flex justify-between items-center">
          <div className="flex items-center">
            <h4 className="text-xl font-bold p-1">{t('addVulnerability')}</h4>
            <span className="px-4 rounded-md border-0 text-white">
              {categoryVuln ? categoryVuln.label : t('noCategory')}
            </span>
          </div>
          <button
            className="bg-transparent text-white p-2 rounded mx-3"
            onClick={() => (changed ? setOpenModal(true) : closeSlidingPage())}
            type="button"
          >
            <XMarkIcon className="h-6 w-6" />
          </button>
        </div>
        <hr className="h-1 my-3 bg-gray-600 border-0 rounded" />
        <div className="flex items-center">
          <div className="w-2/3 mx-4">
            <SimpleInput
              id="title"
              label={t('title')}
              name="title"
              onChange={value => handleInputChange('title', value)}
              placeholder=""
              requiredAlert={titleRequiredAlert}
              requiredField={true}
              type="text"
              value={detail.title}
            />
          </div>
          <div className="w-1/6 mx-4">
            <SelectDropdown
              items={typeListFiltered}
              onChange={handleTypeChange}
              placeholder=""
              selected={selectedType}
              title={t('type')}
            />
          </div>
          <div className="w-1/6 mx-4 relative">
            <SelectDropdown
              items={languages}
              onChange={handleLanguageChange}
              selected={language}
              title={t('language')}
            />
          </div>
        </div>
        <div>
          <RichText
            label={t('description')}
            onChange={value => handleInputChange('description', value)}
            placeholder=""
            value={detail.description}
          />
        </div>
        <div>
          <RichText
            label={t('observation')}
            onChange={value => handleInputChange('observation', value)}
            placeholder=""
            value={detail.observation}
          />
        </div>
        <div>
          <RichText
            label={t('remediation')}
            onChange={value => handleInputChange('remediation', value)}
            placeholder=""
            value={detail.remediation}
          />
        </div>
        <div className="mx-4 flex justify-center">
          <CVSSCalculator
            handleCvssChange={(newCvssVector: string) =>
              setCvssVector(newCvssVector)
            }
            handleCvssRecomendation={handleCvssRecomendation}
          />
        </div>
        <div className="flex">
          <div className="w-1/2 p-4">
            <SelectDropdown
              items={complexityOptions}
              onChange={value =>
                handleDropdownChange('remediationComplexity', value)
              }
              selected={complexity}
              title={t('remediationComplexity')}
            />
          </div>
          <div className="w-1/2 p-4 relative">
            <SelectDropdown
              items={priorityOptions}
              onChange={value => handleDropdownChange('priority', value)}
              selected={priority}
              title={t('remediationPriority')}
            />
          </div>
        </div>
        <div className="m-4">
          <TextArea
            id="references"
            label={t('references')}
            name="references"
            onChange={value => handleInputChange('references', value)}
            placeholder=""
            rows={4}
            value={
              Array.isArray(detail.references)
                ? detail.references.join('\n')
                : detail.references
            }
          />
        </div>
        <div className="m-4">
          <TextArea
            id="cwes"
            label="CWEs"
            name="cwes"
            onChange={value => handleInputChange('cwes', value)}
            placeholder=""
            rows={4}
            value={
              Array.isArray(detail.cwes) ? detail.cwes.join('\n') : detail.cwes
            }
          />
        </div>
        <div className="mb-2 mx-4 flex">
          <PrimaryButton onClick={() => handleCWERecomendation()}>
            <span>{t('recommendCwe')}</span>
          </PrimaryButton>
          {cweLoading ? (
            <span className="ml-2">
              <ArrowPathIcon className="h-8 w-8 animate-spin text-blue-500" />
            </span>
          ) : null}
        </div>
        {cweRecommended.length > 0 ? (
          <div className="mx-4 mb-4">
            <MultiCheckboxButton
              cweRecommendationSelected={cweRecommendationSelected}
              cwesRecommended={cweRecommended}
              setCweRecommendationSelected={setCweRecommendationSelected}
            />
            {cweRecommendationSelected.length > 0 ? (
              <PrimaryButton
                onClick={() => {
                  handlerSubmitCWE();
                }}
              >
                {t('btn.confirmSelection')}
              </PrimaryButton>
            ) : null}
          </div>
        ) : null}
        <div className="mb-2 mx-4 flex justify-end">
          <PrimaryButton onClick={handleSubmitNewVulnerability}>
            <span>{t('addVulnerability')}</span>
          </PrimaryButton>
        </div>
      </div>
    </>
  );
};

export default AddVulnerability;
