import { useDataSources, useUpdateDataSources, useTestDataSource, useRegisteredProviders } from "@/hooks/useConfig"
import { DataSourceConfig } from "@/types/config"
import { useToast } from "@/hooks/use-toast"
import { DynamicConfigForm } from "@/components/config/DynamicConfigForm"

export function DataSourceTab() {
  const { data: dataSources, isLoading: isConfigLoading } = useDataSources();
  const { data: providersMetadata, isLoading: isMetadataLoading } = useRegisteredProviders();
  
  const updateDataSources = useUpdateDataSources();
  const testDataSource = useTestDataSource();
  const { toast } = useToast();

  if (isConfigLoading || isMetadataLoading) {
    return <div>Loading data sources...</div>;
  }

  if (!providersMetadata || providersMetadata.length === 0) {
      return (
          <div className="p-4 text-center text-muted-foreground">
              No data providers registered. Please ensure provider services are running.
          </div>
      );
  }

  const handleSave = (providerId: string, config: DataSourceConfig) => {
      // We need to reconstruct the full DataSourcesConfig map
      // Note: dataSources is a HashMap<String, DataSourceConfig>
      const newDataSources = { ...dataSources, [providerId]: config };
      updateDataSources.mutate(newDataSources, {
          onSuccess: () => toast({ title: "Success", description: `${providerId} configuration saved` }),
          onError: (err) => toast({ title: "Error", description: "Failed to save: " + err, type: "error" })
      });
  };

  const handleTest = (providerId: string, config: DataSourceConfig) => {
      // Construct payload for generic test endpoint
      const payload = {
          type: providerId, 
          data: config // Send the whole config object as data
      };

      // We cast to any because TestConfigRequest type definition in frontend might be loose or generic
      testDataSource.mutate(payload as any, {
          onSuccess: (data: any) => {
            console.log("Test Connection Success Payload:", data);
            // Check both explicit false and explicit "false" string, or any other falsy indicator
            if (data.success === false || data.success === "false") {
                console.warn("Test reported success but payload indicates failure:", data);
                toast({ 
                    title: "Test Failed", 
                    description: data.message || "Connection test failed",
                    type: "error" 
                });
            } else {
                console.log("Test confirmed successful.");
                toast({ 
                    title: "Success", 
                    description: data.message || "Connection test successful" 
                });
            }
          },
          onError: (err: any) => {
            console.error("Test Connection Error:", err);
            let errorMessage = "Connection test failed";
            
            if (err.response?.data) {
                const data = err.response.data;
                console.log("Error Response Data:", data);
                // Try to parse 'details' if it exists and is a string (common-contracts error format)
                if (typeof data.details === 'string') {
                    try {
                        const parsed = JSON.parse(data.details);
                        if (parsed.message) errorMessage = parsed.message;
                        else errorMessage = data.details;
                    } catch (e) {
                        errorMessage = data.details;
                    }
                } else if (data.message) {
                    errorMessage = data.message;
                } else if (data.error) {
                    errorMessage = data.error;
                }
            }
            
            toast({ 
                title: "Test Failed", 
                description: errorMessage, 
                type: "error" 
            });
          }
      });
  };

  return (
    <div className="grid gap-6 md:grid-cols-1 lg:grid-cols-2">
      {providersMetadata.map(meta => {
        // Find existing config or create default
        const configEntry = dataSources ? (dataSources as Record<string, any>)[meta.id] : undefined;
        
        // Default config structure. 
        // Note: We default 'provider' field to the ID from metadata. 
        // Backend expects specific enum values for 'provider', but currently our IDs match (lowercase/uppercase handling needed?)
        // The backend DataSourceProvider enum is PascalCase (Tushare), but IDs are likely lowercase (tushare).
        // However, DataSourceConfig.provider is an enum.
        // We might need to map ID to Enum if strict. 
        // For now, assuming the backend persistence can handle the string or we just store it.
        // Actually, the 'provider' field in DataSourceConfig is DataSourceProvider enum. 
        // Let's hope the JSON deserialization handles "tushare" -> Tushare.
        
        const config = (configEntry || {
            provider: meta.id, // This might need capitalization adjustment
            enabled: false,
            // We init other fields as empty, they will be filled by DynamicConfigForm
        }) as DataSourceConfig;

        return (
            <DynamicConfigForm 
                key={meta.id}
                metadata={meta}
                initialConfig={config}
                onSave={(c) => handleSave(meta.id, c)}
                onTest={(c) => handleTest(meta.id, c)}
                isSaving={updateDataSources.isPending}
                isTesting={testDataSource.isPending}
            />
        )
      })}
    </div>
  )
}
