'use client';

import React, { useRef, useEffect, useState } from 'react';
import { Grid, IconButton, InputAdornment } from '@mui/material';
import { useFormik } from 'formik';
import { useResponsive } from '@/hooks';
import { enqueueSnackbar } from 'notistack';

import { TableColumn, type ModeType } from '@/shared/types/common';
import { IRHAbsence, CreateAbsenceDto, UserOption } from '@/shared/types/absence-rh';
import FormContainer from '@/layouts/form/form-container';
import ActionButtons from '@/shared/components/form/buttons-action';
import EditExportButtons from '@/shared/components/form/edit-export-buttons';
import FormField from '@/shared/components/form/form-field';
import ConditionalComponent from '@/shared/components/table/ConditionalComponent';
import { createFormFieldsRHAbsence } from '../utils/form-fields-rh-absence';
import { absenceSchema } from '../utils/absence-schema';
import { useRHAbsenceStore } from '@/shared/api/stores/hr-service/rhAbsence';
import { StyledTextField } from '@/shared/theme/css';
import FontAwesome from '@/shared/components/fontawesome';
import CustomTooltip from '@/shared/components/tooltips/tooltip-custom';
import { faPaperclip } from '@fortawesome/free-solid-svg-icons';

interface RHAbsenceFormProps {
  absence: IRHAbsence;
  mode: ModeType;
  onSave: (updatedAbsence: IRHAbsence) => void;
  onEdit: (updatedAbsence: IRHAbsence) => void;
  onClose: (forceClose: boolean) => void;
  isTraiteAbsence?: boolean;
  updateTabContent?: (tabId: string, content: IRHAbsence) => void;
  tabId?: string;
}

export default function AbsenceForm({
  absence,
  mode,
  onSave,
  onClose,
  onEdit,
  isTraiteAbsence,
  updateTabContent,
  tabId,
}: RHAbsenceFormProps) {
  const isBetweenSmAndLg = useResponsive('between', 'sm', 'lg');
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Add state to store the actual file object
  const [selectedFile, setSelectedFile] = useState<File | null>(null);

  const isReadOnly = mode === 'view';
  const isEditing = mode === 'edit';

  // Get store methods and user data from RH absence store
  const {
    createAbsence,
    updateAbsence,
    allUsers,
    getCollaboratorsForAuthorization,
    usersLoading,
    fetchAllUsers,
    // Export functionality
    exportLoading,
    startExport,
    downloadExport,
  } = useRHAbsenceStore();

  const collaborators = getCollaboratorsForAuthorization();

  // Initialize users data if not already loaded
  useEffect(() => {
    if (allUsers.length === 0 && !usersLoading) {
      fetchAllUsers();
    }
  }, [allUsers.length, usersLoading, fetchAllUsers]);

  const formik = useFormik<IRHAbsence>({
    initialValues: absence,
    validationSchema: absenceSchema,
    enableReinitialize: true,
    onSubmit: async (values) => {
      try {

        const getCollaboratorId = (value: string | null | undefined): string => {
          if (!value) return '';


          if (/^\d+$/.test(value)) {
            return value;
          }


          const collab = collaborators.find(c => c.label === value);
          if (collab) {
            return collab.id;
          }


          return value;
        };

        const getCollaboratorName = (value: string | null | undefined): string | null => {
          if (!value) return null;


          if (typeof value === 'string' && !/^\d+$/.test(value)) {
            return value;
          }


          const collaboratorId = getCollaboratorId(value);
          if (collaboratorId) {
            const collab = collaborators.find(c => c.id === collaboratorId);
            if (collab) {
              return collab.label;
            }
          }

          return null;
        };

        // Determine the request type from form values
        const requestType = values.requestType || 'ABSENCE';

        // Map form values to backend DTO format - only include fields the backend expects
        const createDto: any = {
          userId: Number(values.userId),
          startDate: values.dateDebut || values.startDate,
          endDate: values.dateFin || values.endDate,
          numberOfDays: calculateDays(values.dateDebut || values.startDate, values.dateFin || values.endDate),
          justificationFileUrl: values.justificatif || null,
          authorizedByName: getCollaboratorName(values.authorizedBy || values.autorisePar),
          validatedByName: getCollaboratorName(values.validatedBy || values.validerPar),
          hoursCount: Number(values.nbrHeures) || values.numberOfDays * 8,
          receivingMethod: values.modeReception || values.receivingMethod || 'APPLICATION',
          state: 'Unprocessed',
          observations: values.observations || null,
          comment: values.comment || null,
          requestType: requestType,
          affectedToTrip: false,
          tripsIds: []
        };

        // Add type-specific field based on requestType
        // typeAbsence contient soit le type d'absence soit le type de congé
        if (requestType === 'ABSENCE') {
          createDto.absenceType = values.typeAbsence || '';
        } else if (requestType === 'LEAVE') {
          createDto.leaveType = values.typeAbsence || '';
        }

        console.log('Sending absence request:', createDto); // Debug log

        if (isEditing && absence.id) {
          await updateAbsence(Number(absence.id), createDto);
        } else {
          await createAbsence(createDto, selectedFile);
        }

        onSave(values);
        onClose(true);
        const successMessage = requestType === 'LEAVE'
          ? 'Congé créé avec succès'
          : requestType === 'ABSENCE'
            ? 'Absence créée avec succès'
            : 'Demande créée avec succès';
        enqueueSnackbar(successMessage, { variant: 'success' });
      } catch (error) {
        console.error('Form submission error:', error);
        enqueueSnackbar('Erreur lors de la création de l\'absence', { variant: 'error' });
      }
    },
  });

  // Debounce updateTabContent to prevent infinite loops
  useEffect(() => {
    if (updateTabContent && tabId && (mode !== "view")) {
      const timeoutId = setTimeout(() => {
        updateTabContent(tabId, formik.values);
      }, 300);
      
      return () => clearTimeout(timeoutId);
    }
  }, [formik.values, updateTabContent, tabId, mode]);

  // Clear typeAbsence when requestType changes
  useEffect(() => {
    const requestType = formik.values.requestType;
    if (requestType && formik.values.typeAbsence) {
      // Check if current typeAbsence value is valid for the selected requestType
      const isAbsenceType = ['EXTERNAL_ASSIGNMENT', 'PROFESSIONAL_TRAINING', 'EXCEPTIONAL_REMOTE_WORK',
        'AUTHORIZED_ABSENCE', 'UNAUTHORIZED_ABSENCE', 'MEDICAL_APPOINTMENT', 'OTHER'].includes(formik.values.typeAbsence);
      const isLeaveType = ['LEAVE_PAID', 'LEAVE_SICK', 'LEAVE_PARENTAL', 'LEAVE_UNPAID', 'LEAVE_RTT'].includes(formik.values.typeAbsence);

      if ((requestType === 'ABSENCE' && isLeaveType) || (requestType === 'LEAVE' && isAbsenceType)) {
        // Clear the value if it doesn't match the current requestType
        formik.setFieldValue('typeAbsence', '');
      }
    }
  }, [formik.values.requestType]);

  const handleIconClick = () => {
    if (fileInputRef.current) {
      fileInputRef.current.click();
    }
  };

  const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (file) {
      // Update both fields to keep them in sync
      formik.setFieldValue('justificationFileUrl', file.name);
      formik.setFieldValue('justificatif', file.name);
      setSelectedFile(file);
    }
  };

  const renderField = (field: any) => {
    // Handle dynamic type field (typeAbsence changes based on requestType)
    if (field.name === 'typeAbsence') {
      const fieldName = field.name as keyof IRHAbsence;

      // Get dynamic label and options based on requestType
      const requestType = formik.values.requestType;
      let label = 'Type';
      let options = field.options;

      if (requestType === 'LEAVE') {
        label = 'Type de congé';
        options = [
          { value: 'LEAVE_PAID', label: 'Congé payé' },
          { value: 'LEAVE_SICK', label: 'Congé maladie' },
          { value: 'LEAVE_PARENTAL', label: 'Congé parental' },
          { value: 'LEAVE_UNPAID', label: 'Congé sans solde' },
          { value: 'LEAVE_RTT', label: 'RTT' }
        ];
      } else if (requestType === 'ABSENCE') {
        label = 'Type d\'absence';
        options = [
          { value: 'EXTERNAL_ASSIGNMENT', label: 'Mission externe' },
          { value: 'PROFESSIONAL_TRAINING', label: 'Formation professionnelle' },
          { value: 'EXCEPTIONAL_REMOTE_WORK', label: 'Télétravail exceptionnel' },
          { value: 'AUTHORIZED_ABSENCE', label: 'Absence autorisée' },
          { value: 'UNAUTHORIZED_ABSENCE', label: 'Absence non autorisée' },
          { value: 'MEDICAL_APPOINTMENT', label: 'Rendez-vous médical' },
          { value: 'OTHER', label: 'Autre' }
        ];
      }

      return (
        <FormField
          field={{ ...field, label, options }}
          value={formik.values[fieldName]}
          onChange={(name, value) => {
            console.log('TypeAbsence changed to:', value);
            formik.setFieldValue(name, value);
          }}
          error={
            formik.touched[fieldName]
              ? (formik.errors[fieldName] as string | undefined)
              : undefined
          }
          onBlur={formik.handleBlur}
          isReadOnly={field.disabled || isReadOnly}
        />
      );
    }

    if (field.name === "justificatif") {
      const fieldName = field.name as keyof IRHAbsence;
      const error = formik.touched[fieldName] && formik.errors[fieldName];

      // Get the value from justificationFileUrl
      const value = formik.values.justificationFileUrl || "";

      // Only show file icon if it's an actual file URL
      const isFileUrl = typeof value === 'string' && value.toLowerCase().startsWith('http');

      return (
        <StyledTextField
          isSmallScreen={isBetweenSmAndLg}
          fullWidth
          name={field.name}
          InputLabelProps={{
            shrink: true,
          }}
          value={value}
          onChange={(e) => {
            // Update both fields to keep them in sync
            formik.setFieldValue('justificationFileUrl', e.target.value);
            formik.setFieldValue(fieldName, e.target.value);
          }}
          onBlur={formik.handleBlur}
          error={!!error}
          helperText={error ? String(formik.errors[fieldName]) : undefined}
          label={field.label}
          placeholder={field.placeholder}
          sx={{
            ...(isReadOnly && {
              '& .MuiInputBase-root': {
                backgroundColor: '#f5f5f5',
                cursor: 'not-allowed',
              },
              '& .MuiInputBase-input': {
                cursor: 'not-allowed',
                color: 'text.disabled',
              }
            })
          }}
          InputProps={{
            readOnly: isReadOnly,
            endAdornment: isFileUrl ? (
              <InputAdornment position="end" >
                <CustomTooltip title="Importer la justification" arrow>
                  <IconButton onClick={handleIconClick} disabled={isReadOnly}>
                    <FontAwesome
                      icon={faPaperclip}
                      sx={{
                        color: isReadOnly ? 'text.disabled' : "primary.main",
                        width: isBetweenSmAndLg ? 16 : 18,
                      }}
                    />
                  </IconButton>
                </CustomTooltip>
              </InputAdornment>
            ) : null,
          }}
        />
      );
    }

    const fieldName = field.name as keyof IRHAbsence;

    // Special handling for user selection field
    if (field.name === 'nomChauffeur') {
      return (
        <FormField
          field={field}
          value={formik.values[fieldName]}
          onChange={(name, value) => {
            // Set the selected user name
            formik.setFieldValue(name, value);

            // Auto-update related fields when user is selected
            if (value && allUsers.length > 0) {
              const selectedUser = allUsers.find(user => user.label === value);
              if (selectedUser) {
                // Set userId, type, and department automatically
                formik.setFieldValue('userId', Number(selectedUser.id));

                const userType = selectedUser.type === 'CHAUFFEUR' ? 'chauffeur' : 'sédentaire';
                formik.setFieldValue('type', userType);

                if (selectedUser.departmentName) {
                  formik.setFieldValue('departement', selectedUser.departmentName);
                }
              }
            }
          }}
          error={
            formik.touched[fieldName]
              ? (formik.errors[fieldName] as string | undefined)
              : undefined
          }
          onBlur={formik.handleBlur}
          isReadOnly={field.disabled || isReadOnly}
        />
      );
    }


    if (field.name === 'autorisePar') {

      let displayValue = formik.values[fieldName] as string;


      if (absence.authorizedByName) {
        displayValue = absence.authorizedByName;
      } else if (displayValue && /^\d+$/.test(displayValue)) {

        displayValue = getCollaboratorNameById(displayValue);
      }

      return (
        <FormField
          field={field}
          value={displayValue}
          onChange={(name, value) => {

            formik.setFieldValue(name, value);


            const selectedCollab = collaborators.find(c => c.label === value);
            if (selectedCollab) {

              formik.setFieldValue('authorizedBy', selectedCollab.id);
            }
          }}
          error={
            formik.touched[fieldName]
              ? (formik.errors[fieldName] as string | undefined)
              : undefined
          }
          onBlur={formik.handleBlur}
          isReadOnly={field.disabled || isReadOnly}
        />
      );
    }


    if (field.name === 'validerPar') {

      let displayValue = formik.values[fieldName] as string;


      if (absence.validatedByName) {
        displayValue = absence.validatedByName;
      } else if (displayValue && /^\d+$/.test(displayValue)) {

        displayValue = getCollaboratorNameById(displayValue);
      }

      return (
        <FormField
          field={field}
          value={displayValue}
          onChange={(name, value) => {
            formik.setFieldValue(name, value);
            const selectedCollab = collaborators.find(c => c.label === value);
            if (selectedCollab) {
              formik.setFieldValue('validatedBy', selectedCollab.id);
            }
          }}
          error={
            formik.touched[fieldName]
              ? (formik.errors[fieldName] as string | undefined)
              : undefined
          }
          onBlur={formik.handleBlur}
          isReadOnly={field.disabled || isReadOnly}
        />
      );
    }

    return (
      <FormField
        field={field}
        value={formik.values[fieldName]}
        onChange={(name, value) => formik.setFieldValue(name, value)}
        error={
          formik.touched[fieldName]
            ? (formik.errors[fieldName] as string | undefined)
            : undefined
        }
        onBlur={formik.handleBlur}
        isReadOnly={field.disabled || isReadOnly}
      />
    );
  };

  // Helper function to calculate number of days
  const calculateDays = (startDate: string, endDate: string): number => {
    if (!startDate || !endDate) return 1;
    const start = new Date(startDate);
    const end = new Date(endDate);
    const diffTime = Math.abs(end.getTime() - start.getTime());
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
    return diffDays > 0 ? diffDays : 1;
  };

  // Get form fields with user data
  const formFields = createFormFieldsRHAbsence(allUsers, collaborators);

  // Helper to find collaborator name by ID
  const getCollaboratorNameById = (id: string | null | undefined): string => {
    if (!id) return '';
    const collab = collaborators.find(c => c.id === id);
    if (collab) {
      return collab.label;
    }
    return id;
  };

  // Export handler for single absence
  const handleExportSingle = async () => {
    try {


      // Create filters for just this absence
      const exportFilters = {
        absenceNumber: absence.numeroEnregistrement || `ABS-${absence.id}`,
        page: 0,
        size: 1,
        requestType: 'ABSENCE'
      };

      const result = await startExport(exportFilters);

      if (result.success && result.exportPath) {
        enqueueSnackbar(result.message, { variant: 'success' });

        // Auto-download the file
        setTimeout(async () => {
          try {
            const downloadResult = await downloadExport(result.exportPath!);
            if (downloadResult.success) {
              enqueueSnackbar(downloadResult.message, { variant: 'success' });
            } else {
              enqueueSnackbar(downloadResult.message, { variant: 'error' });
            }
          } catch (error) {
            console.error('Download failed:', error);
            enqueueSnackbar('Échec du téléchargement automatique', { variant: 'error' });
          }
        }, 2000);
      } else {
        enqueueSnackbar(result.message, { variant: 'error' });
      }
    } catch (error) {
      console.error('Export failed:', error);
      enqueueSnackbar('Échec de l\'export', { variant: 'error' });
    }
  };

  if (usersLoading) {
    return <div>Chargement des utilisateurs...</div>;
  }

  const formTitle = absence.requestType === 'LEAVE'
    ? 'Fiche Congé'
    : absence.requestType === 'ABSENCE'
      ? 'Fiche Absence'
      : 'Fiche Demande';

  return (
    <FormContainer titre={formTitle}>
      <ConditionalComponent isValid={isReadOnly}>
        <EditExportButtons
          onEdit={isTraiteAbsence ? undefined : () => onEdit(absence)}
          onExport={handleExportSingle}
          dataRow={absence}
        />
      </ConditionalComponent>

      <form onSubmit={formik.handleSubmit}>
        <Grid container spacing={4}>
          {formFields.map((field, index) => (
            <Grid item xs={12} sm={4} key={`${field.name}-${index}`}>
              {renderField(field)}
            </Grid>
          ))}
          <input type="file" ref={fileInputRef} style={{ display: "none" }} onChange={handleFileUpload} />
          <Grid item xs={12}>
            <ConditionalComponent isValid={mode !== "view"}>
              <ActionButtons
                onSave={() => {
                  formik.validateForm().then((errors) => {
                    console.log('Validation errors:', errors);
                    console.log('Form values:', formik.values);
                    if (Object.keys(errors).length === 0) {
                      formik.submitForm();
                    } else {
                      enqueueSnackbar('Veuillez remplir tous les champs obligatoires', { variant: 'warning' });
                    }
                  });
                }}
                onCancel={() => onClose(false)}
                mode={mode}
              />
            </ConditionalComponent>
          </Grid>
        </Grid>
      </form>
    </FormContainer>
  );
} 
