/**
 * DocumentUploadComponent.jsx
 * 
 * React component for uploading documents to the SCM document storage service.
 * Handles complete workflow: initialize → upload → complete → download
 */

import React, { useState, useRef } from 'react';

const DocumentUploadComponent = ({ token, domain, entityId, category }) => {
  const [uploadStatus, setUploadStatus] = useState('idle'); // idle, uploading, complete, error
  const [uploadProgress, setUploadProgress] = useState(0);
  const [objectId, setObjectId] = useState(null);
  const [error, setError] = useState(null);
  const [metadata, setMetadata] = useState(null);
  const fileInputRef = useRef(null);

  const API_BASE = 'http://localhost:8000';

  /**
   * Calculate SHA-256 checksum of file
   */
  const calculateChecksum = async (file) => {
    const buffer = await file.arrayBuffer();
    const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
  };

  /**
   * Step 1: Initialize upload
   */
  const initializeUpload = async (file) => {
    try {
      const response = await fetch(`${API_BASE}/scm/storage/upload/init`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({
          domain,
          entity_id: entityId,
          category,
          file_name: file.name,
          mime_type: file.type,
          file_size: file.size,
          visibility: 'private',
        }),
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(
          `Upload init failed: ${response.status} - ${errorData.detail || response.statusText}`
        );
      }

      return await response.json();
    } catch (err) {
      throw new Error(`Initialize upload failed: ${err.message}`);
    }
  };

  /**
   * Step 2: Upload file to MinIO presigned URL
   */
  const uploadToPresignedUrl = async (file, presignedUrl) => {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();

      // Track upload progress
      xhr.upload.addEventListener('progress', (e) => {
        if (e.lengthComputable) {
          const percentComplete = (e.loaded / e.total) * 100;
          setUploadProgress(Math.round(percentComplete));
        }
      });

      xhr.addEventListener('load', () => {
        if (xhr.status === 200) {
          resolve();
        } else {
          reject(
            new Error(
              `Upload to MinIO failed: ${xhr.status} - ${xhr.statusText}`
            )
          );
        }
      });

      xhr.addEventListener('error', () => {
        reject(new Error('Upload to MinIO failed: Network error'));
      });

      xhr.addEventListener('abort', () => {
        reject(new Error('Upload to MinIO cancelled'));
      });

      xhr.open('PUT', presignedUrl);
      xhr.setRequestHeader('Content-Type', file.type);
      xhr.send(file);
    });
  };

  /**
   * Step 3: Complete upload
   */
  const completeUpload = async (uploadId, checksumSha256) => {
    try {
      const response = await fetch(`${API_BASE}/scm/storage/upload/complete`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({
          upload_id: uploadId,
          checksum_sha256: checksumSha256,
        }),
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(
          `Upload complete failed: ${response.status} - ${errorData.detail || response.statusText}`
        );
      }

      return await response.json();
    } catch (err) {
      throw new Error(`Complete upload failed: ${err.message}`);
    }
  };

  /**
   * Main upload handler
   */
  const handleUpload = async (file) => {
    try {
      setUploadStatus('uploading');
      setError(null);
      setUploadProgress(0);

      // Step 1: Initialize
      console.log('1. Initializing upload...');
      const initResponse = await initializeUpload(file);
      console.log('   Upload ID:', initResponse.upload_id);

      // Step 2: Calculate checksum
      console.log('2. Calculating checksum...');
      const checksum = await calculateChecksum(file);
      console.log('   Checksum:', checksum);

      // Step 3: Upload to MinIO
      console.log('3. Uploading to MinIO...');
      await uploadToPresignedUrl(file, initResponse.presigned_urls[0]);
      setUploadProgress(100);
      console.log('   File uploaded successfully');

      // Step 4: Complete upload
      console.log('4. Completing upload...');
      const completeResponse = await completeUpload(
        initResponse.upload_id,
        checksum
      );

      const finalObjectId = completeResponse.id;
      setObjectId(finalObjectId);

      if (completeResponse.deduplicated) {
        console.log(
          '   File was deduplicated (already exists)',
          completeResponse.id
        );
      }

      // Fetch metadata
      await fetchMetadata(finalObjectId);

      setUploadStatus('complete');
    } catch (err) {
      console.error('Upload error:', err);
      setError(err.message);
      setUploadStatus('error');
    }
  };

  /**
   * Fetch object metadata
   */
  const fetchMetadata = async (id) => {
    try {
      const response = await fetch(`${API_BASE}/scm/storage/${id}`, {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });

      if (!response.ok) {
        throw new Error(`Fetch failed: ${response.statusText}`);
      }

      setMetadata(await response.json());
    } catch (err) {
      console.error('Fetch metadata error:', err);
    }
  };

  /**
   * Generate download URL
   */
  const handleDownload = async () => {
    try {
      const response = await fetch(`${API_BASE}/scm/storage/download-url`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({ object_id: objectId }),
      });

      if (!response.ok) {
        throw new Error(`Download URL generation failed: ${response.statusText}`);
      }

      const { url } = await response.json();
      window.open(url, '_blank');
    } catch (err) {
      setError(`Download failed: ${err.message}`);
    }
  };

  /**
   * Delete object (soft delete)
   */
  const handleDelete = async () => {
    if (!window.confirm('Are you sure you want to delete this file?')) {
      return;
    }

    try {
      const response = await fetch(`${API_BASE}/scm/storage/${objectId}`, {
        method: 'DELETE',
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });

      if (!response.ok) {
        throw new Error(`Delete failed: ${response.statusText}`);
      }

      setObjectId(null);
      setMetadata(null);
      setUploadStatus('idle');
    } catch (err) {
      setError(`Delete failed: ${err.message}`);
    }
  };

  /**
   * Handle file input change
   */
  const handleFileChange = async (e) => {
    const file = e.target.files?.[0];
    if (file) {
      await handleUpload(file);
    }
  };

  return (
    <div style={styles.container}>
      <h2>Document Upload</h2>

      {/* File Input */}
      <div style={styles.section}>
        <label htmlFor="file-input" style={styles.label}>
          Select File:
        </label>
        <input
          id="file-input"
          ref={fileInputRef}
          type="file"
          onChange={handleFileChange}
          disabled={uploadStatus === 'uploading'}
          style={styles.input}
        />
      </div>

      {/* Upload Progress */}
      {uploadStatus === 'uploading' && (
        <div style={styles.section}>
          <p>Uploading: {uploadProgress}%</p>
          <div style={styles.progressBar}>
            <div
              style={{
                ...styles.progressFill,
                width: `${uploadProgress}%`,
              }}
            />
          </div>
        </div>
      )}

      {/* Error Message */}
      {error && (
        <div style={{ ...styles.section, ...styles.error }}>
          <strong>Error:</strong> {error}
        </div>
      )}

      {/* Success Message */}
      {uploadStatus === 'complete' && objectId && (
        <div style={{ ...styles.section, ...styles.success }}>
          <strong>Upload Successful!</strong>
          <p>Object ID: {objectId}</p>
        </div>
      )}

      {/* Metadata Display */}
      {metadata && (
        <div style={styles.section}>
          <h3>File Information</h3>
          <dl style={styles.metadata}>
            <dt>File Name:</dt>
            <dd>{metadata.file_name}</dd>

            <dt>MIME Type:</dt>
            <dd>{metadata.mime_type}</dd>

            <dt>Size:</dt>
            <dd>{(metadata.file_size / 1024 / 1024).toFixed(2)} MB</dd>

            <dt>Domain:</dt>
            <dd>{metadata.domain}</dd>

            <dt>Category:</dt>
            <dd>{metadata.category}</dd>

            <dt>Visibility:</dt>
            <dd>{metadata.visibility}</dd>

            <dt>Created:</dt>
            <dd>{new Date(metadata.created_at).toLocaleString()}</dd>

            <dt>Checksum:</dt>
            <dd style={styles.checksum}>{metadata.checksum_sha256}</dd>
          </dl>
        </div>
      )}

      {/* Action Buttons */}
      {objectId && (
        <div style={styles.section}>
          <button
            onClick={handleDownload}
            style={{ ...styles.button, ...styles.buttonPrimary }}
          >
            Download
          </button>
          <button
            onClick={handleDelete}
            style={{ ...styles.button, ...styles.buttonDanger }}
          >
            Delete
          </button>
        </div>
      )}
    </div>
  );
};

// Styling
const styles = {
  container: {
    maxWidth: '600px',
    margin: '20px auto',
    padding: '20px',
    border: '1px solid #ddd',
    borderRadius: '8px',
    fontFamily: 'Arial, sans-serif',
  },
  section: {
    marginBottom: '20px',
  },
  label: {
    display: 'block',
    marginBottom: '8px',
    fontWeight: 'bold',
  },
  input: {
    width: '100%',
    padding: '8px',
    borderRadius: '4px',
    border: '1px solid #ccc',
  },
  progressBar: {
    width: '100%',
    height: '20px',
    backgroundColor: '#f0f0f0',
    borderRadius: '4px',
    overflow: 'hidden',
  },
  progressFill: {
    height: '100%',
    backgroundColor: '#4CAF50',
    transition: 'width 0.3s',
  },
  error: {
    padding: '12px',
    backgroundColor: '#ffebee',
    color: '#c62828',
    borderRadius: '4px',
    border: '1px solid #ef5350',
  },
  success: {
    padding: '12px',
    backgroundColor: '#e8f5e9',
    color: '#2e7d32',
    borderRadius: '4px',
    border: '1px solid #66bb6a',
  },
  metadata: {
    display: 'grid',
    gridTemplateColumns: '120px 1fr',
    gap: '8px 16px',
    marginTop: '12px',
  },
  checksum: {
    fontFamily: 'monospace',
    fontSize: '12px',
    wordBreak: 'break-all',
  },
  button: {
    padding: '10px 20px',
    marginRight: '10px',
    border: 'none',
    borderRadius: '4px',
    cursor: 'pointer',
    fontSize: '14px',
    fontWeight: 'bold',
  },
  buttonPrimary: {
    backgroundColor: '#2196F3',
    color: 'white',
  },
  buttonDanger: {
    backgroundColor: '#f44336',
    color: 'white',
  },
};

export default DocumentUploadComponent;
