'use client';

import React, { useEffect, useRef, useState, useCallback } from 'react';
import {
  Radio,
  RadioGroup,
  FormControlLabel,
  Typography,
  Grid,
  Box,
  FormHelperText,
  CircularProgress,
  Alert,
} from '@mui/material';
import {
  faFileArrowUp,
} from '@fortawesome/free-solid-svg-icons';
import { formFields } from '../utils/form-fields-contract';
import FontAwesome from '@/shared/components/fontawesome';
import FormField from '@/shared/components/form/form-field';
import { FormFieldType, ModeType, TableColumn, TableType } from '@/shared/types/common';
import { AddButton } from '@/shared/components/table/styles';
import EditExportButtons from '@/shared/components/form/edit-export-buttons';
import ActionButtons from '@/shared/components/form/buttons-action';
import { CONTRACT_STATUS, ContractList, ContractRequest, mapContractToRequest } from '@/shared/types/contract';
import { FormikTouched, useFormik } from 'formik';
import { contractSchema } from '../utils/contract-validation';
import FormContainer from '@/layouts/form/form-container';
import ConditionalComponent from '../../../components/table/ConditionalComponent';
import { useContractStore } from '@/shared/api/stores/admin-service/contractStore';
import { useInfrastructureStore } from '@/shared/api/stores/admin-service/infrastructureStore';
import { LotNumbers } from '@/shared/types/infrastructure';
import { useSnackbar } from 'notistack';
import ContratCircuitsTable from '../components/contrat-circuits-table';
import { useClientStore } from '@/shared/api/stores/userStore';
import { IClientDropdownList } from '@/shared/types/client';
import CreateClientModal from '@/shared/components/dialog/create-client-modal';

interface ContractFormProps {
  contrat: ContractList;
  mode: ModeType;
  onEdit: (updatedContract: ContractRequest) => void;
  onClose: (isSaved: boolean) => void;
  tableHead: TableColumn[];
  updateTabContent?: (tabId: string, newContent: ContractRequest) => void
  tabId?: string
}
export interface RenderFieldOptions {
  onAddClient?: () => void;
}
export default function ContractForm({
  contrat,
  mode,
  onClose,
  onEdit,
  tableHead,
  updateTabContent,
  tabId,
}: ContractFormProps) {
  const isReadOnly = mode === 'view';
  const { enqueueSnackbar } = useSnackbar();

  const [contractFormData, setContractFormData] = useState<ContractRequest>({} as ContractRequest);

  const [agencyOptions, setAgencyOptions] = useState<{ value: string; label: string }[]>([]);
  const [departmentOptions, setDepartmentOptions] = useState<{ value: string; label: string }[]>([]);
  const [lotOptions, setLotOptions] = useState<{ value: string; label: string }[]>([]);
  const [clientOptions, setClientOptions] = useState<{ value: string; label: string }[]>([]);

  const [selectedFileName, setSelectedFileName] = useState<string>('');

  const [titleAvailability, setTitleAvailability] = useState<{ message: string; isAvailable: boolean } | null>(null);
  const [codeAvailability, setCodeAvailability] = useState<{ message: string; isAvailable: boolean } | null>(null);

  const [clientDepartmentId, setClientDepartmentId] = useState<string>();

  const [openClientModal, setOpenClientModal] = useState(false);
  const handleAddClient = () => setOpenClientModal(true);
  const handleCloseClientModal = () => setOpenClientModal(false);


  const fileInputRef = useRef<HTMLInputElement>(null);

  const {
    error,
    clearError,
    getContractById,
    createContract,
    updateContract,
    existsContractByTitleLoading,
    existsContractByTitle,
    existsContractByCodeLoading,
    existsContractByCode,
  } = useContractStore();

  const {
    error: infrastructureStoreError,
    clearError: clearInfrastructureStoreError,
    departmentHexColorById,
    getDepartmentHexColorById,
    departmentNameIdByDeparmentId,
    getAgencyNameIdByDepartmentId,
    agencyNameIdByDeparmentId,
    getLotsNumberIdByDepartmentId,
    lotsNumberIdByDeparmentId,
    getDepartmentNameIdByDepartmentId,
  } = useInfrastructureStore();

  const {
    clientsDropdownList,
    getAllClientsDropdownList
  } = useClientStore();

  const handleFormSubmit = async (values: ContractRequest) => {
    if (titleAvailability != null && !titleAvailability.isAvailable) {
      enqueueSnackbar('Veuillez entrer un nom valide !', { variant: 'error' });
      return;
    }
    if (formik.values.contractCode) {
      if (codeAvailability != null && !codeAvailability.isAvailable) {
        enqueueSnackbar('Veuillez entrer un code valide !', { variant: 'error' });
        return;
      }
    }
    if (mode === 'edit') {
      try {
        await updateContract(contrat.id, values);
        onClose(true);
        enqueueSnackbar('Contrat modifié avec succès', { variant: 'success' });
      } catch (error: any) {
        enqueueSnackbar(error.message, { variant: 'error' });
        clearError();
        return;
      }
    } else if (mode === 'add' || mode === 'copy') {
      try {
        await createContract(values);
        onClose(true);
        enqueueSnackbar('Contrat créé avec succès', { variant: 'success' });
      } catch (error: any) {
        enqueueSnackbar(error.message, { variant: 'error' });
        clearError();
        return;
      }
    }
  };

  const formik = useFormik<ContractRequest>({
    initialValues: contractFormData,
    validationSchema: contractSchema,
    enableReinitialize: true,
    onSubmit: handleFormSubmit
  });

  const getInitialValues = async () => {
    if (contrat.id && mode !== 'add') {
      const contract = await getContractById(contrat.id);
      if (contract) {
        if (contract.departmentId) {
          formik.setFieldValue('clientId', String(contract.clientId));
          setClientDepartmentId(String(contract.departmentId));
        }
        const mappedContract = mapContractToRequest(contract);
        setContractFormData(mappedContract);
      }
    }
  }

  useEffect(() => {
    getAllClientsDropdownList();
    getInitialValues();
  }, []);

  const changeClientDepartmentId = (clientId: string) => {
    const client = clientsDropdownList.find((client: IClientDropdownList) => client.id === Number(clientId));
    if (client) {
      if (clientDepartmentId !== client.departmentId) {
        setClientDepartmentId(client.departmentId);
      }
    } else {
      setClientDepartmentId(undefined);
    }
    formik.setFieldValue('departmentId', '');
    formik.setFieldValue('agencyId', '');
    formik.setFieldValue('contractColor', '');
    formik.setFieldValue('lotsId', []);
  }

  useEffect(() => {
    if (clientsDropdownList.length > 0) {
      setClientOptions(clientsDropdownList.map((client: IClientDropdownList) => ({
        value: String(client.id),
        label: client.firstname + ' ' + client.lastname
      })));
    }
  }, [clientsDropdownList]);

  useEffect(() => {
    if (clientDepartmentId) {
      getDepartmentNameIdByDepartmentId(Number(clientDepartmentId));
      getDepartmentHexColorById(String(clientDepartmentId));
      getAgencyNameIdByDepartmentId(Number(clientDepartmentId));
      getLotsNumberIdByDepartmentId(Number(clientDepartmentId));
    }
  }, [clientDepartmentId]);

  useEffect(() => {
    if (departmentNameIdByDeparmentId?.id) {
      const departmentsOptions: { value: string; label: string }[] = [{
        value: String(departmentNameIdByDeparmentId.id),
        label: departmentNameIdByDeparmentId.name
      }];
      setDepartmentOptions(departmentsOptions);
      formik.setFieldValue('departmentId', String(departmentNameIdByDeparmentId.id))
    } else {
      setDepartmentOptions([]);
      formik.setFieldValue('departmentId', '')
    }
  }, [departmentNameIdByDeparmentId]);

  useEffect(() => {
    if (departmentHexColorById) {
      formik.setFieldValue('contractColor', String(departmentHexColorById));
    }
  }, [departmentHexColorById]);

  useEffect(() => {
    if (agencyNameIdByDeparmentId?.id) {
      const agenciesOptions: { value: string; label: string }[] = [{
        value: String(agencyNameIdByDeparmentId.id),
        label: agencyNameIdByDeparmentId.name
      }];
      setAgencyOptions(agenciesOptions);
      formik.setFieldValue('agencyId', String(agencyNameIdByDeparmentId.id))
    } else {
      setAgencyOptions([]);
      formik.setFieldValue('agencyId', '')
    }
  }, [agencyNameIdByDeparmentId]);

  useEffect(() => {
    if (lotsNumberIdByDeparmentId.length > 0) {
      const lotsOptions = lotsNumberIdByDeparmentId.map((lot: LotNumbers) => ({
        value: String(lot.id),
        label: lot.number
      }));
      setLotOptions(lotsOptions);
    } else {
      setLotOptions([]);
    }
  }, [lotsNumberIdByDeparmentId]);

  useEffect(() => {
    if (mode === 'add') {
      setContractFormData({} as ContractRequest);
      formik.resetForm();
    }
  }, []);

  const titleTimeoutRef = useRef<NodeJS.Timeout>();
  const codeTimeoutRef = useRef<NodeJS.Timeout>();

  const checkContractTitle = useCallback((title: string) => {
    if (titleTimeoutRef.current) {
      clearTimeout(titleTimeoutRef.current);
    }

    if (!title) {
      setTitleAvailability(null);
      return;
    }

    const trimmedTitle = title.trim();
    if (trimmedTitle === '') {
      setTitleAvailability(null);
      return;
    }

    titleTimeoutRef.current = setTimeout(() => {
      const verifyTitle = async () => {
        try {
          const exists = mode === 'edit'
            ? await existsContractByTitle(trimmedTitle, Number(contrat.id))
            : await existsContractByTitle(trimmedTitle);

          setTitleAvailability({
            message: exists ? 'Le titre du contrat existe déjà' : 'Le titre du contrat est disponible',
            isAvailable: !exists
          });
        } catch (error) {
          setTitleAvailability(null);
        }
      };

      verifyTitle();
    }, 500);
  }, [mode, contrat.id, existsContractByTitle]);

  const checkContractCode = useCallback((code: string) => {
    if (codeTimeoutRef.current) {
      clearTimeout(codeTimeoutRef.current);
    }

    if (!code) {
      setCodeAvailability(null);
      return;
    }

    const trimmedCode = code.trim();
    if (trimmedCode === '') {
      setCodeAvailability(null);
      return;
    }

    codeTimeoutRef.current = setTimeout(() => {
      const verifyCode = async () => {
        try {
          const exists = mode === 'edit'
            ? await existsContractByCode(trimmedCode, Number(contrat.id))
            : await existsContractByCode(trimmedCode);

          setCodeAvailability({
            message: exists ? 'Le code du contrat existe déjà' : 'Le code du contrat est disponible',
            isAvailable: !exists
          });
        } catch (error) {
          setCodeAvailability(null);
        }
      };

      verifyCode();
    }, 500);
  }, [mode, contrat.id, existsContractByCode]);

  useEffect(() => {
    return () => {
      if (titleTimeoutRef.current) {
        clearTimeout(titleTimeoutRef.current);
      }
      if (codeTimeoutRef.current) {
        clearTimeout(codeTimeoutRef.current);
      }
    };
  }, []);

  useEffect(() => {
    if (updateTabContent && tabId && (mode !== "view")) {
      updateTabContent(tabId, formik.values)
    }
  }, [formik.values, updateTabContent, tabId, mode])

  const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
    const files = event.target.files;
    if (files && files.length > 0) {
      const file = files[0];
      setSelectedFileName(file.name);
    }
  };

  const handleImportClick = () => {
    fileInputRef.current?.click();
  };

  useEffect(() => {
    if (error) {
      enqueueSnackbar(error, { variant: 'error' });
      clearError();
    }
  }, [error, enqueueSnackbar, clearError]);

  useEffect(() => {
    if (infrastructureStoreError) {
      enqueueSnackbar(infrastructureStoreError, { variant: 'error' });
      clearInfrastructureStoreError();
    }
  }, [infrastructureStoreError, enqueueSnackbar, clearInfrastructureStoreError]);

  const renderField = (field: FormFieldType<ContractRequest>, options?: RenderFieldOptions) => {
    const handleChange = (name: string, value: any) => {
      formik.setFieldValue(name, value);

      if (name === 'title') {
        checkContractTitle(value);
      }

      if (name === 'contractCode') {
        checkContractCode(value);
      }

      if (name === 'clientId') {
        changeClientDepartmentId(value);
      }
    };

    return (
      <>
        <FormField
          field={field}
          value={
            field.name === 'agencyId' ? String(formik.values[field.name as keyof ContractRequest]) :
              field.name === 'departmentId' ? String(formik.values[field.name as keyof ContractRequest]) :
                field.name === 'lotsId' ? (Array.isArray(formik.values[field.name as keyof ContractRequest]) ? formik.values[field.name as keyof ContractRequest] : []) :
                  field.name === 'clientId' ? String(formik.values[field.name as keyof ContractRequest]) :
                    formik.values[field.name as keyof ContractRequest]
          }
          onChange={handleChange}
          error={
            formik.touched[field.name as keyof ContractRequest]
              ? (formik.errors[field.name as keyof ContractRequest] as string | undefined)
              : undefined
          }
          onBlur={formik.handleBlur}
          isReadOnly={isReadOnly || field.name === 'contractColor' ||
            field.name === 'departmentId' || field.name === 'agencyId'
          }
          onAddClient={options?.onAddClient}
        />
        <ConditionalComponent isValid={field.name === 'title'}>
          <FormHelperText
            sx={{
              color: existsContractByTitleLoading ? 'text.secondary' : (titleAvailability?.isAvailable ? 'success.main' : 'error.main'),
              marginTop: '4px',
              display: 'flex',
              alignItems: 'center'
            }}
          >
            <ConditionalComponent isValid={existsContractByTitleLoading}>
              <Box sx={{ display: 'flex', alignItems: 'center' }}>
                <Box
                  sx={{
                    width: '16px',
                    height: '16px',
                    border: '2px solid #f3f3f3',
                    borderTop: '2px solid #746CD4',
                    borderRadius: '50%',
                    animation: 'spin 1s linear infinite',
                    marginRight: '8px',
                    '@keyframes spin': {
                      '0%': { transform: 'rotate(0deg)' },
                      '100%': { transform: 'rotate(360deg)' }
                    }
                  }}
                />
                <Typography sx={{ color: '#746CD4' }}>
                  Vérification en cours...
                </Typography>
              </Box>
            </ConditionalComponent>
            <ConditionalComponent isValid={!existsContractByTitleLoading}>
              {titleAvailability?.message}
            </ConditionalComponent>
          </FormHelperText>
        </ConditionalComponent>
        <ConditionalComponent isValid={field.name === 'contractCode'}>
          <FormHelperText
            sx={{
              color: existsContractByCodeLoading ? 'text.secondary' : (codeAvailability?.isAvailable ? 'success.main' : 'error.main'),
              marginTop: '4px',
              display: 'flex',
              alignItems: 'center'
            }}
          >
            <ConditionalComponent isValid={existsContractByCodeLoading}>
              <Box sx={{ display: 'flex', alignItems: 'center' }}>
                <Box
                  sx={{
                    width: '16px',
                    height: '16px',
                    border: '2px solid #f3f3f3',
                    borderTop: '2px solid #746CD4',
                    borderRadius: '50%',
                    animation: 'spin 1s linear infinite',
                    marginRight: '8px',
                    '@keyframes spin': {
                      '0%': { transform: 'rotate(0deg)' },
                      '100%': { transform: 'rotate(360deg)' }
                    }
                  }}
                />
                <Typography sx={{ color: '#746CD4' }}>
                  Vérification en cours...
                </Typography>
              </Box>
            </ConditionalComponent>
            <ConditionalComponent isValid={!existsContractByCodeLoading}>
              {codeAvailability?.message}
            </ConditionalComponent>
          </FormHelperText>
        </ConditionalComponent>
      </>
    );
  };

  return (
    <>
      <FormContainer titre="Fiche Contrat">
        {isReadOnly ? (
          <EditExportButtons
            onEdit={() => onEdit(formik.values)}
            tooltipTitle={TableType.Contrat}
            dataRow={contrat}
            tableHead={tableHead}
          />
        ) : (
          <></>
        )}
        <form onSubmit={formik.handleSubmit}>
          <Grid container spacing={5} >
            {formFields(agencyOptions, departmentOptions, lotOptions, clientOptions).map((field) => (
              <Grid item xs={12} sm={4} key={field.name}>
                {renderField(field, { onAddClient: handleAddClient })}
              </Grid>
            ))}
            <Grid item xs={12}>
              <Box display="flex" alignItems="center" gap={4}>
                <Typography sx={{ color: isReadOnly ? "text.disabled" : "primary.main" }}>
                  Le bon de commande
                </Typography>
                <AddButton
                  variant="contained"
                  sx={{ minHeight: '43px' }}
                  endIcon={<FontAwesome icon={faFileArrowUp} width={18} />}
                  disabled={isReadOnly}
                  onClick={() => handleImportClick()}
                >
                  Importez un document
                </AddButton>
                <ConditionalComponent isValid={selectedFileName !== ''}>
                  <Typography
                    variant="body2"
                    sx={{
                      color: 'text.primary',
                      fontStyle: 'italic',
                      fontSize: '0.875rem',
                    }}
                  >
                    Fichier sélectionné : {selectedFileName}
                  </Typography>
                </ConditionalComponent>
                <input
                  type="file"
                  ref={fileInputRef}
                  onChange={handleFileUpload}
                  accept=".xlsx,.xls,.csv,.pdf"
                  style={{ display: 'none' }}
                />
                <ConditionalComponent isValid={mode === 'edit' || mode === 'view'}>
                  <Typography sx={{ color: isReadOnly ? "text.disabled" : "primary.main" }}>
                    Statut
                  </Typography>
                  <div>
                    <RadioGroup
                      row
                      name="status"
                      value={formik.values.status || ''}
                      onChange={formik.handleChange}
                      onBlur={formik.handleBlur}
                      aria-disabled={true}
                    >
                      {CONTRACT_STATUS.map((option) => (
                        <FormControlLabel
                          key={option.value}
                          value={option.value}
                          control={<Radio />}
                          label={option.label}
                          disabled={isReadOnly}
                          sx={{
                            '& .MuiFormControlLabel-label': {
                              color: formik.values.status === option.value ? 'primary.main' : 'inherit',
                            },
                          }}
                        />
                      ))}
                    </RadioGroup>
                    <ConditionalComponent isValid={!!(formik.touched.status && formik.errors.status)}>
                      <FormHelperText error>{formik.errors.status}</FormHelperText>
                    </ConditionalComponent>
                  </div>
                </ConditionalComponent>
              </Box>
            </Grid>

            <ConditionalComponent isValid={!isReadOnly}>
              <Grid item xs={12}>
                <ActionButtons
                  onSave={() => {
                    formik.validateForm().then((errors) => {
                      const hasErrors = Object.keys(errors).length > 0;
                      if (!hasErrors) {
                        formik.submitForm();
                      } else {
                        formik.setTouched(
                          Object.keys(errors).reduce((acc, key) => {
                            acc[key as keyof ContractRequest] = true;
                            return acc;
                          }, {} as FormikTouched<ContractRequest>)
                        );
                      }
                    });
                  }}
                  onCancel={() => onClose(false)}
                  mode={mode}
                />
              </Grid>
            </ConditionalComponent>

          </Grid>
        </form>
        {isReadOnly ? <ContratCircuitsTable></ContratCircuitsTable> : <></>}
      </FormContainer>

      <CreateClientModal
        open={openClientModal}
        onClose={(forceClose) => {
          setOpenClientModal(false);
        }}
        tableHead={tableHead}
      />
    </>
  );

}
