import { t } from 'i18next';
import { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast, Toaster } from 'sonner';

import Card from '../../components/card/Card';
import Modal from '../../components/modal/Modal';
import UITable from '../../components/table/UITable';
import { useSortableTable } from '../../hooks/useSortableTable';
import { useTableFiltering } from '../../hooks/useTableFiltering';
import {
  deleteVulnerability,
  getCategories,
  getLanguages,
  getTypes,
  getVulnerabilities,
} from '../../services/vulnerabilities';
import AddVulnerability from './add/addVulnerability';
import VulnerabilityButtons from './components/vulnerabilityButtons';
import EditVulnerability from './edit/editVulnerability';
import MergeVulnerabilities from './merge/mergeVulnerabilities';

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

type VulnerabilityData = {
  _id: string;
  cvssv3: string | null;
  priority?: number | '';
  remediationComplexity?: number | '';
  details: Details[];
  status?: number;
  category?: string | null;
  __v: number;
  createdAt?: string;
  updatedAt?: string;
};

type LanguageData = {
  language: string;
  locale: string;
};

type CategoryData = {
  _id: string;
  name: string;
  sortValue: string;
  sortOrder: string;
  sortAuto: boolean;
};

type TypeData = {
  name: string;
  locale: string;
};

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

type ListItemCategory = {
  id: number;
  value: string;
  label?: string;
  isNull?: boolean;
  hrEnabled?: boolean;
  onClick: (item: ListItem) => void;
};

type TableData = {
  _id: string;
  title: string;
  category?: string;
  type?: string;
};

export const Vulnerabilities = () => {
  const navigate = useNavigate();

  const [vulnerabilities, setVulnerabilities] = useState<VulnerabilityData[]>(
    [],
  );
  const [tableInfo, setTableInfo] = useState<TableData[]>([]);

  const [languagesList, setLanguagesList] = useState<ListItem[]>([]);
  const [currentLanguage, setCurrentLanguage] = useState<ListItem | null>(null);
  const [loadingLanguage, setLoadingLanguage] = useState<boolean>(true);

  const [categoriesList, setCategoriesList] = useState<ListItemCategory[]>([]);
  const [typesList, setTypesList] = useState<ListItem[]>([]);

  const [isOpenAddVuln, setIsOpenAddVuln] = useState(false);
  const openAddVulnSlidingPage = () => setIsOpenAddVuln(true);

  const [isOpenEditVuln, setIsOpenEditVuln] = useState<boolean>(false);
  const [editVuln, setEditVuln] = useState<VulnerabilityData>();
  const [selectedCategoryAddVuln, setSelectedCategoryAddVuln] =
    useState<ListItem | null>(null);

  const handleSuccessToast = (message: string) => {
    toast.success(message);
  };

  const [openModalDeleteVuln, setOpenModalDeleteVuln] = useState(false);

  const columns = [
    { header: t('title'), accessor: 'title', sortable: true, filterable: true },
    {
      header: t('category'),
      accessor: 'category',
      sortable: true,
      filterable: true,
    },
    { header: t('type'), accessor: 'type', sortable: true, filterable: true },
  ];

  const [tableData, handleSorting, setTableData] = useSortableTable<TableData>(
    tableInfo,
    columns,
  );

  const fetchVulnerabilities = useCallback(async () => {
    try {
      const dataVulnerability = await getVulnerabilities();
      setVulnerabilities(dataVulnerability.datas);
      const vulnDataTable = dataVulnerability.datas.map(
        (item: VulnerabilityData) => ({
          _id: item._id,
          title: item.details[0].title ?? '',
          category: item.category ?? t('noCategory'),
          type: item.details[0].vulnType ?? t('undefined'),
        }),
      );
      setTableData(vulnDataTable);
      setTableInfo(vulnDataTable);
    } catch (error) {
      console.error('Error:', error);
    }
  }, [setTableData]);

  const fetchLanguages = async () => {
    try {
      const dataLanguage = await getLanguages();
      const languageNames = dataLanguage.datas.map(
        (item: LanguageData, index: number) => ({
          id: index,
          value: item.locale,
          label: item.language,
        }),
      );
      setLanguagesList(languageNames);
      setCurrentLanguage(languageNames[0]);
      setLoadingLanguage(false);
    } catch (error) {
      console.error('Error:', error);
    }
  };

  const fetchTypes = async () => {
    try {
      const dataType = await getTypes();
      const typeNames = dataType.datas.map((item: TypeData, index: number) => ({
        id: index + 1,
        value: item.name,
        label: item.name,
        locale: item.locale,
      }));
      setTypesList([...typeNames]);
    } catch (error) {
      console.error('Error:', error);
    }
  };

  const fetchCategories = useCallback(async () => {
    try {
      const dataCategory = await getCategories();
      const categoryNames = dataCategory.datas.map(
        (item: CategoryData, index: number) => ({
          id: index + 1,
          value: item.name,
          label: item.name,
          onClick: (item2: ListItem) => {
            setSelectedCategoryAddVuln(item2);
            openAddVulnSlidingPage();
          },
        }),
      );
      setCategoriesList([
        {
          id: 0,
          label: t('noCategory'),
          value: '',
          isNull: true,
          hrEnabled: true,
          onClick: (item2: ListItem) => {
            setSelectedCategoryAddVuln(item2);
            openAddVulnSlidingPage();
          },
        },
        ...categoryNames,
      ]);
    } catch (error) {
      console.error('Error:', error);
    }
  }, []);

  useEffect(() => {
    void fetchVulnerabilities();
    void fetchLanguages();
    void fetchTypes();
    void fetchCategories();
  }, [fetchCategories, fetchVulnerabilities]);
  //

  //// Workaround para dropdown de filtrado, al parecer funciona bien btw
  useEffect(() => {
    const filtered = vulnerabilities
      .filter(vulnIter =>
        vulnIter.details.some(
          detail => detail.locale === currentLanguage?.value,
        ),
      )
      .map(vulnIter => {
        const index = vulnIter.details.findIndex(
          detail => detail.locale === currentLanguage?.value,
        );
        return { ...vulnIter, matchingDetailIndex: index };
      });

    const vulnDataTable: TableData[] = filtered.map(item => ({
      _id: item._id,
      title: item.details[item.matchingDetailIndex].title ?? 'noTitle',
      category: item.category ?? t('noCategory'),
      type: item.details[item.matchingDetailIndex].vulnType ?? t('undefined'),
    }));
    setTableData(vulnDataTable);
    setTableInfo(vulnDataTable);
  }, [vulnerabilities, currentLanguage, setTableData]);

  const [isOpenMerge, setIsOpenMerge] = useState(false);
  const [itemDelete, setItemDelete] = useState<TableData>();

  const confirmDeleteVulnerability = async () => {
    try {
      const response = await deleteVulnerability(itemDelete?._id ?? '');
      if (response.status === 'success') {
        handleSuccessToast(t('msg.vulnerabilityDeletedOk'));
      }
    } catch (error) {
      toast.error(t('err.failedDeleteVulnerability'));
      console.error('Error:', error);
    }
    setOpenModalDeleteVuln(false);
    void fetchVulnerabilities();
  };

  const deleteRegisterConfirmation = (item: TableData) => {
    setItemDelete(item);
    setOpenModalDeleteVuln(true);
  };

  const editRegister = (item: TableData) => {
    const vuln = vulnerabilities.find(vuln => vuln._id === item._id);
    setEditVuln(vuln);
    setIsOpenEditVuln(true);
  };

  const findRegister = (item: TableData) => {
    const sanitizedQueryParam = encodeURIComponent(item.title.trim());
    navigate(`/audits?findingTitle=${sanitizedQueryParam}`);
  };

  const keyExtractor = (item: TableData) => item._id;

  const rowActions = [
    {
      label: 'Edit',
      onClick: (item: TableData) => editRegister(item),
    },
    {
      label: 'FindAudit',
      onClick: (item: TableData) => findRegister(item),
    },
    {
      label: 'Delete',
      onClick: (item: TableData) => deleteRegisterConfirmation(item),
    },
  ];

  const [filters, handleFilterChange] = useTableFiltering<TableData>(
    tableInfo,
    columns,
    setTableData,
  );

  return (
    <div className="max-w-screen-2xl mx-auto my-6">
      <div className="fixed z-20">
        <Modal
          cancelText={t('btn.stay')}
          disablehr
          isOpen={openModalDeleteVuln}
          onCancel={() => setOpenModalDeleteVuln(false)}
          onSubmit={confirmDeleteVulnerability}
          submitText={t('btn.confirm')}
          title={t('msg.confirmSuppression')}
        >
          <span className="ml-3">{t('msg.vulnerabilityWillBeDeleted')}</span>
        </Modal>
      </div>
      <Toaster />
      <Card title={t('nav.vulnerabilities')}>
        <>
          <div className="fixed z-20">
            {isOpenAddVuln ? (
              <AddVulnerability
                categoryVuln={selectedCategoryAddVuln}
                currentLang={currentLanguage}
                handleOnSuccess={handleSuccessToast}
                handlerIsOpen={setIsOpenAddVuln}
                isOpen={isOpenAddVuln}
                languages={languagesList}
                refreshVulns={fetchVulnerabilities}
                types={typesList}
              />
            ) : null}
          </div>
          <div className="fixed z-20">
            {isOpenEditVuln && editVuln ? (
              <EditVulnerability
                categories={categoriesList}
                currentVuln={editVuln}
                handleOnSuccess={handleSuccessToast}
                handlerIsOpen={setIsOpenEditVuln}
                isOpen={isOpenEditVuln}
                languages={languagesList}
                refreshVulns={fetchVulnerabilities}
                types={typesList}
              />
            ) : null}
          </div>
          <div className="fixed z-20">
            {isOpenMerge ? (
              <MergeVulnerabilities
                handleOnSuccess={handleSuccessToast}
                handlerIsOpen={setIsOpenMerge}
                isOpen={isOpenMerge}
                languages={languagesList}
                refreshVulns={fetchVulnerabilities}
                vulnerabilities={vulnerabilities}
              />
            ) : null}
          </div>
          <UITable
            columns={columns}
            data={tableData}
            emptyState={<div>{t('err.noMatchingRecords')}</div>}
            filters={filters}
            keyExtractor={keyExtractor}
            onFilter={handleFilterChange}
            onSort={handleSorting}
            rowActions={rowActions}
          >
            <div className="mb-4 w-full">
              <VulnerabilityButtons
                categoriesList={categoriesList}
                currentLanguage={currentLanguage}
                languagesList={languagesList}
                loadingLanguage={loadingLanguage}
                setCurrentLanguage={setCurrentLanguage}
                setOpenMerge={setIsOpenMerge}
              />
            </div>
          </UITable>
        </>
      </Card>
    </div>
  );
};
