import React, { useState, useRef, useEffect } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faChevronLeft, faChevronDown, faTimes, faImage  } from '@fortawesome/free-solid-svg-icons';
import { FileUploader } from 'react-drag-drop-files';
import Select from 'react-select'

const fileTypes = ["JPG", "JPEG", "PNG"]; // Allowed file types


const Search = () => {
    
  const BASE_URL = process.env.REACT_APP_BASE_URL
  const API_KEY = process.env.REACT_APP_API_KEY

  const [isSelectOpen, setIsSelectOpen] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');
  const [selectedImageName, setSelectedImageName] = useState('');
  const [resultImageLabel, setResultImageLabel] = useState('');
  const fileInputRef = useRef(null);
  const [showResult, setShowResult] = useState(false);
  const [applicationId, setApplicationId] = useState('');
  const [selectedQuota, setSelectedQuota] = useState(0);
  const [limitId, setLimitId] = useState('');
  const [imageUrls, setImageUrls] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [results, setResults] = useState([]);
  const [file, setFile] = useState(null);
  const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);

  const [applicationIds, setApplicationIds] = useState([]);
  const [inputValueApplication, setInputValueApplication] = useState(''); // Controlled input value for Application ID

  const [limitIds] = useState(
      Array.from({ length: 10 }, (_, index) => ({
      id: index + 1,
      name: index + 1,
      }))
  );  

  const [applicationIdError, setApplicationIdError] = useState('');
  const [limitIdError, setLimitIdError] = useState('');
  const [imageError, setImageError] = useState('');
  const [uploadedFile, setUploadedFile] = useState(null); 

  const formatFileSize = (sizeInBytes) => {
    if (sizeInBytes < 1024) {
        return `${sizeInBytes} bytes`; // Jika ukuran lebih kecil dari 1 KB
    } else if (sizeInBytes < 1048576) {
        return `${(sizeInBytes / 1024).toFixed(2)} KB`; // Jika ukuran lebih kecil dari 1 MB
    } else {
        return `${(sizeInBytes / 1048576).toFixed(2)} MB`; // Jika ukuran lebih besar dari 1 MB
    }
  };

  useEffect(() => {
    const fetchApplicationIds = async () => {
        try {
            setIsLoading(true)
            const url = `${BASE_URL}/application/list`;
            console.log('Fetching URL:', url); // Log the URL
            
            const response = await fetch(url, {
                method: 'GET',
                headers: {
                    'accept': 'application/json',
                    'x-api-key': `${API_KEY}`,
                },
            });

            const data = await response.json();

            if (data.status_code === 200) {
                const ids = data.details.data.map(app => app.id);
                console.log('Application Id: ' + ids); // Log the IDs
                setApplicationIds(data.details.data); // Update state with the fetched data
            } else {
                console.error('Failed to fetch data:', data.details.message);
            }
        } catch (error) {
            console.error('Error fetching application IDs:', error);
        } finally {
            setIsLoading(false)
        }
    };

    fetchApplicationIds();

    const handleResize = () => setIsMobile(window.innerWidth <= 768);
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  const applicationOptions = applicationIds.map(app => ({
    value: app.id,
    label: app.name
  }));

  const handleApplicationChange = (selectedOption) => {
    if (selectedOption) {
      const selectedId = selectedOption.value;
      const selectedApp = applicationIds.find(app => app.id === parseInt(selectedId));
      if (selectedApp) {
        setSelectedQuota(selectedApp.quota); // Set the selected quota
        setApplicationId(selectedId); // Set the selected application ID
      }
    }
  };  

  const handleInputChangeApplication = (newInputValue) => {
    // Limit input to 15 characters for Application ID
    if (newInputValue.length <= 15) {
        setInputValueApplication(newInputValue);
    }
};

  const handleFocus = () => {
    setIsSelectOpen(true);
  };

  const handleBlur = () => {
    setIsSelectOpen(false);
  };

  const handleImageUpload = (file) => {
    // Ensure the file is not undefined or null before accessing its properties
    if (file && file.name) {
      const fileExtension = file.name.split('.').pop().toUpperCase();
      if (fileTypes.includes(fileExtension)) {
        setSelectedImageName(file.name);
        setFile(file);
        setUploadedFile(file); // Set uploadedFile to the selected file
        setImageError(''); // Clear any previous errors
      } else {
        alert('Image format is not supported');
        setImageError('Image format is not supported');
        setFile(null);
        setUploadedFile(null); // Clear uploadedFile if the file is unsupported
      }
    } else {
      console.error('No file selected or invalid file object.');
    }
  };

  const handleImageCancel = () => {
    setSelectedImageName('');
    setFile(null);
    if (fileInputRef.current) {
        fileInputRef.current.value = '';
    }
  };

  const handleCheckClick = async () => {
    // Clear existing errors
    setApplicationIdError('');
    setLimitIdError('');
    setImageError('');
    setErrorMessage('');
  
    // Initialize validation flags
    let hasError = false;
  
    // Validate Application ID
    if (!applicationId) {
      setApplicationIdError('Please select an Application ID before searching.');
      hasError = true;
    }
  
    // Validate Limit ID
    if (!limitId) {
      setLimitIdError('Please select a Limit before searching.');
      hasError = true;
    }
  
    // Validate Image Upload
    if (!selectedImageName) {
      setImageError('Please upload an image file.');
      hasError = true;
    }
  
    // Check if the file is uploaded
    if (!uploadedFile) {
      setErrorMessage('Please upload an image file.');
      hasError = true;
    }
  
    // If any errors were found, do not proceed
    if (hasError) {
      return;
    }
  
    const parsedLimitId = parseInt(limitId, 10);
  
    const formData = new FormData();
    formData.append('application_id', applicationId);
    formData.append('threshold', 1);
    formData.append('limit', parsedLimitId);
    formData.append('file', uploadedFile, uploadedFile.name); // Use the uploaded file
  
    setIsLoading(true);
  
    try {
      const response = await fetch(`${BASE_URL}/face_recognition/search`, {
        method: 'POST',
        headers: {
          'accept': 'application/json',
          'x-api-key': `${API_KEY}`,
        },
        body: formData,
      });
  
      const data = await response.json();
  
      console.log('Response Data:', data);
  
      if (response.ok) {
        const resultsArray = Array.isArray(data.details.data) ? data.details.data : [];
        const processedResults = resultsArray.map(item => ({
          identity: item.identity,
          similarity: item.similarity,
          imageUrl: item.image_url,
          distance: item.distance,
        }));
  
        // Fetch images using their URLs
        await Promise.all(processedResults.map(async result => {
          const imageFileName = result.imageUrl.split('/').pop(); // Extract file name if needed
          await fetchImage(imageFileName); // Fetch image
          console.log('multiple image data: ', result.imageUrl);
        }));
  
        setResults(processedResults);
        setResultImageLabel(selectedImageName)
        setShowResult(true);
      } else {
        console.error('Error response:', JSON.stringify(data, null, 2));
        const errorMessage = data.message || data.detail || data.details?.message || 'An unknown error occurred.';
        setErrorMessage(errorMessage);
      }
    } catch (error) {
      console.error('Error:', error);
      setErrorMessage('An error occurred while making the request.');
    } finally {
      setIsLoading(false);
    }
  };
  
  
  const fetchImage = async (imageFileName) => {
    setIsLoading(true);
    try {
      const response = await fetch(`${BASE_URL}/preview/image/${imageFileName}`, {
          method: 'GET',
          headers: {
              'accept': 'application/json',
              'x-api-key': API_KEY,
          },
      });

      if (!response.ok) {
          const errorDetails = await response.json();
          console.error('Image fetch error details:', errorDetails);
          setErrorMessage('Failed to fetch image, please try again.');
          return;
      }

      const imageBlob = await response.blob();
      const imageData = URL.createObjectURL(imageBlob);
      console.log('Fetched image URL:', imageData);
      setImageUrls(prevUrls => [...prevUrls, imageData]); // Store the blob URL

    } catch (error) {
      console.error('Error fetching image:', error);
      setErrorMessage(error.message);
    } finally {
      setIsLoading(false);
    }
  };

  const CustomLabel = ({ overRide, children, ...props }) => {
    // We intentionally don't pass `overRide` to the label
    return (
        <label {...props}>
            {children}
        </label>
    );
  };
  
  const styles = {
    formGroup: {
        marginTop: '-45px',
    },
    selectWrapper: {
        position: 'relative',
        marginTop: '0',
    },
    select: {
        width: '100%',
        paddingRight: '30px',
    },
    chevronIcon: {
        position: 'absolute',
        right: '10px',
        top: '50%',
        transform: 'translateY(-50%)',
        pointerEvents: 'none',
    },
    remainingQuota: {
        display: 'flex',
        flexDirection: 'row',
        alignItems: 'center',
        marginTop: '4px',
    },
    quotaText: {
        fontSize: '40px',
        color: '#0542cc',
        fontWeight: '600',
    },
    timesText: {
        marginLeft: '8px',
        verticalAlign: 'super',
        fontSize: '20px',
    },
    uploadArea: {
        backgroundColor: '#e6f2ff',
        height: '40svh',
        cursor: 'pointer',
        marginTop: '1rem',
        padding: '1rem',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
        border: '1px solid #ced4da',
        borderRadius: '0.25rem',
    },
    uploadIcon: {
        fontSize: '40px',
        color: '#0542cc',
        marginBottom: '7px',
    },
    uploadText: {
        color: '#1f2d3d',
        fontWeight: '400',
        fontSize: '16px',
        lineHeight: '13px',
    },    
    wrapper: {
        border: '1px solid #ddd',
        borderRadius: '6px',
        padding: '18px 10px 0 8px', // Padding lebih seragam
        height: '13svh', // Tinggi lebih kecil untuk menyesuaikan tampilan
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        backgroundColor: '#f9f9f9',
        overflow: 'hidden',
    },
    fileWrapper: {
        display: 'flex',
        alignItems: 'center',
        flex: '1',
    },
    textContainer: {
        flex: '1',
        fontSize: '16px', // Ukuran font lebih kecil
        marginLeft: '6px',
        overflow: 'hidden',
        whiteSpace: 'nowrap',
        textOverflow: 'ellipsis',
        marginTop: '1rem'
    },
    fileSize: {
        fontSize: '12px',
        color: '#555',
        marginBottom: '2rem',
    },
    closeButtonContainer: {
        display: 'flex',
        alignItems: 'center',
        marginLeft: 'auto',
    },
    closeButton: {
        background: 'transparent',
        border: 'none',
        cursor: 'pointer',
        padding: '0',
    },
    imageIcon: {
        color: '#0542cc',
        fontSize: '18px', // Ukuran ikon sedikit lebih kecil
        marginRight: '6px',
    },
    closeIcon: {
        color: 'red',
        fontSize: '18px',
    },
    submitButton: {
        marginLeft: 'auto',
        marginTop: '4rem',
        textAlign: 'start',
        position: 'relative',
        zIndex: 1,
    },
    uploadError: {
        color: 'red',
        fontSize: '12px',
        marginTop: '5px',
    },
    loadingOverlay: {
      position: 'fixed',
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      backgroundColor: 'rgba(0, 0, 0, 0.2)',
      display: 'flex',
      flexDirection: 'column', 
      justifyContent: 'center',
      alignItems: 'center',
      zIndex: 1000,
    },
    spinner: {
      border: '4px solid rgba(0, 0, 0, 0.1)',
      borderLeftColor: '#0542cc',
      borderRadius: '50%',
      width: '90px',
      height: '90px',
      animation: 'spin 1s ease-in-out infinite',
    },
    loadingText: {
      marginTop: '10px',
      fontSize: '1.2rem',
      color: '#fff',
      textAlign: 'center',
    },
    containerResultStyle: {
      padding: '1rem',
      backgroundColor: '#f7f7f7',
      borderRadius: '8px',
      margin: '1rem',
      width: '100%', // Full width for large screens
    },
    resultContainer: {
        display: 'flex',
        flexDirection: 'row',
        flexWrap: 'wrap',
        gap: '1rem',
        justifyContent: 'center',        
    },
    resultItem: {
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        textAlign: 'center',
        padding: '0.5rem',
        backgroundColor: '#fff',
        border: '1px solid #ddd',
        borderRadius: '8px',
        boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.1)',
        width: '150px', // Default width for larger screens
    },
    resultTextContainer: {
        marginBottom: '0.5rem',
    },
    resultText: {
        fontSize: '0.9rem',
        color: '#333',
        margin: '0.2rem 0',
    },
    resultImage: {
        width: '80px',
        height: '80px',
        borderRadius: '50%',
        marginTop: '0.5rem',
    },

    // Media query for mobile responsiveness
    '@media screen and (max-width: 768px)': {
      containerResultStyle: {
        width: '100%', // Full width on mobile
      },
      resultContainer: {
        flexDirection: 'column', // Stack results vertically on small screens
      },
      resultItem: {
        width: '100%', // Make result items take full width on mobile
      },
    },
  };
  
  return (
    <div>
      {/* Inject keyframes for the spinner */}
      <style>
          {`
          @keyframes spin {
              0% { transform: rotate(0deg); }
              100% { transform: rotate(360deg); }
          }
          `}
      </style>

      {isLoading && (
          <div style={styles.loadingOverlay}>
              <div style={styles.spinner}></div>
              <p style={styles.loadingText}>Loading...</p>
          </div>
      )}
      
      {/* Application ID Selection */}
      <div className="form-group row align-items-center">
          <div className="col-md-6">
            <div className="select-wrapper">
              <Select
                id="applicationId"
                value={applicationOptions.find(option => option.value === applicationId)}
                onChange={handleApplicationChange}
                options={applicationOptions}
                placeholder="Select Application ID"
                isSearchable
                menuPortalTarget={document.body}
                menuPlacement="auto"
                inputValue={inputValueApplication}
                onInputChange={handleInputChangeApplication}
              />
            </div>
            {applicationIdError && (
              <small style={styles.uploadError}>{applicationIdError}</small>
            )}
          </div>

          <div className="col-md-6">
              <p className="text-secondary" style={{ fontSize: '16px', fontWeight: '400', margin: '0', marginTop: '8px' }}>
                  Remaining Quota
              </p>
              <div style={styles.remainingQuota}>
                  <span style={styles.quotaText}>{selectedQuota}</span> {/* Display selected quota */}
                  <span style={styles.timesText}>(times)</span>
              </div>
          </div>
      </div>

      {/* limit ID Input and Threshold Selection */}
      <div className="form-group row align-items-center">
        <div className="col-md-6">
            <div style={styles.selectWrapper}>
                <select
                    id="limitId"
                    className="form-control"
                    style={styles.select}
                    value={limitId}
                    onChange={(e) => setLimitId(e.target.value)}
                    onFocus={handleFocus}
                    onBlur={handleBlur}
                >
                <option value="">Select Limit</option>
                {limitIds.map((app) => (
                    <option key={app.id} value={app.id}>
                        {app.name}
                    </option>
                ))}
                </select>
                <FontAwesomeIcon
                    icon={isSelectOpen ? faChevronDown : faChevronLeft}
                    style={styles.chevronIcon}
                />
                {limitIdError && (
                    <small style={styles.uploadError}>{limitIdError}</small>
                )}
            </div>
        </div>
      </div>

      {/* Upload Section */}
      {/* Drag and Drop File Uploader */}
      <div className='col-md-6'>
        <div className="row form-group mt-4">
            <CustomLabel htmlFor="uploadPhoto" style={styles.customLabel}>
                Upload Face Photo
            </CustomLabel>
            <FileUploader
              handleChange={handleImageUpload}
              name="file"
              types={fileTypes}
              multiple={false}
              onDrop={(files) => handleImageUpload(files[0])}
              children={
                  <div style={styles.uploadArea}>
                      <i className="fas fa-cloud-upload-alt" style={styles.uploadIcon}></i>
                      <p style={styles.uploadText}>Drag and Drop Here</p>
                      <p>Or</p>
                      <a href="#" onClick={() => fileInputRef.current.click()}>Browse</a>
                      <p className="text-muted">Recommended size: 300x300 (Max File Size: 2MB)</p>
                      <p className="text-muted">Supported file types: JPG, JPEG</p>
                  </div>
              }
            />
            <input
                type="file"
                id="fileUpload"
                ref={fileInputRef}
                style={{ display: 'none' }}
                accept="image/jpeg, image/jpg"
                onChange={e => handleImageUpload(e.target.files[0])}
            />
            {(imageError || errorMessage) && (
                <small style={{ color: 'red' }}>
                    {imageError || errorMessage}
                </small>
            )}
        </div>
      </div>

        {selectedImageName && (
            <div className="mt-3">
                <p><strong>File:</strong> {selectedImageName}</p>
                {file && (
                    <p style={styles.fileSize}>
                        Size: {formatFileSize(file.size)}
                    </p>
                )}
                <button className="btn btn-danger" onClick={handleImageCancel}>
                    <FontAwesomeIcon icon={faTimes} className="me-2" />Cancel
                </button>
            </div>
        )}

        {errorMessage && <small style={styles.uploadError}>{errorMessage}</small>}

      {/* Submit Button */}
      <div style={styles.submitButton}>
        <button onClick={handleCheckClick} className="btn d-flex justify-content-center align-items-center me-2" style={{ backgroundColor: '#0542CC' }}>
            <p className="text-white mb-0">Check Now</p>
        </button>
      </div>

      {/* Results Section */}
      {
        showResult && results.length > 0 && (
          <div style={styles.containerResultStyle}>
              <h1 style={{ color: '#0542cc', textAlign: 'center' }}>Results</h1>
              <div style={styles.resultContainer}>
                  {results.slice(0, limitId).map((result, index) => (
                      <div key={index} style={styles.resultItem}>
                          <div style={styles.resultTextContainer}>
                              {/* Displaying the dynamically set resultImageLabel */}
                              <p style={styles.resultText}>Image Name: {resultImageLabel}</p> {/* Updated here */}
                              <p style={styles.resultText}>Similarity: {result.similarity}%</p>
                              <p style={styles.resultText}>Distance: {result.distance}</p>
                          </div>
                          <img src={imageUrls[index]} alt={`Result ${index + 1}`} style={styles.resultImage} />
                      </div>
                  ))}
              </div>
          </div>
        )
      }
    </div>
  );
}

export default Search

