using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class P2PCoordinator
{
    private const int ServerPort = 11000;
    private TcpListener _tcpListener;
    
    private readonly Dictionary<string, IPEndPoint> _tcpEndpoints = new();
    private readonly Dictionary<string, TcpClient> _tcpConnections = new();
    
    private readonly object _lock = new object();
    private bool _isRunning = true;
    public P2PCoordinator()
    {
        try
        {
            _tcpListener = new TcpListener(IPAddress.Any, ServerPort);
            Console.WriteLine($"P2P协调服务器启动,监听端口: {ServerPort}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"服务器初始化失败: {ex.Message}");
            Environment.Exit(1);
        }
    }
    public void Start()
    {
        new Thread(ListenTcp).Start();
        
        Console.WriteLine("服务器运行中. 按任意键停止...");
        Console.ReadKey();
        Stop();
    }
    private void ListenTcp()
    {
        try
        {
            _tcpListener.Start();
            Console.WriteLine("TCP监听已启动");
            
            while (_isRunning)
            {
                TcpClient client = _tcpListener.AcceptTcpClient();
                new Thread(() => HandleTcpClient(client)).Start();
            }
        }
        catch (Exception ex)
        {
            if (_isRunning) Console.WriteLine($"TCP监听错误: {ex.Message}");
        }
    }
    private void HandleTcpClient(TcpClient client)
    {
        string clientId = null;
        try
        {
            NetworkStream stream = client.GetStream();
            byte[] buffer = new byte[1024];
            int bytesRead = stream.Read(buffer, 0, buffer.Length);
            if (bytesRead == 0) return;
            string message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            string[] parts = message.Split(':');
            if (parts.Length < 2) return;
            string command = parts[0];
            clientId = parts[1];
            var clientEP = (IPEndPoint)client.Client.RemoteEndPoint;
            Console.WriteLine($"[TCP] {clientId} 连接: {clientEP}");
            lock (_lock)
            {
                if (command == "REGISTER")
                {
                    _tcpEndpoints[clientId] = clientEP;
                    _tcpConnections[clientId] = client;
                    Console.WriteLine($"[注册] {clientId} -> {clientEP}");
                    
                    SendTcpResponse(client, "REGISTERED");
                }
                else if (command == "CONNECT" && parts.Length > 2)
                {
                    string targetId = parts[2];
                    Console.WriteLine($"[连接请求] {clientId} -> {targetId}");
                    HandleConnectionRequest(clientId, targetId);
                }
            }
            // 处理后续消息
            while (_isRunning)
            {
                bytesRead = stream.Read(buffer, 0, buffer.Length);
                if (bytesRead == 0) break;
                message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                parts = message.Split(':');
                command = parts[0];
                if (command == "HEARTBEAT")
                {
                    // 心跳检测
                    SendTcpResponse(client, "HEARTBEAT_ACK");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"处理TCP客户端错误: {ex.Message}");
        }
        finally
        {
            if (clientId != null)
            {
                lock (_lock)
                {
                    _tcpConnections.Remove(clientId);
                    _tcpEndpoints.Remove(clientId);
                }
            }
            client.Close();
        }
    }
    private void HandleConnectionRequest(string fromClient, string toClient)
    {
        lock (_lock)
        {
            if (!_tcpConnections.ContainsKey(fromClient))
            {
                Console.WriteLine($"[错误] 源客户端未连接: {fromClient}");
                return;
            }
            
            if (!_tcpConnections.ContainsKey(toClient))
            {
                SendTcpResponse(_tcpConnections[fromClient], "ERROR:目标客户端未连接");
                Console.WriteLine($"[错误] 目标客户端未连接: {toClient}");
                return;
            }
            
            if (!_tcpEndpoints.TryGetValue(fromClient, out IPEndPoint fromEp) ||
                !_tcpEndpoints.TryGetValue(toClient, out IPEndPoint toEp))
            {
                SendTcpResponse(_tcpConnections[fromClient], "ERROR:端点信息不完整");
                Console.WriteLine($"[错误] 端点信息不完整: {fromClient} -> {toClient}");
                return;
            }
            // 交换端点信息
            string fromMessage = $"PEER_INFO:{toClient}:{toEp.Address}:{toEp.Port}";
            string toMessage = $"PEER_INFO:{fromClient}:{fromEp.Address}:{fromEp.Port}";
            
            SendTcpResponse(_tcpConnections[fromClient], fromMessage);
            SendTcpResponse(_tcpConnections[toClient], toMessage);
            
            Console.WriteLine($"[端点交换] {fromClient} <-> {toClient}");
            Console.WriteLine($"  {fromEp} <-> {toEp}");
        }
    }
    private void SendTcpResponse(TcpClient client, string message)
    {
        try
        {
            if (client.Connected)
            {
                NetworkStream stream = client.GetStream();
                byte[] data = Encoding.ASCII.GetBytes(message);
                stream.Write(data, 0, data.Length);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发送TCP响应错误: {ex.Message}");
        }
    }
    private void Stop()
    {
        Console.WriteLine("停止服务器...");
        _isRunning = false;
        
        try
        {
            lock (_lock)
            {
                foreach (var client in _tcpConnections.Values)
                {
                    try { client.Close(); } catch { }
                }
                _tcpConnections.Clear();
                _tcpEndpoints.Clear();
            }
            
            _tcpListener.Stop();
            Console.WriteLine("服务器已停止");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"停止服务器错误: {ex.Message}");
        }
    }
    static void Main(string[] args)
    {
        Console.Title = "P2P协调服务器";
        Console.WriteLine("=== P2P协调服务器 ===");
        Console.WriteLine("用于远程桌面直连");
        Console.WriteLine("端口: " + ServerPort);
        Console.WriteLine(new string('=', 50));
        
        var server = new P2PCoordinator();
        server.Start();
    }
}