/* eslint-disable import/extensions */
/* eslint-disable sonarjs/no-duplicate-string */
import { CheckIcon } from '@heroicons/react/20/solid';
import clsx from 'clsx';
import { t } from 'i18next';
import {
  Check,
  ChevronDown,
  ChevronUp,
  FilePlus2,
  Plus,
  Users,
} from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import { Link, useParams } from 'react-router-dom';
import { toast } from 'sonner';

import { EncryptionModal } from '@/routes/audits/edit/general/EncryptionModal';
import { AuditSection, encryptPDF, getAuditById } from '@/services/audits';

import { Section } from '../../services/data';
import DefaultRadioGroup from '../button/DefaultRadioGroup';
import DropdownButton, { ListItem } from '../button/DropdownButton';

type MenuItem = {
  name: string;
  icon: React.ComponentType<{ className?: string }>;
  value: string;
  additionalIcon?: React.ComponentType<{ className?: string }>;
};

type Finding = {
  id: number;
  name: string;
  category: string;
  severity: string;
  identifier: string;
  status: number;
};

type SortOption = {
  id: number;
  value: string;
};

type SortOrderOption = {
  id: string;
  label: string;
  value: string;
};

type ConnectedUser = {
  id: number;
  name: string;
  online: boolean;
};

type AuditSidebarProps = {
  activeItem: string;
  setActiveItem: (item: string) => void;
  isCollapsed: boolean;
  setIsCollapsed: (collapsed: boolean) => void;
  isListVisible: boolean;
  setIsListVisible: (visible: boolean) => void;
  auditSections: AuditSection[];
  sections: Section[];
  sortBy: SortOption | null;
  setSortBy: (option: SortOption | null) => void;
  sortOrder: string;
  setSortOrder: (order: string) => void;
  menuItems: MenuItem[];
  findings: Finding[];
  sortOptions: SortOption[];
  sortOrderOptions: SortOrderOption[];
  connectedUsers: ConnectedUser[];
};

const severityColorMap: Record<string, string> = {
  L: 'bg-green-600',
  M: 'bg-yellow-500',
  H: 'bg-orange-500',
  C: 'bg-red-600',
  default: 'bg-gray-600',
};

const getSeverityColor = (severity: string) => {
  return severityColorMap[severity] ?? severityColorMap.default;
};

const AuditSidebar = ({
  activeItem,
  setActiveItem,
  auditSections,
  isCollapsed,
  setIsCollapsed,
  isListVisible,
  setIsListVisible,
  sections,
  sortOrder,
  setSortOrder,
  menuItems,
  findings,
  sortOrderOptions,
  connectedUsers,
}: AuditSidebarProps) => {
  const handleSetIsCollapsed = useCallback(
    (collapsed: boolean) => setIsCollapsed(collapsed),
    [setIsCollapsed],
  );
  const handleSetActiveItem = useCallback(
    (item: string) => setActiveItem(item),
    [setActiveItem],
  );
  const severityOrder: Record<string, number> = {
    C: 1,
    H: 2,
    M: 3,
    L: 4,
    I: 5,
  };

  const [isOpenModal, setIsOpenModal] = useState(false);
  const handleSetIsOpenModal = useCallback(
    (isOpen: boolean) => setIsOpenModal(isOpen),
    [],
  );
  const [isGeneratingPDF, setIsGeneratingPDF] = useState(false);

  const [auditName, setAuditName] = useState('');
  const { auditId } = useParams();

  useEffect(() => {
    getAuditById(auditId)
      .then(audit => {
        setAuditName(audit.datas.name);
      })
      .catch(console.error);
  }, [auditId]);

  const fileTypes: ListItem[] = [
    {
      id: 1,
      value: 'docx',
      label: 'docx',
      onClick: () =>
        window.open(
          `${import.meta.env.VITE_API_URL}/api/audits/${auditId}/generate`,
          '_blank',
        ),
    },
    {
      id: 2,
      value: 'pdf',
      label: 'pdf',
      onClick: () =>
        window.open(
          `${import.meta.env.VITE_API_URL}/api/audits/${auditId}/generate/pdf`,
          '_blank',
        ),
    },
    {
      id: 3,
      value: 'json',
      label: 'json',
      onClick: () =>
        window.open(
          `${import.meta.env.VITE_API_URL}/api/audits/${auditId}/generate/json`,
          '_blank',
        ),
    },
    {
      id: 4,
      value: 'csv',
      label: 'csv',
      onClick: () =>
        window.open(
          `${import.meta.env.VITE_API_URL}/api/audits/${auditId}/generate/csv`,
          '_blank',
        ),
    },
    {
      id: 5,
      value: 'pdf/encrypted',
      label: `pdf (${t('encrypted')})`,
      onClick: () => setIsOpenModal(true),
    },
  ];

  findings.sort((a, b) => {
    const orderMultiplier = sortOrder === 'Ascending' ? -1 : 1;
    return (
      orderMultiplier * (severityOrder[a.severity] - severityOrder[b.severity])
    );
  });

  const handleSubmitEncrypt = async (password: string) => {
    setIsGeneratingPDF(true);

    const blob = await encryptPDF(password, auditId ?? '').catch(
      (error: Error) => {
        toast.error(t('err.errorGeneratingPdf'));
        console.error('Error generating PDF:', error);
      },
    );
    if (blob) {
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = `${auditName}.pdf`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);
      toast.success(t('msg.auditEncryptedOk'));
    } else {
      toast.error(t('err.errorGeneratingPdf'));
    }
    setIsOpenModal(false);
    setIsGeneratingPDF(false);
  };

  return (
    <div
      className={clsx(
        'flex flex-col h-screen bg-gray-900 text-gray-100 transition-all duration-300',
        isCollapsed ? 'w-20' : 'w-64',
      )}
    >
      <div className="flex items-center justify-between p-4 border-b border-gray-800">
        <div className={clsx('m-2', isCollapsed && 'sr-only')}>
          <DropdownButton items={fileTypes} placeholder={t('export')} />
        </div>
        <EncryptionModal
          auditName={auditName}
          handleSubmitEncrypt={handleSubmitEncrypt}
          isGeneratingPDF={isGeneratingPDF}
          isOpen={isOpenModal}
          onCancel={() => handleSetIsOpenModal(false)}
        />
        <button
          aria-label={isCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}
          className="text-gray-400 hover:text-gray-100 hover:bg-gray-800 p-2 rounded-full transition-colors duration-200 z-10"
          onClick={() => handleSetIsCollapsed(!isCollapsed)}
          type="button"
        >
          {isCollapsed ? (
            <ChevronDown className="h-5 w-5" />
          ) : (
            <ChevronUp className="h-5 w-5" />
          )}
        </button>
      </div>
      <nav className="flex-1 overflow-y-auto py-4">
        <ul className="space-y-2">
          {menuItems.map(item => (
            <li key={item.name}>
              <Link
                className={clsx(
                  'w-full flex items-center justify-start gap-3 px-4 py-2 text-left text-sm font-medium rounded-lg transition-colors duration-200',
                  'hover:bg-gray-800',
                  activeItem === item.name
                    ? 'bg-gray-800 text-white'
                    : 'text-gray-400',
                )}
                onClick={() => {
                  handleSetActiveItem(item.name);
                }}
                to={item.value}
              >
                <item.icon className="h-5 w-5 flex-shrink-0" />
                <span
                  className={clsx(
                    'flex-1 transition-opacity',
                    isCollapsed && 'opacity-0 w-0 overflow-hidden',
                  )}
                >
                  {item.name}
                </span>
                {item.additionalIcon ? (
                  <item.additionalIcon
                    className={clsx(
                      'h-4 w-4',
                      isCollapsed ? 'ml-0' : 'ml-auto',
                    )}
                  />
                ) : null}
              </Link>
            </li>
          ))}
        </ul>
        <div className={clsx('mt-4 px-4', isCollapsed && 'px-2')}>
          <div className={clsx('mb-4 font-thin', isCollapsed && 'sr-only')}>
            <p className="text-gray-400 text-lg">{t('sortBy')} CVSS</p>
            <DefaultRadioGroup
              name="sortOrder"
              onChange={setSortOrder}
              options={sortOrderOptions}
              value={sortOrder}
            />
          </div>
          <ul className="space-y-2">
            {findings.map(finding => (
              <Link
                className="flex items-center gap-2 text-sm hover:bg-gray-800 transition-colors duration-200 rounded-lg"
                key={finding.id}
                to={`findings/${finding.identifier}`}
              >
                <li className="flex items-center gap-2 text-sm px-4 py-2">
                  <span
                    className={`w-6 h-6 flex items-center justify-center ${getSeverityColor(finding.severity)} text-white rounded-full font-medium`}
                  >
                    {finding.severity}
                  </span>
                  <span
                    className={clsx('text-gray-300', isCollapsed && 'sr-only')}
                  >
                    {finding.name}
                  </span>
                  {finding.status === 0 && !isCollapsed ? (
                    <span>
                      <CheckIcon className="h-6 w-6 text-gray-500" />
                    </span>
                  ) : null}
                </li>
              </Link>
            ))}
          </ul>
        </div>
      </nav>
      <div className="p-4 border-t border-gray-800">
        <div className="mb-2 flex gap-2">
          <button
            className="w-full flex items-center justify-start gap-3 text-gray-400 hover:text-gray-100 hover:bg-gray-800 px-4 py-2 rounded-lg transition-colors duration-200 whitespace-nowrap"
            type="button"
          >
            <FilePlus2 className="h-5 w-5 flex-shrink-0" />
            <span
              className={clsx(
                'transition-opacity',
                isCollapsed && 'opacity-0 w-0 overflow-hidden',
              )}
            >
              {t('customSections')}
            </span>
          </button>
          {!isCollapsed ? (
            <button
              className="flex items-center justify-center text-gray-400 hover:text-gray-100 hover:bg-gray-800 rounded-full transition-colors duration-200 w-10 h-10"
              onClick={() => setIsListVisible(!isListVisible)}
              type="button"
            >
              <Plus className="h-5 w-5 flex-shrink-0" />
            </button>
          ) : null}
          <div className="relative">
            {isListVisible ? (
              <ul
                className="absolute z-10 mt-2 bg-gray-800 rounded-lg p-2 space-y-1 shadow-lg border border-gray-700"
                style={{ minWidth: '200px' }}
              >
                {sections.map(section => {
                  const isSelected = auditSections.some(
                    auditSection => auditSection.field === section.field,
                  );

                  return (
                    <button
                      className={clsx(
                        'w-full text-left text-gray-300 hover:bg-gray-700 rounded-md p-2 flex items-center gap-2',
                        isSelected && 'bg-gray-700 text-white',
                      )}
                      key={section.field}
                      onClick={() => setIsListVisible(!isListVisible)}
                      type="button"
                    >
                      {section.icon.startsWith('fa-') ? (
                        <i className={`fa ${section.icon}`} />
                      ) : (
                        <i className="material-icons">{section.icon}</i>
                      )}
                      <span>{section.name}</span>
                      {isSelected ? (
                        <Check className="h-5 w-5 flex-shrink-0 ml-auto " />
                      ) : null}
                    </button>
                  );
                })}
              </ul>
            ) : null}
          </div>
        </div>

        {!isCollapsed ? (
          <ul className="space-y-2">
            {auditSections.map(section => (
              <li key={section.name}>
                <Link
                  className={clsx(
                    'flex items-center gap-2 text-sm w-full justify-start px-4 py-2 text-left font-medium rounded-lg transition-colors duration-200',
                    activeItem === section.name
                      ? 'bg-gray-800 text-white'
                      : 'text-gray-400',
                    'hover:bg-gray-800',
                  )}
                  onClick={() => {
                    setActiveItem(section.name);
                  }}
                  to={`sections/${section._id}`}
                >
                  {section.icon?.startsWith('fa-') ? (
                    <i className={`fa ${section.icon}`} />
                  ) : (
                    <i className="material-icons">{section.icon}</i>
                  )}
                  <span className={clsx('flex-1 transition-opacity')}>
                    {section.name}
                  </span>
                </Link>
              </li>
            ))}
          </ul>
        ) : null}
      </div>
      <div className="p-4 border-t border-gray-800">
        <div className="mb-2">
          <button
            className="w-full flex items-center justify-start gap-3 text-gray-400 hover:text-gray-100 hover:bg-gray-800 px-4 py-2 rounded-lg transition-colors duration-200"
            type="button"
          >
            <Users className="h-5 w-5 flex-shrink-0" />
            <span
              className={clsx(
                'transition-opacity',
                isCollapsed && 'opacity-0 w-0 overflow-hidden',
              )}
            >
              {t('usersConnected')}
            </span>
          </button>
        </div>
        <ul className="space-y-2">
          {connectedUsers.map(user => (
            <li
              className="flex items-center gap-2 text-sm px-4 py-1"
              key={user.id}
            >
              <span
                className={clsx(
                  'w-2 h-2 rounded-full flex-shrink-0',
                  user.online ? 'bg-green-500' : 'bg-gray-500',
                )}
              />
              <span className={clsx('text-gray-300', isCollapsed && 'sr-only')}>
                {user.name}
              </span>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
};

export default AuditSidebar;
