import { useCallback, useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { api } from '../../api/client';
import type { Agent, AgentCapabilities } from '../../types';
import { canRunAggressiveAction, aggressiveActionHint } from '../../help/aggressiveActions';
import './ProtocolTunnelPanel.css';

export interface TunnelStatusView {
  cloudflared_running?: boolean;
  cloudflared_url?: string;
  cloudflared_pid?: number;
  wireguard_active?: boolean;
  wireguard_detail?: string;
  ssh_forwards?: Array<{
    local_port: number;
    remote_host: string;
    remote_port: number;
    ssh_user?: string;
    jump_host?: string;
    pid: number;
    running?: boolean;
  }>;
}

function parseTunnelStatus(message: string): TunnelStatusView | null {
  const start = message.indexOf('{');
  if (start < 0) return null;
  try {
    return JSON.parse(message.slice(start)) as TunnelStatusView;
  } catch {
    return null;
  }
}

interface Props {
  agentId: string;
  agentName: string;
  online: boolean;
  caps?: AgentCapabilities | null;
  platform?: string;
  compact?: boolean;
  /** WS command_result messages — panel listens for tunnel_status */
  lastTunnelStatusMessage?: string;
  onDispatch: (action: string, args?: Record<string, unknown>) => void | Promise<void>;
  busy?: string | null;
}

export default function ProtocolTunnelPanel({
  agentId,
  agentName,
  online,
  caps,
  platform,
  compact = false,
  lastTunnelStatusMessage,
  onDispatch,
  busy,
}: Props) {
  const [expanded, setExpanded] = useState(!compact);
  const [cfURL, setCfURL] = useState('');
  const [localPort, setLocalPort] = useState('2222');
  const [targetHostPort, setTargetHostPort] = useState('192.168.1.10:22');
  const [sshUser, setSshUser] = useState('');
  const [status, setStatus] = useState<TunnelStatusView | null>(null);
  const [statusRaw, setStatusRaw] = useState('');

  useEffect(() => {
    api.getConfig().then((cfg) => {
      const fromTunnel = cfg.tunnel_defaults?.cloudflared_target_url?.trim();
      const fromPublic = cfg.server?.public_url?.trim();
      setCfURL(fromTunnel || fromPublic || '');
    }).catch(() => {});
  }, []);

  useEffect(() => {
    if (lastTunnelStatusMessage) {
      const parsed = parseTunnelStatus(lastTunnelStatusMessage);
      if (parsed) setStatus(parsed);
      setStatusRaw(lastTunnelStatusMessage);
    }
  }, [lastTunnelStatusMessage]);

  const tunnelAllowed = canRunAggressiveAction('start_tunnel', caps, platform);
  const tunnelHint = aggressiveActionHint('start_tunnel', caps, platform);

  const refreshStatus = useCallback(() => {
    if (!online || !agentId) return;
    void onDispatch('tunnel_status');
  }, [online, agentId, onDispatch]);

  useEffect(() => {
    if (expanded && online) refreshStatus();
  }, [expanded, online, refreshStatus]);

  const disabled = !online || !!busy;

  return (
    <div className={`protocol-tunnel-panel ${compact ? 'compact' : ''}`}>
      <button
        type="button"
        className="protocol-tunnel-toggle"
        onClick={() => setExpanded((e) => !e)}
        aria-expanded={expanded}
      >
        <span className="font-tech">◈ Protocol Tunneling</span>
        <span className="protocol-tunnel-chevron">{expanded ? '▾' : '▸'}</span>
      </button>

      {expanded && (
        <div className="protocol-tunnel-body">
          <p className="protocol-tunnel-help">
            Encapsulates traffic for ops on <strong>your</strong> fleet — reach internal hosts and expose
            agent LAN services. Not for third-party evasion or hiding infrastructure.
          </p>

          <div className="protocol-tunnel-cards">
            <section className="protocol-tunnel-card">
              <h4 className="font-tech">Cloudflare Tunnel</h4>
              <p className="protocol-tunnel-card-hint">Agent dials out to your control URL (no inbound port).</p>
              <label className="protocol-tunnel-label">
                Target URL
                <input
                  type="text"
                  className="input protocol-tunnel-input"
                  value={cfURL}
                  onChange={(e) => setCfURL(e.target.value)}
                  placeholder="https://your-server.example.com"
                  disabled={disabled}
                />
              </label>
              <div className="protocol-tunnel-actions">
                <button
                  type="button"
                  className="btn-magenta btn-sm"
                  disabled={disabled || !tunnelAllowed}
                  title={tunnelHint}
                  onClick={() => onDispatch('tunnel_cloudflared', { command: cfURL.trim() })}
                >
                  Start Cloudflared
                </button>
              </div>
            </section>

            <section className="protocol-tunnel-card">
              <h4 className="font-tech">WireGuard (Path Tracer)</h4>
              <p className="protocol-tunnel-card-hint">
                Multi-hop mesh VPN for owned nodes — configure sessions on the dashboard.
              </p>
              <Link to="/pathtracer" className="btn btn-outline btn-sm protocol-tunnel-link">
                Open Path Tracer →
              </Link>
            </section>

            <section className="protocol-tunnel-card">
              <h4 className="font-tech">SSH Local Forward</h4>
              <p className="protocol-tunnel-card-hint">
                Windows agent opens <code>127.0.0.1:local → LAN target</code> via OpenSSH/plink (admin reach-through).
              </p>
              <div className="protocol-tunnel-row">
                <label className="protocol-tunnel-label">
                  Local port
                  <input
                    type="text"
                    className="input protocol-tunnel-input short"
                    value={localPort}
                    onChange={(e) => setLocalPort(e.target.value)}
                    disabled={disabled}
                  />
                </label>
                <label className="protocol-tunnel-label">
                  Target host:port
                  <input
                    type="text"
                    className="input protocol-tunnel-input"
                    value={targetHostPort}
                    onChange={(e) => setTargetHostPort(e.target.value)}
                    placeholder="192.168.1.50:3389"
                    disabled={disabled}
                  />
                </label>
              </div>
              <label className="protocol-tunnel-label">
                SSH user (optional)
                <input
                  type="text"
                  className="input protocol-tunnel-input"
                  value={sshUser}
                  onChange={(e) => setSshUser(e.target.value)}
                  placeholder="Administrator"
                  disabled={disabled}
                />
              </label>
              <div className="protocol-tunnel-actions">
                <button
                  type="button"
                  className="btn-magenta btn-sm"
                  disabled={disabled || !tunnelAllowed || platform === 'darwin' || platform === 'linux'}
                  title={
                    platform !== 'windows' && platform !== undefined
                      ? 'SSH forward is Windows-only'
                      : tunnelHint
                  }
                  onClick={() =>
                    onDispatch('tunnel_ssh_forward', {
                      data: JSON.stringify({
                        local_port: parseInt(localPort, 10) || 2222,
                        remote_host: targetHostPort.split(':')[0] || '',
                        remote_port: parseInt(targetHostPort.split(':').pop() ?? '22', 10) || 22,
                        ssh_user: sshUser.trim() || undefined,
                      }),
                    })
                  }
                >
                  Start SSH Forward
                </button>
              </div>
            </section>
          </div>

          <div className="protocol-tunnel-status-bar">
            <button
              type="button"
              className="btn btn-outline btn-sm"
              disabled={disabled}
              onClick={refreshStatus}
            >
              {busy === 'tunnel_status' ? '…' : 'Refresh Status'}
            </button>
            <button
              type="button"
              className="btn-red btn-sm"
              disabled={disabled || !tunnelAllowed}
              title={tunnelHint}
              onClick={() => onDispatch('tunnel_stop', { command: 'all' })}
            >
              Stop All Tunnels
            </button>
          </div>

          {(status || statusRaw) && (
            <div className="protocol-tunnel-status">
              <h4 className="font-tech">tunnel_status — {agentName}</h4>
              {status ? (
                <ul className="protocol-tunnel-status-list">
                  <li>
                    Cloudflared:{' '}
                    {status.cloudflared_running
                      ? `running (pid ${status.cloudflared_pid}) → ${status.cloudflared_url ?? ''}`
                      : 'stopped'}
                  </li>
                  <li>
                    WireGuard:{' '}
                    {status.wireguard_active ? 'active' : 'inactive'}
                  </li>
                  <li>
                    SSH forwards:{' '}
                    {status.ssh_forwards?.length
                      ? status.ssh_forwards
                          .map(
                            (f) =>
                              `127.0.0.1:${f.local_port} → ${f.remote_host}:${f.remote_port} (pid ${f.pid})`
                          )
                          .join('; ')
                      : 'none'}
                  </li>
                </ul>
              ) : (
                <pre className="protocol-tunnel-raw">{statusRaw.slice(0, 2000)}</pre>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

export { parseTunnelStatus };
