import { useState, useEffect, useCallback } from 'react';
import { AppLayout } from '../../components/layout/AppLayout';
import { connectorsApi } from '../../api/connectors';
import type { ConnectorDef, ConnectorRecord, ConnectorLog, ConfigField } from '../../api/connectors';
import { useAuth } from '../../contexts/AuthContext';
import {
  Plug,
  Plus,
  X,
  RefreshCw,
  Trash2,
  CheckCircle2,
  AlertCircle,
  Loader2,
  ArrowRight,
  Clock,
  ExternalLink,
  Activity,
  Shield,
  Eye,
} from 'lucide-react';

// Map service name to icon color/category
const categoryConfig: Record<string, { bg: string; icon: string; label: string }> = {
  crm: { bg: 'bg-blue-100', icon: 'text-blue-600', label: 'CRM' },
  accounting: { bg: 'bg-green-100', icon: 'text-green-600', label: 'Accounting' },
  advertising: { bg: 'bg-purple-100', icon: 'text-purple-600', label: 'Advertising' },
  automation: { bg: 'bg-orange-100', icon: 'text-orange-600', label: 'Automation' },
  telephony: { bg: 'bg-amber-100', icon: 'text-amber-600', label: 'Telephony' },
  default: { bg: 'bg-surface-100', icon: 'text-surface-600', label: 'Integration' },
};

function getCategoryConfig(service: string) {
  // Infer category from service name
  if (service === 'hubspot') return categoryConfig.crm;
  if (service === 'quickbooks') return categoryConfig.accounting;
  if (service === 'google_ads' || service === 'googleads') return categoryConfig.advertising;
  if (service === 'zapier') return categoryConfig.automation;
  if (service === 'sms') return categoryConfig.telephony;
  return categoryConfig.default;
}

function statusConfig(status: string) {
  switch (status) {
    case 'connected':
      return { icon: CheckCircle2, color: 'text-green-600', label: 'Connected' };
    case 'syncing':
      return { icon: RefreshCw, color: 'text-blue-600', label: 'Syncing...' };
    case 'error':
      return { icon: AlertCircle, color: 'text-red-600', label: 'Error' };
    default:
      return { icon: Clock, color: 'text-surface-400', label: 'Inactive' };
  }
}

// Connector card for available (not yet connected) integrations
function AvailableCard({
  connector,
  onConnect,
  disabled,
}: {
  connector: ConnectorDef;
  onConnect: (c: ConnectorDef) => void;
  disabled?: boolean;
}) {
  const cat = getCategoryConfig(connector.service);
  return (
    <div className={`group relative flex flex-col rounded-xl border border-surface-200 bg-white p-5 sm:p-6 transition-shadow hover:shadow-md ${disabled ? 'opacity-60' : ''}`}>
      <div className="mb-4 flex items-start justify-between">
        <div className="flex items-center gap-3">
          <div className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-lg ${cat.bg}`}>
            <Plug className={`h-5 w-5 ${cat.icon}`} />
          </div>
          <div>
            <h3 className="text-sm font-semibold text-surface-900">{connector.name}</h3>
            <p className="text-xs text-surface-500">{cat.label}</p>
          </div>
        </div>
        <span className="rounded-full bg-surface-100 px-2 py-0.5 text-[10px] font-medium text-surface-500">
          {connector.auth_type === 'oauth2' ? 'OAuth' : 'API Key'}
        </span>
      </div>

      <p className="mb-4 text-sm text-surface-600 flex-1">{connector.description}</p>

      <div className="mb-4 flex flex-wrap gap-1.5">
        {(connector.capabilities || []).slice(0, 4).map((cap) => (
          <span
            key={cap}
            className="rounded-md bg-surface-50 px-2 py-0.5 text-[10px] font-medium text-surface-500"
          >
            {cap}
          </span>
        ))}
        {connector.capabilities && connector.capabilities.length > 4 && (
          <span className="rounded-md bg-surface-50 px-2 py-0.5 text-[10px] font-medium text-surface-500">
            +{connector.capabilities.length - 4} more
          </span>
        )}
      </div>

      <div className="mt-auto flex items-center justify-between border-t border-surface-100 pt-4">
        <a
          href={connector.docs_url}
          target="_blank"
          rel="noopener noreferrer"
          className="flex items-center gap-1 text-xs text-surface-400 hover:text-surface-600 min-h-[44px]"
        >
          Docs <ExternalLink className="h-3 w-3" />
        </a>
        {disabled ? (
          <span className="flex items-center gap-1.5 rounded-lg bg-surface-100 px-3 py-2 text-sm font-medium text-surface-400 cursor-not-allowed min-h-[44px]">
            <Eye className="h-4 w-4" />
            View Only
          </span>
        ) : (
          <button
            onClick={() => onConnect(connector)}
            className="flex items-center gap-1.5 rounded-lg bg-brand-600 px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-700 min-h-[44px]"
          >
            <Plus className="h-4 w-4" />
            Connect
          </button>
        )}
      </div>
    </div>
  );
}

// Connector card for active connections
function ActiveCard({
  connector,
  onSync,
  onDisconnect,
  onReconnect,
  syncing,
  readOnly,
  isOAuth,
}: {
  connector: ConnectorRecord;
  onSync: (id: string) => void;
  onDisconnect: (id: string) => void;
  onReconnect?: (c: ConnectorRecord) => void;
  syncing: boolean;
  readOnly?: boolean;
  isOAuth?: boolean;
}) {
  const [showLogs, setShowLogs] = useState(false);
  const [logs, setLogs] = useState<ConnectorLog[]>([]);
  const status = statusConfig(connector.status);
  const StatusIcon = status.icon;

  const loadLogs = useCallback(async () => {
    try {
      const result = await connectorsApi.logs(connector.id);
      setLogs(result.logs);
    } catch {
      setLogs([]);
    }
  }, [connector.id]);

  const toggleLogs = async () => {
    if (!showLogs) {
      await loadLogs();
    }
    setShowLogs((v) => !v);
  };

  return (
    <div className="relative flex flex-col rounded-xl border border-surface-200 bg-white p-5 sm:p-6">
      <div className="mb-4 flex items-start justify-between">
        <div className="flex items-center gap-3">
          <div className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-lg ${getCategoryConfig(connector.service).bg}`}>
            <Plug className={`h-5 w-5 ${getCategoryConfig(connector.service).icon}`} />
          </div>
          <div>
            <h3 className="text-sm font-semibold text-surface-900 capitalize">{connector.service.replace('_', ' ')}</h3>
            <div className={`flex items-center gap-1.5 ${status.color}`}>
              <StatusIcon className={`h-3.5 w-3.5 ${syncing ? 'animate-spin' : ''}`} />
              <span className="text-xs font-medium">{status.label}</span>
              {connector.last_sync_at && (
                <span className="text-xs text-surface-400">
                  {' · '}Last synced {new Date(connector.last_sync_at).toLocaleString()}
                </span>
              )}
            </div>
          </div>
        </div>
        <select
          value={connector.sync_frequency}
          onChange={(e) => {
            // For now, just visual — syncing frequency requires backend update endpoint
          }}
          className="rounded-lg border border-surface-200 bg-surface-50 px-2 py-1 text-xs font-medium text-surface-600 min-h-[44px]"
        >
          <option value="real_time">Real-time</option>
          <option value="hourly">Hourly</option>
          <option value="daily">Daily</option>
        </select>
      </div>

      {connector.error_message && (
        <div className="mb-4 flex items-start gap-2 rounded-lg bg-red-50 p-3">
          <AlertCircle className="mt-0.5 h-4 w-4 shrink-0 text-red-600" />
          <p className="text-xs text-red-700">{connector.error_message}</p>
        </div>
      )}

      <div className="mt-auto flex items-center gap-2 border-t border-surface-100 pt-4">
        {readOnly ? (
          <span className="flex items-center gap-1.5 rounded-lg bg-surface-100 px-3 py-2 text-sm font-medium text-surface-400 cursor-not-allowed min-h-[44px]">
            <Shield className="h-4 w-4" />
            Read Only
          </span>
        ) : (
          <>
            <button
              onClick={() => onSync(connector.id)}
              disabled={syncing || connector.status === 'syncing'}
              className="flex items-center gap-1.5 rounded-lg bg-surface-100 px-3 py-2 text-sm font-medium text-surface-700 transition-colors hover:bg-surface-200 disabled:opacity-50 min-h-[44px]"
            >
              <RefreshCw className={`h-4 w-4 ${syncing ? 'animate-spin' : ''}`} />
              Sync Now
            </button>
            <button
              onClick={toggleLogs}
              className="flex items-center gap-1.5 rounded-lg bg-surface-100 px-3 py-2 text-sm font-medium text-surface-700 transition-colors hover:bg-surface-200 min-h-[44px]"
            >
              <Activity className="h-4 w-4" />
              Logs
            </button>
            {isOAuth && onReconnect && (
              <button
                onClick={() => onReconnect(connector)}
                className="flex items-center gap-1.5 rounded-lg bg-brand-50 px-3 py-2 text-sm font-medium text-brand-700 transition-colors hover:bg-brand-100 min-h-[44px]"
              >
                <Plug className="h-4 w-4" />
                Reconnect
              </button>
            )}
            <button
              onClick={() => onDisconnect(connector.id)}
              className="ml-auto flex items-center gap-1.5 rounded-lg bg-red-50 px-3 py-2 text-sm font-medium text-red-600 transition-colors hover:bg-red-100 min-h-[44px]"
            >
              <Trash2 className="h-4 w-4" />
              Disconnect
            </button>
          </>
        )}
      </div>

      {/* Expandable logs */}
      {showLogs && (
        <div className="mt-4 max-h-48 overflow-y-auto rounded-lg border border-surface-200 bg-surface-50 p-3">
          {logs.length === 0 ? (
            <p className="text-xs text-surface-400">No sync logs yet</p>
          ) : (
            <div className="space-y-2">
              {logs.map((log: any) => (
                <div key={log.id} className="flex items-start gap-2 text-xs">
                  <span
                    className={`shrink-0 font-medium ${
                      log.status === 'success'
                        ? 'text-green-600'
                        : log.status === 'error'
                        ? 'text-red-600'
                        : 'text-surface-400'
                    }`}
                  >
                    {log.status}
                  </span>
                  <span className="text-surface-600">{log.event_type}</span>
                  {log.record_count > 0 && (
                    <span className="text-surface-400">{log.record_count} records</span>
                  )}
                  {log.duration_ms != null && (
                    <span className="text-surface-400">{log.duration_ms}ms</span>
                  )}
                  <span className="ml-auto shrink-0 text-surface-300">
                    {new Date(log.created_at).toLocaleTimeString()}
                  </span>
                </div>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// Connect modal
function ConnectModal({
  connector,
  onClose,
  onSuccess,
}: {
  connector: ConnectorDef;
  onClose: () => void;
  onSuccess: () => void;
}) {
  const [config, setConfig] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError('');
    setLoading(true);
    try {
      const result = await connectorsApi.create(connector.service, config, 'hourly');
      if (result.connector.status === 'connected') {
        onSuccess();
      } else {
        setError(result.connector.error_message || 'Connection failed');
      }
    } catch (err: unknown) {
      setError(
        (err as { response?: { data?: { error?: string } } })?.response?.data?.error || 'Connection failed'
      );
    } finally {
      setLoading(false);
    }
  };

  // Use config_fields if available, otherwise fall back to auth_fields
  const fields: ConfigField[] = connector.config_fields || connector.auth_fields?.map(f => ({
    name: f,
    label: f.replace(/_/g, ' ').replace(/\b\w/g, (c: string) => c.toUpperCase()),
    type: f.includes('token') || f.includes('secret') || f.includes('password') ? 'password' : 'text',
    required: true,
  })) || [];

  // Determine which fields to show based on provider selection
  const selectedProvider = config.provider;
  const shouldShowField = (field: ConfigField) => {
    if (field.name === 'account_sid') return selectedProvider === 'twilio';
    if (field.name === 'auth_id') return selectedProvider === 'plivo';
    return true; // show all other fields
  };

  return (
    <div className="fixed inset-0 z-[60] flex items-center justify-center bg-black/50 p-4">
      <div className="w-full max-w-md rounded-2xl bg-white p-6 shadow-xl">
        <div className="mb-4 flex items-center justify-between">
          <h2 className="text-lg font-semibold text-surface-900">Connect {connector.name}</h2>
          <button
            onClick={onClose}
            className="flex min-h-[44px] min-w-[44px] items-center justify-center rounded-lg text-surface-400 hover:bg-surface-100 hover:text-surface-600"
          >
            <X className="h-5 w-5" />
          </button>
        </div>

        <form onSubmit={handleSubmit} className="space-y-4">
          {fields.map((field) => {
            if (!shouldShowField(field)) return null;

            const label = field.label || field.name.replace(/_/g, ' ').replace(/\b\w/g, (c: string) => c.toUpperCase());
            const fieldType = field.type || 'text';
            const isRequired = field.required ?? true;

            return (
              <div key={field.name}>
                <label className="mb-1 block text-sm font-medium text-surface-700">
                  {label}
                  {!isRequired && <span className="text-surface-400"> (optional)</span>}
                </label>

                {fieldType === 'select' ? (
                  <select
                    className="w-full rounded-lg border border-surface-200 px-3 py-2.5 text-sm transition-colors focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-200 min-h-[44px] bg-white"
                    value={config[field.name] || ''}
                    onChange={(e) => setConfig((prev) => ({ ...prev, [field.name]: e.target.value }))}
                    required={isRequired}
                  >
                    <option value="">Select provider...</option>
                    {(field.options || []).map((opt: string) => (
                      <option key={opt} value={opt}>{opt.charAt(0).toUpperCase() + opt.slice(1)}</option>
                    ))}
                  </select>
                ) : (
                  <input
                    type={fieldType}
                    className="w-full rounded-lg border border-surface-200 px-3 py-2.5 text-sm transition-colors focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-200 min-h-[44px]"
                    placeholder={`Enter ${label.toLowerCase()}`}
                    value={config[field.name] || ''}
                    onChange={(e) => setConfig((prev) => ({ ...prev, [field.name]: e.target.value }))}
                    required={isRequired}
                  />
                )}
              </div>
            );
          })}

          {error && (
            <div className="flex items-start gap-2 rounded-lg bg-red-50 p-3">
              <AlertCircle className="mt-0.5 h-4 w-4 shrink-0 text-red-600" />
              <p className="text-xs text-red-700">{error}</p>
            </div>
          )}

          <div className="flex items-center gap-3 pt-2">
            <button
              type="button"
              onClick={onClose}
              className="flex-1 rounded-lg border border-surface-200 bg-white px-4 py-3 text-sm font-medium text-surface-700 transition-colors hover:bg-surface-50 min-h-[44px]"
            >
              Cancel
            </button>
            <button
              type="submit"
              disabled={loading}
              className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-brand-600 px-4 py-3 text-sm font-medium text-white transition-colors hover:bg-brand-700 disabled:opacity-50 min-h-[44px]"
            >
              {loading ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <>
                  <ArrowRight className="h-4 w-4" />
                  Connect
                </>
              )}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

// ─── Role / access helpers ─────────────────────────────────────────────
/** Detect demo accounts by email suffix (e.g. demo@commandcenter.com). */
function isDemoAccount(email?: string | null): boolean {
  if (!email) return false;
  const lower = email.toLowerCase();
  return lower.startsWith('demo@') || lower === 'demo';
}

// Main page
export function IntegrationsPage() {
  const { user, hasCompanyPermission } = useAuth();
  const [available, setAvailable] = useState<ConnectorDef[]>([]);
  const [connected, setConnected] = useState<ConnectorRecord[]>([]);
  const [loading, setLoading] = useState(true);
  const [syncingId, setSyncingId] = useState<string | null>(null);
  const [connectModal, setConnectModal] = useState<ConnectorDef | null>(null);
  const [toast, setToast] = useState<{ message: string; type: 'success' | 'error' } | null>(null);

  // ─── Access control derived state ───────────────────────────────────
  const canEdit = hasCompanyPermission('edit_integrations');
  const isDemo = isDemoAccount(user?.email);
  const isReadOnly = isDemo || !canEdit;

  const fetchData = useCallback(async () => {
    try {
      const [availRes, listRes] = await Promise.all([
        connectorsApi.available(),
        connectorsApi.list(),
      ]);
      setAvailable(availRes.connectors);
      setConnected(listRes.connectors);
    } catch {
      setToast({ message: 'Failed to load integrations', type: 'error' });
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const handleSync = async (id: string) => {
    if (isReadOnly) return;
    setSyncingId(id);
    try {
      await connectorsApi.sync(id);
      setToast({ message: 'Sync completed', type: 'success' });
      await fetchData();
    } catch (err: unknown) {
      setToast({ message: (err as { response?: { data?: { error?: string } } })?.response?.data?.error || 'Sync failed', type: 'error' });
    } finally {
      setSyncingId(null);
    }
  };

  const handleDisconnect = async (id: string) => {
    if (isReadOnly) return;
    try {
      await connectorsApi.remove(id);
      setToast({ message: 'Integration disconnected', type: 'success' });
      await fetchData();
    } catch (err: unknown) {
      setToast({ message: (err as { response?: { data?: { error?: string } } })?.response?.data?.error || 'Failed to disconnect', type: 'error' });
    }
  };

  const handleConnectClick = (connector: ConnectorDef) => {
    if (isReadOnly) return;
    // OAuth2 connectors redirect to provider login; manual connectors show modal
    if (connector.auth_type === 'oauth2') {
      window.location.href = `/api/connectors/oauth/authorize/${connector.service}`;
    } else {
      setConnectModal(connector);
    }
  };

  const handleReconnect = (connector: ConnectorRecord) => {
    if (isReadOnly) return;
    window.location.href = `/api/connectors/oauth/authorize/${connector.service}`;
  };

  const connectedServices = new Set(connected.map((c) => c.service));
  const unconnected = available.filter((a) => !connectedServices.has(a.service));

  // Handle OAuth callback success/error from URL params
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const success = params.get('oauth_success');
    const error = params.get('oauth_error');
    const message = params.get('message');

    if (success) {
      setToast({ message: `${success} connected successfully!`, type: 'success' });
      fetchData();
      params.delete('oauth_success');
      window.history.replaceState({}, '', window.location.pathname);
    } else if (error) {
      setToast({ message: `${message || error} connection failed. Please try again.`, type: 'error' });
      params.delete('oauth_error');
      params.delete('message');
      window.history.replaceState({}, '', window.location.pathname);
    }
  }, []);

  // Auto-dismiss toast
  useEffect(() => {
    if (toast) {
      const timer = setTimeout(() => setToast(null), 4000);
      return () => clearTimeout(timer);
    }
  }, [toast]);

  return (
    <AppLayout title="Integrations">
      {/* Toast */}
      {toast && (
        <div className="fixed top-4 right-4 z-[70] flex items-center gap-2 rounded-lg bg-surface-900 px-4 py-3 text-sm text-white shadow-lg">
          {toast.type === 'success' ? (
            <CheckCircle2 className="h-4 w-4 text-green-400" />
          ) : (
            <AlertCircle className="h-4 w-4 text-red-400" />
          )}
          {toast.message}
        </div>
      )}

      <div data-testid="page-content" className="space-y-6 sm:space-y-8">
        {/* Demo / read-only banner */}
        {isReadOnly && (
          <div className={`flex items-start gap-3 rounded-xl border p-4 ${
            isDemo
              ? 'border-amber-200 bg-amber-50'
              : 'border-blue-200 bg-blue-50'
          }`}>
            <Shield className={`mt-0.5 h-5 w-5 shrink-0 ${
              isDemo ? 'text-amber-600' : 'text-blue-600'
            }`} />
            <div>
              <p className={`text-sm font-semibold ${
                isDemo ? 'text-amber-800' : 'text-blue-800'
              }`}>
                {isDemo ? 'Demo Mode' : 'View Only'}
              </p>
              <p className={`mt-0.5 text-xs ${
                isDemo ? 'text-amber-700' : 'text-blue-700'
              }`}>
                {isDemo
                  ? 'This is a demo account. You can browse available integrations but cannot create, modify, or remove connectors. Contact your admin for full access.'
                  : 'Your current role does not have permission to manage integrations. Contact your company admin or owner to make changes.'}
              </p>
            </div>
          </div>
        )}

        {/* Header */}
        <div>
          <h1 className="text-xl sm:text-2xl font-bold text-surface-900">Integrations</h1>
          <p className="mt-1 text-sm text-surface-500">
            Connect your existing tools to pull live data into Command Sovereignty.
          </p>
        </div>

        {loading ? (
          <div className="flex items-center justify-center py-12">
            <Loader2 className="h-8 w-8 animate-spin text-brand-600" />
          </div>
        ) : (
          <>
            {/* Connected integrations */}
            <section>
              <div className="mb-4 flex items-center justify-between">
                <h2 className="text-sm font-semibold text-surface-700">
                  Connected ({connected.length})
                </h2>
              </div>

              {connected.length === 0 ? (
                <div className="rounded-xl border border-dashed border-surface-200 bg-surface-50 p-8 text-center">
                  <Plug className="mx-auto mb-3 h-8 w-8 text-surface-300" />
                  <p className="text-sm font-medium text-surface-500">No integrations connected yet</p>
                  <p className="mt-1 text-xs text-surface-400">
                    Connect your CRM, accounting, or advertising tools to start syncing data.
                  </p>
                </div>
              ) : (
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                  {connected.map((c) => (
                    <ActiveCard
                      key={c.id}
                      connector={c}
                      onSync={handleSync}
                      onDisconnect={handleDisconnect}
                      onReconnect={handleReconnect}
                      syncing={syncingId === c.id}
                      readOnly={isReadOnly}
                      isOAuth={c.auth_type === 'oauth2'}
                    />
                  ))}
                </div>
              )}
            </section>

            {/* Available integrations */}
            {unconnected.length > 0 && (
              <section>
                <div className="mb-4 flex items-center justify-between">
                  <h2 className="text-sm font-semibold text-surface-700">
                    Available Integrations ({unconnected.length})
                  </h2>
                </div>

                <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
                  {unconnected.map((c) => (
                    <AvailableCard
                      key={c.service}
                      connector={c}
                      onConnect={handleConnectClick}
                      disabled={isReadOnly}
                    />
                  ))}
                </div>
              </section>
            )}
          </>
        )}
      </div>

      {/* Connect modal — only shown if user has edit permission */}
      {connectModal && (
        <ConnectModal
          connector={connectModal}
          onClose={() => setConnectModal(null)}
          onSuccess={() => {
            setConnectModal(null);
            fetchData();
          }}
        />
      )}
    </AppLayout>
  );
}
