'use client';

import { useEffect, useRef, useState, useCallback } from 'react';
import { Phone, Bot, Plus, Loader2, AlertCircle } from 'lucide-react';
import { cn, formatPhone } from '@/lib/utils';
import PhoneNumberCard from './phone-number-card';
import BotRouteCard from './bot-route-card';
import ConnectionLines from './connection-lines';
import RouteConfigModal from './route-config-modal';

/* ─── Types ─── */

interface TwilioNumber {
  sid: string;
  phoneNumber: string;
  friendlyName: string;
}

interface Route {
  id: string;
  twilio_number: string;
  twilio_number_sid: string | null;
  closebot_source_id: string;
  closebot_bot_id: string | null;
  bot_name: string | null;
  greeting_message: string | null;
  after_hours_reply: string | null;
  business_hours_json: string | null;
  max_concurrent: number;
  active: number;
  created_at: string;
  updated_at: string;
}

interface CloseBotBot {
  id: string;
  name: string;
  sources: Array<{ id: string; name: string }>;
}

interface CloseBotSource {
  id: string;
  name: string;
  type: string;
}

interface ConnectionDef {
  routeId: string;
  leftIndex: number;
  rightIndex: number;
  active: boolean;
}

/* ─── New Route Dialog ─── */

function NewRouteDialog({
  numbers,
  bots,
  sources,
  existingRoutes,
  onClose,
  onCreated,
}: {
  numbers: TwilioNumber[];
  bots: CloseBotBot[];
  sources: CloseBotSource[];
  existingRoutes: Route[];
  onClose: () => void;
  onCreated: (route: Route) => void;
}) {
  const usedNumbers = new Set(existingRoutes.map(r => r.twilio_number));
  const availableNumbers = numbers.filter(n => !usedNumbers.has(n.phoneNumber));

  const [selectedNumber, setSelectedNumber] = useState('');
  const [selectedBotId, setSelectedBotId] = useState('');
  const [selectedSourceId, setSelectedSourceId] = useState('');
  const [creating, setCreating] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // When bot changes, reset source
  const selectedBot = bots.find(b => b.id === selectedBotId);

  async function handleCreate() {
    if (!selectedNumber || !selectedSourceId) return;
    setCreating(true);
    setError(null);

    const num = numbers.find(n => n.phoneNumber === selectedNumber);
    const src = sources.find(s => s.id === selectedSourceId);

    try {
      const res = await fetch('/api/routes', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          twilio_number: selectedNumber,
          twilio_number_sid: num?.sid || null,
          closebot_source_id: selectedSourceId,
          closebot_bot_id: selectedBotId || null,
          bot_name: selectedBot?.name || src?.name || 'Unnamed Bot',
        }),
      });

      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || 'Failed to create');
      }

      const route = await res.json();
      onCreated(route);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to create route');
    } finally {
      setCreating(false);
    }
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center">
      <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={onClose} />
      <div className="relative w-full max-w-lg mx-4 rounded-2xl border border-slate-700/60 bg-[#131d2e] shadow-2xl p-6">
        <h2 className="text-lg font-bold text-white mb-1">Add New Route</h2>
        <p className="text-sm text-slate-500 mb-6">Connect a Twilio phone number to a CloseBot source</p>

        <div className="space-y-4">
          {/* Twilio Number */}
          <div>
            <label className="block text-xs font-semibold uppercase tracking-wider text-slate-400 mb-2">
              Twilio Phone Number
            </label>
            <select
              value={selectedNumber}
              onChange={e => setSelectedNumber(e.target.value)}
              className="w-full rounded-lg border border-slate-700/50 bg-slate-800/50 px-4 py-2.5 text-sm text-slate-200 outline-none focus:border-cyan-500/50"
            >
              <option value="">Select a number...</option>
              {availableNumbers.map(n => (
                <option key={n.sid} value={n.phoneNumber}>
                  {formatPhone(n.phoneNumber)} — {n.friendlyName}
                </option>
              ))}
            </select>
            {availableNumbers.length === 0 && (
              <p className="text-[11px] text-amber-400 mt-1">All Twilio numbers are already routed</p>
            )}
          </div>

          {/* Bot Selection */}
          <div>
            <label className="block text-xs font-semibold uppercase tracking-wider text-slate-400 mb-2">
              CloseBot Bot (optional)
            </label>
            <select
              value={selectedBotId}
              onChange={e => { setSelectedBotId(e.target.value); setSelectedSourceId(''); }}
              className="w-full rounded-lg border border-slate-700/50 bg-slate-800/50 px-4 py-2.5 text-sm text-slate-200 outline-none focus:border-cyan-500/50"
            >
              <option value="">Select a bot...</option>
              {bots.map(b => (
                <option key={b.id} value={b.id}>{b.name}</option>
              ))}
            </select>
          </div>

          {/* Source Selection */}
          <div>
            <label className="block text-xs font-semibold uppercase tracking-wider text-slate-400 mb-2">
              CloseBot Source
            </label>
            <select
              value={selectedSourceId}
              onChange={e => setSelectedSourceId(e.target.value)}
              className="w-full rounded-lg border border-slate-700/50 bg-slate-800/50 px-4 py-2.5 text-sm text-slate-200 outline-none focus:border-cyan-500/50"
            >
              <option value="">Select a source...</option>
              {selectedBot
                ? selectedBot.sources.map(s => (
                    <option key={s.id} value={s.id}>{s.name}</option>
                  ))
                : sources.map(s => (
                    <option key={s.id} value={s.id}>{s.name} ({s.type})</option>
                  ))
              }
            </select>
          </div>

          {error && (
            <div className="rounded-lg border border-red-500/30 bg-red-500/10 px-4 py-2.5">
              <p className="text-sm text-red-400">{error}</p>
            </div>
          )}
        </div>

        <div className="flex justify-end gap-3 mt-6">
          <button
            onClick={onClose}
            className="rounded-lg border border-slate-700/50 px-4 py-2 text-sm font-medium text-slate-400 hover:text-slate-200 transition-colors"
          >
            Cancel
          </button>
          <button
            onClick={handleCreate}
            disabled={!selectedNumber || !selectedSourceId || creating}
            className={cn(
              'flex items-center gap-2 rounded-lg px-5 py-2 text-sm font-semibold transition-all',
              'bg-cyan-500 text-white hover:bg-cyan-400 shadow-[0_0_15px_rgba(34,211,238,0.2)]',
              'disabled:opacity-40 disabled:cursor-not-allowed'
            )}
          >
            {creating ? <Loader2 className="h-4 w-4 animate-spin" /> : <Plus className="h-4 w-4" />}
            Create Route
          </button>
        </div>
      </div>
    </div>
  );
}

/* ─── Main Routing View ─── */

export default function RoutingView({
  initialRoutes,
  initialNumbers,
  initialBots,
  initialSources,
  showNewRouteDialog,
  onCloseNewRouteDialog,
}: {
  initialRoutes: Route[];
  initialNumbers: TwilioNumber[];
  initialBots: CloseBotBot[];
  initialSources: CloseBotSource[];
  showNewRouteDialog?: boolean;
  onCloseNewRouteDialog?: () => void;
}) {
  const [routes, setRoutes] = useState<Route[]>(initialRoutes);
  const [numbers] = useState<TwilioNumber[]>(initialNumbers);
  const [bots] = useState<CloseBotBot[]>(initialBots);
  const [sources] = useState<CloseBotSource[]>(initialSources);

  const [selectedRouteId, setSelectedRouteId] = useState<string | null>(null);
  const [configuringRoute, setConfiguringRoute] = useState<Route | null>(null);
  const [showNewRouteLocal, setShowNewRouteLocal] = useState(false);
  const showNewRoute = showNewRouteDialog ?? showNewRouteLocal;
  const setShowNewRoute = onCloseNewRouteDialog
    ? (v: boolean) => { if (!v) onCloseNewRouteDialog(); else setShowNewRouteLocal(true); }
    : setShowNewRouteLocal;

  const leftRef = useRef<HTMLDivElement>(null!);
  const rightRef = useRef<HTMLDivElement>(null!);
  const centerRef = useRef<HTMLDivElement>(null!);

  // Build number→index map for connection lines
  const numberIndexMap = new Map<string, number>();
  numbers.forEach((n, i) => numberIndexMap.set(n.phoneNumber, i));

  // Build connections from routes
  const connections: ConnectionDef[] = routes.map((route, rightIdx) => ({
    routeId: route.id,
    leftIndex: numberIndexMap.get(route.twilio_number) ?? 0,
    rightIndex: rightIdx,
    active: route.active === 1,
  }));

  const connectedNumbers = new Set(routes.map(r => r.twilio_number));

  // Get message count per route (stubbed — could fetch from API)
  const messageCountMap = new Map<string, number>();

  async function handleToggleActive(routeId: string, active: boolean) {
    try {
      const res = await fetch(`/api/routes/${routeId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ active: active ? 1 : 0 }),
      });
      if (res.ok) {
        const updated = await res.json();
        setRoutes(prev => prev.map(r => r.id === routeId ? updated : r));
      }
    } catch (err) {
      console.error('Failed to toggle route:', err);
    }
  }

  function handlePhoneClick(phoneNumber: string) {
    const route = routes.find(r => r.twilio_number === phoneNumber);
    if (route) {
      setSelectedRouteId(prev => prev === route.id ? null : route.id);
    } else {
      setSelectedRouteId(null);
    }
  }

  function handleConfigure(routeId: string) {
    const route = routes.find(r => r.id === routeId);
    if (route) setConfiguringRoute(route);
  }

  function handleRouteSaved(updated: Route) {
    setRoutes(prev => prev.map(r => r.id === updated.id ? updated : r));
    setConfiguringRoute(null);
  }

  function handleRouteCreated(newRoute: Route) {
    setRoutes(prev => [newRoute, ...prev]);
    setShowNewRoute(false);
  }

  return (
    <div className="flex-1 flex flex-col min-h-0">
      {/* Three-column layout */}
      <div className="flex-1 flex gap-0 min-h-0 relative">
        {/* ─── Left: Twilio Phone Numbers ─── */}
        <div className="w-[270px] flex-shrink-0 border-r border-slate-700/30 flex flex-col">
          <div className="px-4 py-3 border-b border-slate-700/30">
            <div className="flex items-center gap-2">
              <Phone className="h-4 w-4 text-cyan-400" />
              <h2 className="text-[11px] font-bold uppercase tracking-widest text-slate-400">
                Twilio Phone Numbers
              </h2>
            </div>
            <p className="text-[10px] text-slate-600 mt-0.5">
              {numbers.length} number{numbers.length !== 1 ? 's' : ''} · {connectedNumbers.size} routed
            </p>
          </div>

          <div ref={leftRef} className="flex-1 overflow-y-auto px-3 py-3 space-y-2">
            {numbers.length === 0 ? (
              <div className="flex flex-col items-center justify-center py-12 text-slate-600">
                <Phone className="h-8 w-8 mb-2 opacity-40" />
                <p className="text-xs font-medium">No numbers found</p>
                <p className="text-[10px] text-slate-700 mt-1">Configure Twilio in Settings</p>
              </div>
            ) : (
              numbers.map((num) => (
                <div key={num.sid} data-phone-card>
                  <PhoneNumberCard
                    phoneNumber={num.phoneNumber}
                    sid={num.sid}
                    friendlyName={num.friendlyName}
                    isConnected={connectedNumbers.has(num.phoneNumber)}
                    isSelected={
                      selectedRouteId !== null &&
                      routes.find(r => r.id === selectedRouteId)?.twilio_number === num.phoneNumber
                    }
                    onClick={() => handlePhoneClick(num.phoneNumber)}
                  />
                </div>
              ))
            )}
          </div>
        </div>

        {/* ─── Center: Connection Lines ─── */}
        <div ref={centerRef} className="flex-shrink-0 w-[180px] relative flex flex-col">
          <div className="px-4 py-3 border-b border-slate-700/30 text-center">
            <h2 className="text-[11px] font-bold uppercase tracking-widest text-slate-400">
              Routing
            </h2>
          </div>
          <div className="flex-1 relative">
            <ConnectionLines
              connections={connections}
              leftContainerRef={leftRef}
              rightContainerRef={rightRef}
              centerRef={centerRef}
              highlightedRouteId={selectedRouteId}
            />
          </div>
        </div>

        {/* ─── Right: CloseBot Bots & Sources ─── */}
        <div className="flex-1 min-w-[300px] border-l border-slate-700/30 flex flex-col">
          <div className="px-4 py-3 border-b border-slate-700/30">
            <div className="flex items-center gap-2">
              <Bot className="h-4 w-4 text-cyan-400" />
              <h2 className="text-[11px] font-bold uppercase tracking-widest text-slate-400">
                CloseBot Bots & Sources
              </h2>
            </div>
            <p className="text-[10px] text-slate-600 mt-0.5">
              {routes.length} route{routes.length !== 1 ? 's' : ''} configured
            </p>
          </div>

          <div ref={rightRef} className="flex-1 overflow-y-auto px-3 py-3 space-y-3">
            {routes.length === 0 ? (
              <div className="flex flex-col items-center justify-center py-12 text-slate-600">
                <Bot className="h-8 w-8 mb-2 opacity-40" />
                <p className="text-xs font-medium">No routes configured</p>
                <p className="text-[10px] text-slate-700 mt-1">Click &quot;+ Add New Route&quot; to get started</p>
              </div>
            ) : (
              routes.map((route) => {
                const source = sources.find(s => s.id === route.closebot_source_id);
                return (
                  <div key={route.id} data-bot-card>
                    <BotRouteCard
                      id={route.id}
                      botName={route.bot_name || 'Unnamed Bot'}
                      sourceType={source?.type || source?.name || 'SMS'}
                      active={route.active === 1}
                      messageCount={messageCountMap.get(route.id) || 0}
                      isSelected={selectedRouteId === route.id}
                      onToggleActive={handleToggleActive}
                      onConfigure={handleConfigure}
                    />
                  </div>
                );
              })
            )}
          </div>
        </div>
      </div>

      {/* Modals */}
      {configuringRoute && (
        <RouteConfigModal
          route={configuringRoute}
          onClose={() => setConfiguringRoute(null)}
          onSaved={handleRouteSaved}
        />
      )}

      {showNewRoute && (
        <NewRouteDialog
          numbers={numbers}
          bots={bots}
          sources={sources}
          existingRoutes={routes}
          onClose={() => setShowNewRoute(false)}
          onCreated={handleRouteCreated}
        />
      )}
    </div>
  );
}

// Export so page.tsx can trigger the dialog
export { type Route, type TwilioNumber, type CloseBotBot, type CloseBotSource };
