import { useState, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { 
  Upload, 
  FileText, 
  CheckCircle, 
  XCircle, 
  AlertCircle, 
  Server, 
  RefreshCw,
  Loader2,
  Download
} from 'lucide-react';
import { WorkPackage } from '@/types/traceability';
import { parseCSVContent, ParseResult } from '@/lib/csvParser';

const STORAGE_KEY = 'traceability_data';
const SERVER_URL_KEY = 'traceability_server_url';

// API URL for production deployment
const API_URL = import.meta.env.VITE_API_URL || '';

interface DataUpdateDialogProps {
  onDataLoaded: (workPackages: WorkPackage[]) => void;
  onClose?: () => void;
}

export function DataUpdateDialog({ onDataLoaded, onClose }: DataUpdateDialogProps) {
  const [activeTab, setActiveTab] = useState('upload');
  const [isLoading, setIsLoading] = useState(false);
  const [parseResult, setParseResult] = useState<ParseResult | null>(null);
  const [logs, setLogs] = useState<string[]>([]);
  const [errors, setErrors] = useState<string[]>([]);
  const [fileName, setFileName] = useState<string>('');
  const fileInputRef = useRef<HTMLInputElement>(null);
  
  // Server endpoint config - persisted
  const [serverUrl, setServerUrl] = useState(() => 
    localStorage.getItem(SERVER_URL_KEY) || (API_URL ? `${API_URL}/api/traceability` : '/api/traceability')
  );
  
  // Drag and drop state
  const [isDragging, setIsDragging] = useState(false);

  const addLog = (log: string) => {
    setLogs(prev => [...prev, log]);
  };

  const persistData = (workPackages: WorkPackage[]) => {
    const data = {
      lastUpdated: new Date().toISOString(),
      workPackages
    };
    localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
    addLog(`💾 Data persisted to storage (${workPackages.length} items)`);
  };

  const handleFile = async (file: File) => {
    setFileName(file.name);
    setIsLoading(true);
    setLogs([]);
    setErrors([]);
    
    try {
      addLog(`📂 Reading file: ${file.name} (${(file.size / 1024).toFixed(1)} KB)`);
      const text = await file.text();
      addLog(`📝 File loaded, ${text.length} characters`);
      
      const result = parseCSVContent(text);
      setParseResult(result);
      setLogs(prev => [...prev, ...result.logs]);
      setErrors(result.errors);
    } finally {
      setIsLoading(false);
    }
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
    const file = e.dataTransfer.files[0];
    if (file && file.name.endsWith('.csv')) {
      handleFile(file);
    }
  };

  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) handleFile(file);
  };

  // Reload from static CSV file
  const handleReloadFromCSV = async () => {
    setIsLoading(true);
    setLogs([]);
    setErrors([]);
    setParseResult(null);
    
    try {
      const cacheBuster = `?t=${Date.now()}`;
      addLog(`🔍 Fetching /data/traceability_export.csv${cacheBuster}`);
      
      const response = await fetch(`/data/traceability_export.csv${cacheBuster}`);
      
      if (!response.ok) {
        throw new Error(`Failed to load CSV: ${response.status} ${response.statusText}`);
      }
      
      const csvText = await response.text();
      addLog(`📄 Received ${csvText.length} bytes`);
      
      const result = parseCSVContent(csvText);
      setParseResult(result);
      setLogs(prev => [...prev, ...result.logs]);
      setErrors(result.errors);
      
    } catch (error) {
      const errorMsg = error instanceof Error ? error.message : 'Unknown error';
      setErrors([errorMsg]);
      addLog(`❌ Error: ${errorMsg}`);
    } finally {
      setIsLoading(false);
    }
  };

  // Trigger sync from OpenProject (runs Python script on server)
  const handleSyncFromServer = async () => {
    if (!serverUrl) {
      setErrors(['Please enter a server endpoint URL']);
      return;
    }
    
    localStorage.setItem(SERVER_URL_KEY, serverUrl);
    
    setIsLoading(true);
    setLogs([]);
    setErrors([]);
    setParseResult(null);
    
    try {
      // First, trigger the sync (runs Python script)
      const syncUrl = serverUrl.replace(/\/api\/traceability\/?$/, '/api/traceability/sync');
      addLog(`🔄 Triggering sync at: ${syncUrl}`);
      
      const syncResponse = await fetch(syncUrl, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' }
      });
      
      if (!syncResponse.ok) {
        const errorData = await syncResponse.json().catch(() => ({}));
        throw new Error(errorData.error || `Sync failed: ${syncResponse.status}`);
      }
      
      const syncResult = await syncResponse.json();
      addLog(`✅ Sync complete: ${syncResult.message}`);
      if (syncResult.stdout) {
        syncResult.stdout.split('\n').filter(Boolean).forEach((line: string) => {
          addLog(`📋 ${line}`);
        });
      }
      
      // Now fetch the updated data
      addLog(`🔍 Fetching updated data from: ${serverUrl}`);
      
      const response = await fetch(serverUrl, {
        method: 'GET',
        headers: { 'Accept': 'application/json, text/csv' }
      });
      
      if (!response.ok) {
        throw new Error(`Server Error: ${response.status} ${response.statusText}`);
      }
      
      const contentType = response.headers.get('content-type') || '';
      addLog(`📄 Response content-type: ${contentType}`);
      
      if (contentType.includes('text/csv')) {
        addLog(`📋 Parsing CSV response...`);
        const csvText = await response.text();
        const result = parseCSVContent(csvText);
        
        setLogs(prev => [...prev, ...result.logs]);
        setErrors(result.errors);
        setParseResult(result);
        
      } else if (contentType.includes('application/json')) {
        addLog(`📋 Parsing JSON response...`);
        const data = await response.json();
        
        let workPackages: WorkPackage[];
        if (Array.isArray(data)) {
          workPackages = data;
        } else if (data.workPackages) {
          workPackages = data.workPackages;
        } else {
          throw new Error('Invalid JSON format: expected array or {workPackages: [...]}');
        }
        
        addLog(`✅ Received ${workPackages.length} work packages`);
        
        const typeCounts = workPackages.reduce((acc, wp) => {
          acc[wp.type] = (acc[wp.type] || 0) + 1;
          return acc;
        }, {} as Record<string, number>);
        
        setParseResult({
          success: true,
          workPackages,
          logs: [],
          errors: [],
          typeCounts
        });
      } else {
        addLog(`⚠️ Unknown content-type, attempting CSV parse...`);
        const text = await response.text();
        const result = parseCSVContent(text);
        setLogs(prev => [...prev, ...result.logs]);
        setErrors(result.errors);
        setParseResult(result);
      }
      
    } catch (error) {
      const errorMsg = error instanceof Error ? error.message : 'Unknown error';
      setErrors([errorMsg]);
      addLog(`❌ Error: ${errorMsg}`);
    } finally {
      setIsLoading(false);
    }
  };

  // Just fetch existing data (no sync)
  const handleFetchFromServer = async () => {
    if (!serverUrl) {
      setErrors(['Please enter a server endpoint URL']);
      return;
    }
    
    localStorage.setItem(SERVER_URL_KEY, serverUrl);
    
    setIsLoading(true);
    setLogs([]);
    setErrors([]);
    setParseResult(null);
    
    try {
      addLog(`🔍 Connecting to server: ${serverUrl}`);
      
      const response = await fetch(serverUrl, {
        method: 'GET',
        headers: {
          'Accept': 'application/json, text/csv'
        }
      });
      
      if (!response.ok) {
        throw new Error(`Server Error: ${response.status} ${response.statusText}`);
      }
      
      const contentType = response.headers.get('content-type') || '';
      addLog(`📄 Response content-type: ${contentType}`);
      
      if (contentType.includes('text/csv')) {
        addLog(`📋 Parsing CSV response...`);
        const csvText = await response.text();
        const result = parseCSVContent(csvText);
        
        setLogs(prev => [...prev, ...result.logs]);
        setErrors(result.errors);
        setParseResult(result);
        
      } else if (contentType.includes('application/json')) {
        addLog(`📋 Parsing JSON response...`);
        const data = await response.json();
        
        let workPackages: WorkPackage[];
        if (Array.isArray(data)) {
          workPackages = data;
        } else if (data.workPackages) {
          workPackages = data.workPackages;
        } else {
          throw new Error('Invalid JSON format: expected array or {workPackages: [...]}');
        }
        
        addLog(`✅ Received ${workPackages.length} work packages`);
        
        const typeCounts = workPackages.reduce((acc, wp) => {
          acc[wp.type] = (acc[wp.type] || 0) + 1;
          return acc;
        }, {} as Record<string, number>);
        
        setParseResult({
          success: true,
          workPackages,
          logs: [],
          errors: [],
          typeCounts
        });
      } else {
        addLog(`⚠️ Unknown content-type, attempting CSV parse...`);
        const text = await response.text();
        const result = parseCSVContent(text);
        setLogs(prev => [...prev, ...result.logs]);
        setErrors(result.errors);
        setParseResult(result);
      }
      
    } catch (error) {
      const errorMsg = error instanceof Error ? error.message : 'Unknown error';
      setErrors([errorMsg]);
      addLog(`❌ Error: ${errorMsg}`);
    } finally {
      setIsLoading(false);
    }
  };

  const handleApply = () => {
    if (parseResult?.success && parseResult.workPackages.length > 0) {
      persistData(parseResult.workPackages);
      onDataLoaded(parseResult.workPackages);
      onClose?.();
    }
  };

  const handleReset = () => {
    setParseResult(null);
    setFileName('');
    setLogs([]);
    setErrors([]);
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  };

  return (
    <Card className="w-full">
      <CardHeader>
        <CardTitle className="flex items-center gap-2">
          <RefreshCw className="h-5 w-5" />
          Update Traceability Data
        </CardTitle>
        <CardDescription>
          Upload a CSV file, reload from static file, or sync from OpenProject
        </CardDescription>
      </CardHeader>
      <CardContent className="space-y-4">
        <Tabs value={activeTab} onValueChange={setActiveTab}>
          <TabsList className="grid w-full grid-cols-2">
            <TabsTrigger value="upload" className="flex items-center gap-2">
              <Upload className="h-4 w-4" />
              Upload / Reload
            </TabsTrigger>
            <TabsTrigger value="server" className="flex items-center gap-2">
              <Server className="h-4 w-4" />
              Server Sync
            </TabsTrigger>
          </TabsList>

          {/* Tab 1: Manual CSV Upload / Reload */}
          <TabsContent value="upload" className="space-y-4">
            <div
              onDrop={handleDrop}
              onDragOver={(e) => { e.preventDefault(); setIsDragging(true); }}
              onDragLeave={() => setIsDragging(false)}
              className={`border-2 border-dashed rounded-lg p-8 text-center transition-colors cursor-pointer ${
                isDragging ? 'border-primary bg-primary/5' : 'border-muted-foreground/25 hover:border-primary/50'
              }`}
              onClick={() => fileInputRef.current?.click()}
            >
              <input
                ref={fileInputRef}
                type="file"
                accept=".csv"
                onChange={handleFileSelect}
                className="hidden"
              />
              <FileText className="h-10 w-10 mx-auto mb-3 text-muted-foreground" />
              <p className="text-sm text-muted-foreground">
                {fileName ? (
                  <span className="font-medium text-foreground">{fileName}</span>
                ) : (
                  <>Drop CSV here or <span className="text-primary underline">browse</span></>
                )}
              </p>
            </div>
            
            <div className="flex gap-2">
              <Button 
                variant="outline" 
                onClick={handleReloadFromCSV}
                disabled={isLoading}
                className="flex-1"
              >
                {isLoading ? (
                  <><Loader2 className="h-4 w-4 mr-2 animate-spin" /> Loading...</>
                ) : (
                  <><Download className="h-4 w-4 mr-2" /> Reload from Static CSV</>
                )}
              </Button>
            </div>
            
            <p className="text-xs text-muted-foreground">
              Run <code className="bg-muted px-1 rounded">python get_traceability.py</code> to generate the CSV file, then reload.
            </p>
          </TabsContent>

          {/* Tab 2: Server Sync */}
          <TabsContent value="server" className="space-y-4">
            <div className="space-y-3">
              <div>
                <Label htmlFor="serverUrl">API Endpoint</Label>
                <Input
                  id="serverUrl"
                  placeholder="/api/traceability or https://your-api.com/api/traceability"
                  value={serverUrl}
                  onChange={(e) => setServerUrl(e.target.value)}
                />
                <p className="text-xs text-muted-foreground mt-1">
                  Uses the data service API to sync with OpenProject
                </p>
              </div>
              
              <div className="grid grid-cols-2 gap-2">
                <Button 
                  onClick={handleSyncFromServer} 
                  disabled={isLoading || !serverUrl}
                >
                  {isLoading ? (
                    <><Loader2 className="h-4 w-4 mr-2 animate-spin" /> Syncing...</>
                  ) : (
                    <><RefreshCw className="h-4 w-4 mr-2" /> Sync from OpenProject</>
                  )}
                </Button>
                <Button 
                  variant="outline"
                  onClick={handleFetchFromServer} 
                  disabled={isLoading || !serverUrl}
                >
                  {isLoading ? (
                    <><Loader2 className="h-4 w-4 mr-2 animate-spin" /> Fetching...</>
                  ) : (
                    <><Server className="h-4 w-4 mr-2" /> Fetch Existing Data</>
                  )}
                </Button>
              </div>
            </div>
            
            <div className="bg-muted/50 rounded-lg p-3 text-xs space-y-2">
              <p className="font-medium">How it works:</p>
              <ul className="list-disc ml-4 space-y-1 text-muted-foreground">
                <li><strong>Sync from OpenProject</strong>: Runs the Python script on the server to fetch latest data from OpenProject API</li>
                <li><strong>Fetch Existing Data</strong>: Gets the last synced CSV from the server (no OpenProject call)</li>
              </ul>
              <p className="text-muted-foreground mt-2">
                Note: Server sync only works in deployed environment with the data-service running.
              </p>
            </div>
          </TabsContent>
        </Tabs>

        {/* Results Section */}
        {(parseResult || errors.length > 0) && (
          <div className="space-y-3 pt-4 border-t">
            <div className="flex items-center gap-2">
              {parseResult?.success ? (
                <>
                  <CheckCircle className="h-5 w-5 text-green-500" />
                  <span className="font-medium text-green-700 dark:text-green-400">
                    Successfully parsed {parseResult.workPackages.length} work packages
                  </span>
                </>
              ) : errors.length > 0 ? (
                <>
                  <XCircle className="h-5 w-5 text-red-500" />
                  <span className="font-medium text-red-700 dark:text-red-400">Operation failed</span>
                </>
              ) : null}
            </div>

            {/* Type counts */}
            {parseResult?.success && Object.keys(parseResult.typeCounts).length > 0 && (
              <div className="flex flex-wrap gap-2">
                {Object.entries(parseResult.typeCounts)
                  .sort(([, a], [, b]) => b - a)
                  .map(([type, count]) => (
                    <Badge key={type} variant="secondary" className="capitalize">
                      {type}: {count}
                    </Badge>
                  ))}
              </div>
            )}

            {/* Errors */}
            {errors.length > 0 && (
              <div className="bg-red-500/10 border border-red-500/20 rounded-lg p-3">
                <div className="flex items-center gap-2 text-red-700 dark:text-red-400 mb-2">
                  <AlertCircle className="h-4 w-4" />
                  <span className="font-medium">Errors</span>
                </div>
                {errors.map((error, i) => (
                  <p key={i} className="text-sm text-red-600 dark:text-red-400">{error}</p>
                ))}
              </div>
            )}

            {/* Logs */}
            {logs.length > 0 && (
              <details className="text-xs" open>
                <summary className="cursor-pointer text-muted-foreground hover:text-foreground">
                  View logs ({logs.length} entries)
                </summary>
                <ScrollArea className="h-32 mt-2 bg-slate-950 rounded p-2">
                  <div className="font-mono text-green-400 space-y-0.5">
                    {logs.map((log, i) => (
                      <div key={i}>{log}</div>
                    ))}
                  </div>
                </ScrollArea>
              </details>
            )}

            {/* Actions */}
            <div className="flex gap-2 pt-2">
              {parseResult?.success && (
                <Button onClick={handleApply}>
                  <CheckCircle className="h-4 w-4 mr-2" />
                  Apply & Save
                </Button>
              )}
              <Button variant="outline" onClick={handleReset}>
                Reset
              </Button>
              {onClose && (
                <Button variant="ghost" onClick={onClose}>
                  Cancel
                </Button>
              )}
            </div>
          </div>
        )}
      </CardContent>
    </Card>
  );
}
