import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';

import PrimaryButton from '../../components/button/PrimaryButton';
import Card from '../../components/card/Card';
import SelectDropdown from '../../components/dropdown/SelectDropdown';
import SimpleInput from '../../components/input/SimpleInput';
import Modal from '../../components/modal/Modal';
import UITable from '../../components/table/UITable';
import { useSortableTable } from '../../hooks/useSortableTable';
import { useTableFiltering } from '../../hooks/useTableFiltering';
import {
  Client,
  createClient,
  deleteClient,
  getClients,
  getCompanies,
  NewClient,
  updateClient,
} from '../../services/data';

type Company = {
  _id?: string;
  name: string;
  shortName: string;
  logo: string;
};

type TableData = {
  _id: string;
  email: string;
  lastname: string;
  firstname: string;
  phone: string;
  cell: string;
  title: string;
  company: string;
};

type ListItem = {
  id: number;
  _id?: string;
  name?: string;
  shortName?: string;
  logo?: string;
  value: string;
};

export const Clients: React.FC = () => {
  const { t } = useTranslation();

  const columns = [
    {
      header: t('firstname'),
      accessor: 'firstname',
      sortable: true,
      filterable: true,
    },
    {
      header: t('lastname'),
      accessor: 'lastname',
      sortable: true,
      filterable: true,
    },
    { header: t('email'), accessor: 'email', sortable: true, filterable: true },
    {
      header: t('company'),
      accessor: 'company',
      sortable: true,
      render: (data?: { name: string }) =>
        data?.name ? <span>{data.name}</span> : <span>-</span>,
    },
  ];

  const [companies, setCompanies] = useState<ListItem[]>([]);
  const [apiCompanies, setApiCompanies] = useState<Company[]>([]);

  const [addModalFirstnameRequiredAlert, setAddModalFirstnameRequiredAlert] =
    useState<boolean>(false);
  const [addModalLastnameRequiredAlert, setAddModalLastnameRequiredAlert] =
    useState<boolean>(false);
  const [addModalEmailRequiredAlert, setAddModalEmailRequiredAlert] =
    useState<boolean>(false);

  const [editModalFirstnameRequiredAlert, setEditModalFirstnameRequiredAlert] =
    useState<boolean>(false);
  const [editModalLastnameRequiredAlert, setEditModalLastnameRequiredAlert] =
    useState<boolean>(false);
  const [editModalEmailRequiredAlert, setEditModalEmailRequiredAlert] =
    useState<boolean>(false);

  const [selectedCompany, setSelectedCompany] = useState<ListItem>({
    id: 0,
    _id: '',
    value: '',
  });

  const initialClientState = {
    company: null,
    firstname: '',
    lastname: '',
    email: '',
    title: '',
    phone: '',
    cell: '',
  };

  const [newClient, setNewClient] = useState<NewClient | null>(
    initialClientState,
  );

  const [clients, setClients] = useState<Client[]>([]);
  const [_loading, setLoading] = useState<boolean>(true);
  const [_error, setError] = useState<string | null>(null);

  const [selectedClient, setSelectedClient] = useState<TableData | null>(null);

  const [tableData, handleSorting, setTableData] = useSortableTable<TableData>(
    clients,
    columns, // error en useSortableTable o UITable
  );

  const [isOpenAddClientModal, setIsOpenAddClientModal] = useState(false);
  const [isOpenEditClientModal, setIsOpenEditClientModal] = useState(false);
  const [isOpenDeleteClientModal, setIsOpenDeleteClientModal] = useState(false);

  const fetchClients = useCallback(async () => {
    try {
      const data = await getClients();
      setClients(data.datas);
      setTableData(data.datas);
      setLoading(false);
    } catch (err) {
      setError('Error fetching clients');
      setLoading(false);
    }
  }, [setTableData]);

  const fetchCompanies = async () => {
    try {
      const data: { datas: Company[] } = await getCompanies();
      const filteredData = data.datas.map((item, index) => ({
        id: index + 1,
        _id: item._id ?? '',
        value: item.name,
      }));
      setCompanies(filteredData);
      setApiCompanies(data.datas);
      setSelectedCompany(filteredData[0]);
      setLoading(false);
    } catch (err) {
      setError('Error fetching company');
      setLoading(false);
    }
  };

  useEffect(() => {
    void fetchClients();
    void fetchCompanies();
  }, [fetchClients]);

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

  const handleEditClientButton = (client: TableData) => {
    const matchingCompany = apiCompanies.find(
      company => company.name === client.company,
    );

    setNewClient({
      _id: client._id,
      email: client.email,
      lastname: client.lastname,
      firstname: client.firstname,
      phone: client.phone,
      cell: client.cell,
      title: client.title,
      company: matchingCompany
        ? {
            _id: matchingCompany._id,
            name: matchingCompany.name,
            shortName: matchingCompany.shortName,
            logo: matchingCompany.logo,
          }
        : null,
    });
    setIsOpenEditClientModal(!isOpenEditClientModal);
  };

  const handleDeleteClientButton = (client: TableData) => {
    setSelectedClient(client);
    setIsOpenDeleteClientModal(!isOpenDeleteClientModal);
  };

  const rowActions = [
    {
      label: 'Edit',
      onClick: (item: TableData) => handleEditClientButton(item),
    },
    {
      label: 'Delete',
      onClick: (item: TableData) => handleDeleteClientButton(item),
    },
  ];

  const [filters, handleFilterChange] = useTableFiltering<TableData>(
    clients,
    columns, // error en useSortableTable o UITable
    setTableData,
  );

  const handleCancelAddClient = () => {
    setNewClient(initialClientState);
    setIsOpenAddClientModal(!isOpenAddClientModal);

    setAddModalFirstnameRequiredAlert(false);
    setAddModalLastnameRequiredAlert(false);
    setAddModalEmailRequiredAlert(false);
  };

  const handleSubmitAddClient = async () => {
    if (!newClient) {
      return;
    }

    if (
      selectedCompany.id === 0 &&
      selectedCompany.value === '' &&
      selectedCompany._id === ''
    ) {
      return;
    }

    let isValid = true;
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    if (!newClient.firstname || newClient.firstname.trim() === '') {
      setAddModalFirstnameRequiredAlert(true);
      isValid = false;
    }

    if (!newClient.lastname || newClient.lastname.trim() === '') {
      setAddModalLastnameRequiredAlert(true);
      isValid = false;
    }

    if (!newClient.email || newClient.email.trim() === '') {
      setAddModalEmailRequiredAlert(true);
      isValid = false;
    }

    if (!isValid) {
      toast.error(t('msg.fieldRequired'));
      return;
    }

    if (!emailRegex.test(newClient.email)) {
      toast.error(t('msg.invalidEmail'));
      return;
    }

    try {
      const matchingCompany = apiCompanies.find(
        company => company._id === selectedCompany._id,
      );

      if (!matchingCompany) {
        setError('Selected company not found');
        return;
      }

      const clientToCreate = {
        ...newClient,
        company: {
          _id: matchingCompany._id,
          name: matchingCompany.name,
          shortName: matchingCompany.shortName,
          logo: matchingCompany.logo,
        },
      };

      await createClient(clientToCreate);
      toast.success(t('msg.clientCreatedOk'));
      setIsOpenAddClientModal(!isOpenAddClientModal);

      setNewClient(initialClientState);
      void fetchClients();
    } catch (error) {
      toast.error(t('msg.clientEmailError'));
      setError('Error creating client');
      console.error('Error:', error);
    }
  };

  const handleCancelEditClient = () => {
    setNewClient(initialClientState);
    setIsOpenEditClientModal(!isOpenEditClientModal);

    setEditModalFirstnameRequiredAlert(false);
    setEditModalLastnameRequiredAlert(false);
    setEditModalEmailRequiredAlert(false);
  };

  const handleSubmitEditClient = async () => {
    if (!newClient) {
      return;
    }

    if (
      selectedCompany.id === 0 &&
      selectedCompany.value === '' &&
      selectedCompany._id === ''
    ) {
      return;
    }

    let isValid = true;
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    if (!newClient.firstname || newClient.firstname.trim() === '') {
      setEditModalFirstnameRequiredAlert(true);
      isValid = false;
    }

    if (!newClient.lastname || newClient.lastname.trim() === '') {
      setEditModalLastnameRequiredAlert(true);
      isValid = false;
    }

    if (!newClient.email || newClient.email.trim() === '') {
      setEditModalEmailRequiredAlert(true);
      isValid = false;
    }

    if (!isValid) {
      toast.error(t('msg.fieldRequired'));
      return;
    }

    if (!emailRegex.test(newClient.email)) {
      toast.error(t('msg.invalidEmail'));
      return;
    }

    try {
      const matchingCompany = apiCompanies.find(
        company => company._id === selectedCompany._id,
      );

      if (!matchingCompany) {
        setError('Selected company not found');
        return;
      }

      const clientToUpdate = {
        ...newClient,
        company: {
          _id: matchingCompany._id,
          name: matchingCompany.name,
          shortName: matchingCompany.shortName,
          logo: matchingCompany.logo,
        },
      };

      await updateClient(clientToUpdate);
      toast.success(t('msg.clientUpdatedOk'));
      setIsOpenEditClientModal(!isOpenEditClientModal);

      setNewClient(initialClientState);
      void fetchClients();
    } catch (error) {
      toast.error(t('msg.clientEmailError'));
      setError('Error updating client');
      console.error('Error:', error);
    }
  };

  const handleCancelDeleteClient = () => {
    setIsOpenDeleteClientModal(!isOpenDeleteClientModal);
  };

  const handleSubmitDeleteClient = async () => {
    if (selectedClient?._id) {
      try {
        await deleteClient(selectedClient._id);
        toast.success(t('msg.clientDeletedOk'));
      } catch (error) {
        setError('Error deleting client');
        console.error('Error:', error);
      }
      setSelectedClient(null);
      setIsOpenDeleteClientModal(!isOpenDeleteClientModal);
      void fetchClients();
    }
  };

  const handleInputChange = (name: string, value: string) => {
    setNewClient(prevState => {
      if (!prevState) {
        return null;
      } else {
        return {
          ...prevState,
          [name]: value,
        };
      }
    });
  };

  const handleCompanyChange = (company: ListItem) => {
    setSelectedCompany(company);
    setNewClient(prevState => {
      if (!prevState) {
        return null;
      } else {
        return {
          ...prevState,
          company: {
            id: company.id,
            _id: company._id,
            name: company.name ?? '',
            shortName: company.shortName ?? '',
            logo: company.logo ?? '',
          },
        };
      }
    });
  };

  return (
    <>
      <Card title={t('clients')}>
        <>
          <div className="flex justify-end mb-2 mr-2">
            <PrimaryButton
              onClick={() => setIsOpenAddClientModal(!isOpenAddClientModal)}
            >
              {t('addClient')}
            </PrimaryButton>
          </div>
          <UITable
            columns={columns} // error en useSortableTable o UITable
            data={tableData}
            emptyState={<div>{t('err.noMatchingRecords')}</div>}
            filters={filters}
            keyExtractor={keyExtractor}
            onFilter={handleFilterChange}
            onSort={handleSorting}
            rowActions={rowActions}
          />
        </>
      </Card>
      <Modal
        // eslint-disable-next-line sonarjs/no-duplicate-string
        cancelText={t('btn.cancel')}
        isOpen={isOpenAddClientModal}
        onCancel={handleCancelAddClient}
        onSubmit={handleSubmitAddClient}
        submitText={t('btn.create')}
        title={t('addClient')}
      >
        <>
          <SelectDropdown
            items={companies}
            onChange={handleCompanyChange}
            selected={selectedCompany}
            title={t('company')}
          />
          <SimpleInput
            id="firstname"
            label={t('firstname')}
            name="firstname"
            onChange={value => handleInputChange('firstname', value)}
            placeholder={t('firstname')}
            requiredAlert={addModalFirstnameRequiredAlert}
            requiredField
            type="text"
            value={newClient?.firstname ?? ''}
          />
          <SimpleInput
            id="lastname"
            label={t('lastname')}
            name="lastname"
            onChange={value => handleInputChange('lastname', value)}
            placeholder={t('lastname')}
            requiredAlert={addModalLastnameRequiredAlert}
            requiredField
            type="text"
            value={newClient?.lastname ?? ''}
          />
          <SimpleInput
            id="email"
            label={t('email')}
            name="email"
            onChange={value => handleInputChange('email', value)}
            placeholder={t('email')}
            requiredAlert={addModalEmailRequiredAlert}
            requiredField
            type="text"
            value={newClient?.email ?? ''}
          />
          <SimpleInput
            id="title"
            label={t('title')}
            name="title"
            onChange={value => handleInputChange('title', value)}
            placeholder={t('title')}
            type="text"
            value={newClient?.title ?? ''}
          />
          <SimpleInput
            id="phone"
            label={t('phone')}
            name="phone"
            onChange={value => handleInputChange('phone', value)}
            placeholder={t('phone')}
            type="text"
            value={newClient?.phone ?? ''}
          />
          <SimpleInput
            id="cell"
            label={t('cell')}
            name="cell"
            onChange={value => handleInputChange('cell', value)}
            placeholder={t('cell')}
            type="text"
            value={newClient?.cell ?? ''}
          />
        </>
      </Modal>
      <Modal
        cancelText={t('btn.cancel')}
        isOpen={isOpenEditClientModal}
        onCancel={handleCancelEditClient}
        onSubmit={handleSubmitEditClient}
        submitText={t('btn.update')}
        title={t('editClient')}
      >
        <>
          <SelectDropdown
            items={companies}
            onChange={handleCompanyChange}
            selected={selectedCompany}
            title={t('company')}
          />
          <SimpleInput
            id="firstname"
            label={t('firstname')}
            name="firstname"
            onChange={value => handleInputChange('firstname', value)}
            placeholder={t('firstname')}
            requiredAlert={editModalFirstnameRequiredAlert}
            requiredField
            type="text"
            value={newClient?.firstname ?? ''}
          />
          <SimpleInput
            id="lastname"
            label={t('lastname')}
            name="lastname"
            onChange={value => handleInputChange('lastname', value)}
            placeholder={t('lastname')}
            requiredAlert={editModalLastnameRequiredAlert}
            requiredField
            type="text"
            value={newClient?.lastname ?? ''}
          />
          <SimpleInput
            id="email"
            label={t('email')}
            name="email"
            onChange={value => handleInputChange('email', value)}
            placeholder={t('email')}
            requiredAlert={editModalEmailRequiredAlert}
            requiredField
            type="text"
            value={newClient?.email ?? ''}
          />
          <SimpleInput
            id="title"
            label={t('title')}
            name="title"
            onChange={value => handleInputChange('title', value)}
            placeholder={t('title')}
            type="text"
            value={newClient?.title ?? ''}
          />
          <SimpleInput
            id="phone"
            label={t('phone')}
            name="phone"
            onChange={value => handleInputChange('phone', value)}
            placeholder={t('phone')}
            type="text"
            value={newClient?.phone ?? ''}
          />
          <SimpleInput
            id="cell"
            label={t('cell')}
            name="cell"
            onChange={value => handleInputChange('cell', value)}
            placeholder={t('cell')}
            type="text"
            value={newClient?.cell ?? ''}
          />
        </>
      </Modal>
      <Modal
        cancelText={t('btn.cancel')}
        isOpen={isOpenDeleteClientModal}
        onCancel={handleCancelDeleteClient}
        onSubmit={handleSubmitDeleteClient}
        submitText={t('btn.confirm')}
        title={t('msg.confirmSuppression')}
      >
        <p>
          {t('client') +
            ` <<${selectedClient?.firstname} ` +
            `${selectedClient?.lastname}>> ` +
            t('msg.deleteNotice') +
            '!'}
        </p>
      </Modal>
    </>
  );
};
