/**
 * Connection Manager Dialog
 *
 * Displays and manages multiple connections for a single integration.
 * Users can add, edit, and delete connections.
 */

import { useState, useCallback, useEffect } from 'react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Badge } from './ui/badge';
import { Alert, AlertDescription } from './ui/alert';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from './ui/dialog';
import {
  AlertCircle,
  ExternalLink,
  Loader2,
  Plus,
  Pencil,
  Trash2,
  ChevronLeft,
} from 'lucide-react';
import { ServiceIcon } from './ServiceIcon';
import {
  Integration,
  IntegrationConnection,
  IntegrationCredentialField,
  AffectedWorkflow,
} from '../types/integration';
import {
  getIntegrationService,
  getIntegrationMetadata,
  CredentialConfig,
} from '../services/integrations';

function credentialsToConfig(
  credentials: Record<string, IntegrationCredentialField>,
): CredentialConfig[] {
  return Object.entries(credentials).map(([field, def]) => ({
    field,
    label: def.label,
    placeholder: def.description,
  }));
}

interface WorkflowsAffectedState {
  connectionId: string;
  workflows: AffectedWorkflow[];
  message: string;
}

interface ConnectionManagerDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  integration: Integration | null;
  onConnectionsChange: () => void;
}

type DialogMode = 'list' | 'add' | 'edit';

interface FormState {
  label: string;
  credentials: Record<string, string>;
}

export function ConnectionManagerDialog({
  open,
  onOpenChange,
  integration,
  onConnectionsChange,
}: ConnectionManagerDialogProps) {
  const [mode, setMode] = useState<DialogMode>('list');
  const [connections, setConnections] = useState<IntegrationConnection[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [editingConnection, setEditingConnection] = useState<IntegrationConnection | null>(null);
  const [workflowsAffected, setWorkflowsAffected] = useState<WorkflowsAffectedState | null>(null);

  // Form state
  const [formState, setFormState] = useState<FormState>({
    label: '',
    credentials: {},
  });

  const staticMetadata = integration ? getIntegrationMetadata(integration.slug) : undefined;
  const metadata =
    staticMetadata ??
    (integration?.credentials
      ? {
          slug: integration.slug,
          name: integration.name,
          description: integration.description,
          credentials: credentialsToConfig(integration.credentials),
        }
      : undefined);
  const canUseMultiAccount = window.sequensyAPI?.capabilities?.multi_account ?? false;

  // Fetch connections when dialog opens
  const fetchConnections = useCallback(async () => {
    if (!integration) return;

    const service = getIntegrationService(integration.slug);
    if (!service) return;

    try {
      setLoading(true);
      setError(null);
      const data = await service.listConnections();
      setConnections(data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load connections');
    } finally {
      setLoading(false);
    }
  }, [integration]);

  useEffect(() => {
    if (open && integration) {
      fetchConnections();
      setMode('list');
      setEditingConnection(null);
      resetForm();
    }
  }, [open, integration, fetchConnections]);

  const resetForm = () => {
    setFormState({
      label: '',
      credentials: {},
    });
    setError(null);
  };

  const handleAddClick = () => {
    resetForm();
    setMode('add');
  };

  const handleEditClick = (connection: IntegrationConnection) => {
    setEditingConnection(connection);
    setFormState({
      label: connection.label,
      credentials: {}, // Don't pre-fill credentials for security
    });
    setError(null);
    setMode('edit');
  };

  const handleBackClick = () => {
    setMode('list');
    setEditingConnection(null);
    resetForm();
  };

  const handleCredentialChange = (field: string, value: string) => {
    setFormState((prev) => ({
      ...prev,
      credentials: {
        ...prev.credentials,
        [field]: value,
      },
    }));
  };

  const handleCreateConnection = async () => {
    if (!integration || !metadata) return;

    const service = getIntegrationService(integration.slug);
    if (!service) return;

    // Validate label
    if (!formState.label.trim()) {
      setError('Please enter a connection label');
      return;
    }

    // Check for duplicate label (case-insensitive)
    const labelLower = formState.label.trim().toLowerCase();
    const duplicate = connections.find((c) => c.label.toLowerCase() === labelLower);
    if (duplicate) {
      setError('A connection with this label already exists');
      return;
    }

    // Validate credentials
    for (const cred of metadata.credentials) {
      const value = formState.credentials[cred.field]?.trim();
      if (!value) {
        setError(`Please enter your ${cred.label}`);
        return;
      }
    }

    try {
      setSubmitting(true);
      setError(null);
      await service.createConnection(formState.label.trim(), formState.credentials);
      await fetchConnections();
      onConnectionsChange();
      setMode('list');
      resetForm();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to create connection');
    } finally {
      setSubmitting(false);
    }
  };

  const handleUpdateConnection = async () => {
    if (!integration || !editingConnection) return;

    const service = getIntegrationService(integration.slug);
    if (!service) return;

    // Validate label
    if (!formState.label.trim()) {
      setError('Please enter a connection label');
      return;
    }

    // Check for duplicate label (case-insensitive, excluding current connection)
    const labelLower = formState.label.trim().toLowerCase();
    const duplicate = connections.find(
      (c) => c.id !== editingConnection.id && c.label.toLowerCase() === labelLower,
    );
    if (duplicate) {
      setError('A connection with this label already exists');
      return;
    }

    // Build update data
    const updateData: { label?: string; credentials?: Record<string, string> } = {
      label: formState.label.trim(),
    };

    // Only include credentials if any were provided
    const hasCredentials = Object.values(formState.credentials).some((v) => v?.trim());
    if (hasCredentials) {
      updateData.credentials = formState.credentials;
    }

    try {
      setSubmitting(true);
      setError(null);
      await service.updateConnection(editingConnection.id, updateData);
      await fetchConnections();
      onConnectionsChange();
      setMode('list');
      setEditingConnection(null);
      resetForm();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to update connection');
    } finally {
      setSubmitting(false);
    }
  };

  const handleDeleteConnection = async (connectionId: string, confirmDeactivate = false) => {
    if (!integration) return;

    const service = getIntegrationService(integration.slug);
    if (!service) return;

    // Only show confirm dialog if not already confirming workflow deactivation
    if (!confirmDeactivate && !window.confirm('Are you sure you want to delete this connection?')) {
      return;
    }

    try {
      setSubmitting(true);
      setError(null);
      await service.deleteConnection(
        connectionId,
        confirmDeactivate ? { confirmDeactivateWorkflows: true } : undefined,
      );
      setWorkflowsAffected(null);
      await fetchConnections();
      onConnectionsChange();
    } catch (err: unknown) {
      // Check if this is a workflows_affected error
      const error = err as {
        code?: string;
        message?: string;
        data?: { affected_workflows?: AffectedWorkflow[] };
      };
      if (error.code === 'workflows_affected' && error.data?.affected_workflows) {
        setWorkflowsAffected({
          connectionId,
          workflows: error.data.affected_workflows,
          message: error.message || 'Active workflows will be deactivated.',
        });
      } else {
        setError(err instanceof Error ? err.message : 'Failed to delete connection');
      }
    } finally {
      setSubmitting(false);
    }
  };

  const handleConfirmDeactivateWorkflows = () => {
    if (workflowsAffected) {
      handleDeleteConnection(workflowsAffected.connectionId, true);
    }
  };

  const handleCancelPauseWorkflows = () => {
    setWorkflowsAffected(null);
  };

  const docsUrl = integration?.docs_url ?? null;

  if (!integration) return null;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <div className="flex items-center gap-3">
            {mode !== 'list' && (
              <Button variant="ghost" size="sm" className="h-8 w-8 p-0" onClick={handleBackClick}>
                <ChevronLeft className="h-4 w-4" />
              </Button>
            )}
            <ServiceIcon service={integration.icon || integration.slug} size={32} />
            <div>
              <DialogTitle className="text-slate-900">
                {mode === 'add'
                  ? `Add ${integration.name} Connection`
                  : mode === 'edit'
                    ? `Edit Connection`
                    : `${integration.name} Connections`}
              </DialogTitle>
              <DialogDescription className="text-slate-500">
                {mode === 'add'
                  ? 'Enter a label and credentials for the new connection.'
                  : mode === 'edit'
                    ? 'Update the connection label or credentials.'
                    : `Manage your ${integration.name} account connections.`}
              </DialogDescription>
            </div>
          </div>
        </DialogHeader>

        {mode === 'list' && (
          <div className="py-4">
            {loading ? (
              <div className="flex items-center justify-center py-8">
                <Loader2 className="h-6 w-6 animate-spin text-cyan-600" />
              </div>
            ) : connections.length === 0 ? (
              <div className="text-center py-8 text-slate-500">
                <p className="mb-4">No connections yet.</p>
                <Button
                  className="bg-cyan-600 hover:bg-cyan-700 text-white"
                  onClick={handleAddClick}
                >
                  <Plus className="w-4 h-4 mr-2" />
                  Add Connection
                </Button>
              </div>
            ) : (
              <div className="space-y-2">
                {connections.map((connection) => (
                  <div
                    key={connection.id}
                    className="flex items-center justify-between p-3 border rounded-lg hover:border-cyan-600 transition-colors"
                  >
                    <div>
                      <span className="font-medium text-sm text-slate-900">{connection.label}</span>
                      <p className="text-xs text-slate-500 mt-0.5">
                        Added {new Date(connection.created_at).toLocaleDateString()}
                      </p>
                    </div>
                    <div className="flex items-center gap-2">
                      <Button
                        variant="ghost"
                        size="sm"
                        className="h-8 w-8 p-0"
                        onClick={() => handleEditClick(connection)}
                      >
                        <Pencil className="h-4 w-4 text-slate-500" />
                      </Button>
                      <Button
                        variant="ghost"
                        size="sm"
                        className="h-8 w-8 p-0"
                        onClick={() => handleDeleteConnection(connection.id)}
                        disabled={submitting}
                      >
                        <Trash2 className="h-4 w-4 text-error" />
                      </Button>
                    </div>
                  </div>
                ))}

                {/* Only show "Add Another Connection" if Pro or has no connections yet */}
                {(canUseMultiAccount || connections.length === 0) && (
                  <Button variant="outline" className="w-full mt-4" onClick={handleAddClick}>
                    <Plus className="w-4 h-4 mr-2" />
                    {connections.length === 0 ? 'Add Connection' : 'Add Another Connection'}
                  </Button>
                )}
              </div>
            )}

            {error && (
              <Alert className="mt-4 bg-error-muted border-error">
                <AlertCircle className="h-4 w-4 text-error" />
                <AlertDescription className="text-error">{error}</AlertDescription>
              </Alert>
            )}

            {/* Workflows affected confirmation */}
            {workflowsAffected && (
              <div className="mt-4 p-4 border border-amber-500 bg-amber-50 rounded-lg">
                <div className="flex items-start gap-3">
                  <AlertCircle className="h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5" />
                  <div className="flex-1">
                    <p className="text-sm font-medium text-amber-800 mb-2">
                      {workflowsAffected.message}
                    </p>
                    <div className="text-sm text-amber-700 mb-3">
                      <p className="font-medium mb-1">Affected workflows:</p>
                      <ul className="list-disc list-inside space-y-0.5">
                        {workflowsAffected.workflows.map((workflow) => (
                          <li key={workflow.id}>{workflow.name}</li>
                        ))}
                      </ul>
                    </div>
                    <div className="flex gap-2">
                      <Button
                        size="sm"
                        variant="outline"
                        onClick={handleCancelPauseWorkflows}
                        disabled={submitting}
                      >
                        Cancel
                      </Button>
                      <Button
                        size="sm"
                        className="bg-amber-600 hover:bg-amber-700 text-white"
                        onClick={handleConfirmDeactivateWorkflows}
                        disabled={submitting}
                      >
                        {submitting ? (
                          <>
                            <Loader2 className="w-3 h-3 mr-1 animate-spin" />
                            Deactivating...
                          </>
                        ) : (
                          'Deactivate Workflows & Delete'
                        )}
                      </Button>
                    </div>
                  </div>
                </div>
              </div>
            )}
          </div>
        )}

        {(mode === 'add' || mode === 'edit') && metadata && (
          <div className="space-y-4 py-4">
            {/* Connection Label */}
            <div className="space-y-2">
              <Label htmlFor="connection-label" className="text-slate-900">
                Connection Label
              </Label>
              <Input
                id="connection-label"
                type="text"
                placeholder="e.g., Main Account, Support Team"
                value={formState.label}
                onChange={(e) => setFormState((prev) => ({ ...prev, label: e.target.value }))}
              />
              <p className="text-xs text-slate-500">A name to help you identify this connection.</p>
            </div>

            {/* Credential Fields */}
            {metadata.credentials.map((cred) => (
              <div key={cred.field} className="space-y-2">
                <Label htmlFor={`cred-${cred.field}`} className="text-slate-900">
                  {cred.label}
                  {mode === 'edit' && (
                    <Badge variant="outline" className="ml-2 text-xs">
                      Optional
                    </Badge>
                  )}
                </Label>
                <Input
                  id={`cred-${cred.field}`}
                  type="password"
                  placeholder={
                    mode === 'edit'
                      ? 'Leave blank to keep existing'
                      : cred.placeholder || `Enter your ${cred.label}`
                  }
                  value={formState.credentials[cred.field] || ''}
                  onChange={(e) => handleCredentialChange(cred.field, e.target.value)}
                />
                {cred.help && <p className="text-xs text-slate-500">{cred.help}</p>}
              </div>
            ))}

            {error && (
              <Alert className="bg-error-muted border-error">
                <AlertCircle className="h-4 w-4 text-error" />
                <AlertDescription className="text-error">{error}</AlertDescription>
              </Alert>
            )}

            {docsUrl && (
              <a
                href={docsUrl}
                target="_blank"
                rel="noopener noreferrer"
                className="text-xs text-cyan-600 hover:underline flex items-center gap-1"
              >
                How to get your API credentials
                <ExternalLink className="h-3 w-3" />
              </a>
            )}

            <DialogFooter className="pt-4">
              <Button variant="outline" onClick={handleBackClick}>
                Cancel
              </Button>
              <Button
                className="bg-cyan-600 hover:bg-cyan-700 text-white"
                onClick={mode === 'add' ? handleCreateConnection : handleUpdateConnection}
                disabled={submitting}
              >
                {submitting ? (
                  <>
                    <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                    {mode === 'add' ? 'Creating...' : 'Saving...'}
                  </>
                ) : mode === 'add' ? (
                  'Create Connection'
                ) : (
                  'Save Changes'
                )}
              </Button>
            </DialogFooter>
          </div>
        )}
      </DialogContent>
    </Dialog>
  );
}
