fix this file for any errors and share the updated one:
import { useState, useRef } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Loader2, Upload, FileText, CheckCircle, AlertCircle } from "lucide-react";
import { toast } from "@/hooks/use-toast";
import { uploadFileForWebhook } from "@/utils/fileUtils";
import { supabase } from "@/integrations/supabase/client";
import { v4 as uuidv4 } from "uuid";

// The webhook URL for file uploads
const FILE_WEBHOOK_URL = "https://n8n-lcsuh-u37369.vm.elestio.app/webhook-test/c472f28c-85d6-44ac-b2fe-11f7d35f178f";

interface TestFileUploaderProps {
  onFileUploaded?: (fileName: string) => void;
}

const TestFileUploader = ({ onFileUploaded }: TestFileUploaderProps) => {
  const [file, setFile] = useState<File | null>(null);
  const [isUploading, setIsUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [uploadStatus, setUploadStatus] = useState<"idle" | "uploading" | "success" | "error">("idle");
  const [webhookResponse, setWebhookResponse] = useState<any>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [userId, setUserId] = useState<string>(() => {
    // Use stored ID from localStorage or create new one
    const storedId = localStorage.getItem('testUserId');
    return storedId || uuidv4();
  });

  // Save userId to localStorage whenever it changes
  const updateUserId = (newId: string) => {
    setUserId(newId);
    localStorage.setItem('testUserId', newId);
  };

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const selectedFile = e.target.files?.[0];
    if (selectedFile) {
      setFile(selectedFile);
      toast({
        title: "File selected",
        description: `${selectedFile.name} (${formatFileSize(selectedFile.size)})`
      });
    }
  };

  const formatFileSize = (size: number): string => {
    if (size < 1024) return `${size} bytes`;
    if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`;
    return `${(size / (1024 * 1024)).toFixed(2)} MB`;
  };

  const simulateProgress = () => {
    // Simulate progress for better UX
    let progress = 0;
    const interval = setInterval(() => {
      progress += Math.random() * 10;
      if (progress > 95) {
        progress = 95; // Hold at 95% until we get response
        clearInterval(interval);
      }
      setUploadProgress(progress);
    }, 300);
    
    return () => clearInterval(interval);
  };

  const handleUpload = async () => {
    if (!file) {
      toast({
        title: "No file selected",
        description: "Please select a file to upload",
        variant: "destructive"
      });
      return;
    }

    try {
      setIsUploading(true);
      setUploadStatus("uploading");
      
      // Start progress simulation
      const stopProgress = simulateProgress();

      console.log(`Starting test upload to webhook ${FILE_WEBHOOK_URL}`);
      console.log(`File: ${file.name}, Size: ${formatFileSize(file.size)}, Type: ${file.type}`);
      console.log("Using user ID for webhook and database:", userId);
      
      const timestamp = Date.now();
      const sessionId = `session_${timestamp}_${Math.random().toString(36).substring(2, 10)}`;
      const filePath = `${timestamp}_${file.name}`;
      
      // Upload to storage first
      const { data: uploadData, error: uploadError } = await supabase
        .storage
        .from('file_uploads')
        .upload(filePath, file, {
          cacheControl: '3600',
          upsert: true
        });
        
      if (uploadError) {
        console.error("Storage upload error:", uploadError);
        throw uploadError;
      }
      
      // Get public URL
      const { data: publicUrlData } = supabase
        .storage
        .from('file_uploads')
        .getPublicUrl(filePath);
        
      const publicUrl = publicUrlData.publicUrl;
      
      // CRITICAL: This exact payload structure is required for n8n Supabase node
      // The node will filter on $json.body.record.user_id
      const webhookPayload = {
        event: "INSERT",
        table: "files",
        schema: "public",
        record: {
          id: uuidv4(),
          file_name: file.name,
          file_path: filePath,
          file_type: file.type,
          file_size: file.size,
          user_id: userId, // Ensures record.user_id is at the correct path
          created_at: new Date().toISOString(),
          metadata: {
            originalName: file.name,
            publicUrl: publicUrl,
            sessionId: sessionId,
            timestamp: new Date().toISOString()
          }
        },
        type: "INSERT",
        old_record: null
      };
      
      console.log("Sending webhook payload to n8n Supabase node:", JSON.stringify(webhookPayload, null, 2));
      console.log("CRITICAL PATH CHECK - USER_ID PATH:", webhookPayload.record.user_id);
      console.log("This must match n8n filter: {{ $json.body.record.user_id }}");

      // Try different webhook approaches to ensure delivery
      let webhookSuccess = false;
      let responseText = "";
      
      // First attempt with full parameters
      try {
        console.log("Attempting primary webhook call with application/json Content-Type");
        const response = await fetch(FILE_WEBHOOK_URL, {
          method: "POST",
          headers: {
            "Content-Type": "application/json", // Ensure this is application/json
            "X-Source": "AiCE-Test-Upload",
            "X-Session-ID": sessionId,
            "X-User-ID": userId,
            "X-Webhook-Source": "TestFileUploader"
          },
          body: JSON.stringify(webhookPayload)
        });
        
        console.log("Webhook response status:", response.status);
        
        if (response.ok) {
          webhookSuccess = true;
          try {
            const responseData = await response.json();
            console.log("Webhook JSON response:", responseData);
            setWebhookResponse(responseData);
            responseText = JSON.stringify(responseData);
          } catch (e) {
            const textResp = await response.text();
            console.log("Webhook text response:", textResp);
            setWebhookResponse({ message: textResp, success: true });
            responseText = textResp;
          }
        } else {
          console.warn(`Webhook request failed with status: ${response.status}`);
          responseText = await response.text() || `Error ${response.status}: ${response.statusText}`;
        }
      } catch (fetchError) {
        console.error("Error with webhook request:", fetchError);
      }
      
      // If first attempt fails, try no-cors as fallback
      if (!webhookSuccess) {
        console.log("First webhook attempt failed, trying no-cors fallback...");
        try {
          await fetch(FILE_WEBHOOK_URL, {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              "X-Source": "AiCE-Test-Upload",
              "X-Session-ID": sessionId,
              "X-User-ID": userId,
              "X-Webhook-Source": "TestFileUploader"
            },
            mode: "no-cors",
            body: JSON.stringify(webhookPayload)
          });
          
          console.log("No-cors fallback webhook request sent");
          webhookSuccess = true;
          setWebhookResponse({ 
            success: true, 
            message: "Webhook triggered via no-cors fallback. NOTE: The response is invisible due to CORS restrictions, but the webhook was likely triggered.",
            userId: userId,
            sessionId: sessionId,
            publicUrl: publicUrl,
            filePath: filePath
          });
        } catch (noCorsError) {
          console.error("Even no-cors fallback failed:", noCorsError);
        }
      }
      
      // MOST IMPORTANT: Ensure consistent record in database for n8n to query
      try {
        console.log("Inserting database record with user_id:", userId);
        
        // Use the SAME USER ID that was in the webhook payload
        // This is critical - both the webhook and database record must use identical user_id
        const { data: fileRecord, error: insertError } = await supabase
          .from('files')
          .insert({
            file_name: file.name,
            file_path: filePath,
            file_type: file.type,
            file_size: file.size,
            user_id: userId, // This must match exactly what was in webhook
            metadata: {
              originalName: file.name,
              publicUrl: publicUrl,
              sessionId: sessionId,
              timestamp: new Date().toISOString(),
              webhookSent: true,
              webhook_response: responseText || "No response received"
            }
          })
          .select();

        if (insertError) {
          console.error("Error inserting file record:", insertError);
          
          // Try direct insert with more basic data
          const { data: publicRecord, error: publicInsertError } = await supabase
            .from('files')
            .insert({
              file_name: file.name,
              file_path: filePath,
              file_type: file.type,
              file_size: file.size,
              user_id: userId, // Ensure the user_id is set correctly
              metadata: {
                originalName: file.name,
                publicUrl: publicUrl,
                sessionId: sessionId,
                timestamp: new Date().toISOString(),
                webhookSent: true,
                direct_insert: true
              }
            });
            
          if (publicInsertError) {
            console.error("Even basic insert failed:", publicInsertError);
          } else {
            console.log("File record inserted via simplified method");
            webhookSuccess = true;
          }
        } else {
          console.log("File record inserted successfully:", fileRecord);
          console.log("This record should now be queryable via n8n Supabase node with filter:");
          console.log("user_id equals", userId);
          
          // Copy the userId to the clipboard for easy use in n8n configuration
          navigator.clipboard.writeText(userId)
            .then(() => {
              toast({
                title: "User ID Copied",
                description: "User ID copied to clipboard for n8n configuration"
              });
            })
            .catch(err => console.error("Failed to copy: ", err));
            
          webhookSuccess = true;
        }
      } catch (dbError) {
        console.error("Database insertion error:", dbError);
      }
      
      stopProgress();
      
      if (webhookSuccess) {
        setUploadProgress(100);
        setUploadStatus("success");
        
        // Call the callback to notify parent component
        if (onFileUploaded) {
          onFileUploaded(file.name);
        }
        
        toast({
          title: "File uploaded successfully",
          description: `File has been uploaded with user_id: ${userId.substring(0, 8)}...`
        });
      } else {
        setUploadStatus("error");
        toast({
          title: "Upload failed",
          description: "Failed to trigger webhook. Database entry was created as fallback.",
          variant: "destructive"
        });
      }
      
    } catch (error: any) {
      console.error("Error uploading file:", error);
      setUploadStatus("error");
      toast({
        title: "Upload failed",
        description: error.message || "An unknown error occurred",
        variant: "destructive"
      });
    } finally {
      setIsUploading(false);
    }
  };

  return (
    <div className="space-y-6">
      {/* User ID for testing - PERSISTENT */}
      <div className="border rounded-md p-3 bg-blue-50 dark:bg-blue-900/20">
        <p className="text-sm font-medium mb-2 flex items-center text-blue-800 dark:text-blue-300">
          <AlertCircle className="h-4 w-4 mr-2" />
          Test User ID for n8n Filter
        </p>
        <div className="flex items-center gap-2 bg-white dark:bg-blue-900/40 rounded p-2">
          <code className="text-xs font-mono flex-1 break-all">{userId}</code>
          <Button 
            size="sm" 
            variant="ghost" 
            onClick={() => {
              navigator.clipboard.writeText(userId);
              toast({ title: "User ID copied to clipboard" });
            }}
          >
            Copy
          </Button>
          <Button 
            size="sm" 
            variant="outline" 
            onClick={() => {
              const newId = uuidv4();
              updateUserId(newId);
              toast({ 
                title: "New User ID Generated", 
                description: "Remember to update your n8n filter with this new ID" 
              });
            }}
          >
            New ID
          </Button>
        </div>
        <p className="text-xs mt-2 text-blue-700 dark:text-blue-400">
          This ID will be used for the file's <code>user_id</code> field. It will persist between refreshes.
          The n8n filter should use: <code>{{ "$json.body.record.user_id" }}</code> equals this ID.
        </p>
      </div>
      
      {/* File selection area */}
      <div 
        className="border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-8 text-center hover:bg-gray-50 dark:hover:bg-gray-800/50 transition cursor-pointer"
        onClick={() => fileInputRef.current?.click()}
      >
        {!file ? (
          <>
            <Upload className="h-10 w-10 mx-auto mb-4 text-gray-400" />
            <h3 className="text-lg font-medium mb-2">Select File for n8n Testing</h3>
            <p className="text-sm text-muted-foreground mb-2">
              Upload a file to test the n8n webhook integration
            </p>
            <p className="text-xs text-muted-foreground">
              PDF, TXT, DOCX, or PPT (max 25MB)
            </p>
          </>
        ) : (
          <>
            <FileText className="h-10 w-10 mx-auto mb-4 text-primary/70" />
            <h3 className="text-lg font-medium mb-2">File Selected</h3>
            <p className="text-sm font-medium text-primary">{file.name}</p>
            <p className="text-xs text-muted-foreground mt-1">
              {formatFileSize(file.size)} • {file.type || "Unknown type"}
            </p>
          </>
        )}
        
        <input
          ref={fileInputRef}
          type="file"
          className="hidden"
          onChange={handleFileChange}
          accept=".pdf,.txt,.doc,.docx,.ppt,.pptx"
        />
      </div>
      
      {/* Upload button & progress */}
      <div className="space-y-4">
        <Button 
          className="w-full" 
          onClick={handleUpload}
          disabled={isUploading || !file}
        >
          {isUploading ? (
            <>
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              Uploading & Triggering Webhook...
            </>
          ) : (
            <>
              <Upload className="mr-2 h-4 w-4" />
              Upload File & Trigger n8n Webhook
            </>
          )}
        </Button>
        
        {uploadStatus !== "idle" && (
          <Progress value={uploadProgress} className="h-2" />
        )}
      </div>
      
      {/* Status and response info */}
      {uploadStatus === "success" && (
        <Alert className="bg-green-50 dark:bg-green-900/20 border-green-200">
          <CheckCircle className="h-4 w-4 text-green-600 dark:text-green-400" />
          <AlertDescription className="text-green-800 dark:text-green-300">
            <p className="font-medium">Upload successful</p>
            <p className="text-sm mt-1">File uploaded and webhook triggered successfully.</p>
            
            {webhookResponse && (
              <div className="mt-2 bg-white dark:bg-green-800/20 p-2 rounded">
                <p className="text-xs font-medium">n8n Filter Information:</p>
                <div className="mt-1 grid grid-cols-1 gap-1 text-xs">
                  <div>
                    <span className="font-medium">User ID:</span> 
                    <code className="ml-1 bg-green-100 dark:bg-green-900/50 px-1 rounded font-mono">
                      {webhookResponse.userId || userId}
                    </code>
                  </div>
                  <div>
                    <span className="font-medium">Filter Expression:</span>
                    <code className="ml-1 bg-green-100 dark:bg-green-900/50 px-1 rounded font-mono">
                      {"{{ $json.body.record.user_id }}"}
                    </code>
                  </div>
                </div>
                
                <p className="text-xs mt-3 text-green-700 dark:text-green-400">
                  Your n8n Supabase node should now be able to find this file record by filtering on user_id = {webhookResponse.userId || userId}
                </p>
              </div>
            )}
          </AlertDescription>
        </Alert>
      )}
      
      {uploadStatus === "error" && (
        <Alert className="bg-red-50 dark:bg-red-900/20 border-red-200">
          <AlertCircle className="h-4 w-4 text-red-600 dark:text-red-400" />
          <AlertDescription className="text-red-800 dark:text-red-300">
            <p className="font-medium">Upload failed</p>
            <p className="text-sm mt-1">
              {webhookResponse?.error || "There was an error uploading the file or triggering the webhook."}
            </p>
            
            <div className="mt-3">
              <Button size="sm" variant="outline" onClick={() => setUploadStatus("idle")}>
                Try Again
              </Button>
            </div>
          </AlertDescription>
        </Alert>
      )}

      {/* Debug info */}
      <div className="text-xs text-muted-foreground border-t pt-4 mt-6">
        <p>Webhook URL: {FILE_WEBHOOK_URL}</p>
        <p className="mt-1">Testing format: <code>{"body.record.user_id"}</code> structure expected by n8n</p>
        <p className="mt-1">Headers sent: <code>X-Session-ID, X-User-ID, X-Source, Content-Type: application/json</code></p>
        <p className="mt-1">Fixed structure: <code>event, table, schema, record, record.user_id</code> for n8n Supabase node</p>
      </div>
    </div>
  );
};

export default TestFileUploader;