import os
import socket
import random
from flask import Flask, request, send_from_directory, render_template_string, jsonify, abort
import threading
import webbrowser
from datetime import datetime
import json
import ipaddress
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed

# 创建Flask应用
app = Flask(__name__)
UPLOAD_FOLDER = 'shared_files'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 * 1024  # 限制上传大小为16GB

# 确保共享目录存在
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

# 确保pp目录存在（用于存放图片）
if not os.path.exists('pp'):
    os.makedirs('pp')

# 存储设备信息和扫描状态
devices = {}
scanning = False
max_threads = 50
total_ips = 0
scanned_ips = 0

def get_local_ip():
    """获取本机在局域网中的IP地址"""
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "127.0.0.1"

def get_netmask():
    """获取子网掩码"""
    try:
        # 使用ipconfig命令获取子网掩码
        if os.name == 'nt':  # Windows
            result = subprocess.run(["ipconfig"], capture_output=True, text=True, encoding='gbk')
        else:  # Linux/Mac
            result = subprocess.run(["ifconfig"], capture_output=True, text=True)
            
        lines = result.stdout.split('\n')
        local_ip = get_local_ip()
        
        for i, line in enumerate(lines):
            if local_ip in line:
                # 尝试从附近行找到子网掩码
                for j in range(max(0, i-2), min(len(lines), i+2)):
                    if "子网掩码" in lines[j] or "netmask" in lines[j].lower():
                        parts = lines[j].split(":")
                        if len(parts) > 1:
                            return parts[1].strip().split()[0]
    except Exception:
        pass
    return "255.255.255.0"  # 默认子网掩码

def calculate_network_range():
    """计算局域网IP范围"""
    global total_ips
    local_ip = get_local_ip()
    netmask = get_netmask()
    
    try:
        network = ipaddress.IPv4Network(f"{local_ip}/{netmask}", strict=False)
        hosts = [str(host) for host in network.hosts()]
        total_ips = len(hosts)
        return hosts
    except:
        # 如果计算失败，使用常见的局域网IP范围
        base_ip = ".".join(local_ip.split(".")[:3])
        hosts = [f"{base_ip}.{i}" for i in range(1, 255)]
        total_ips = len(hosts)
        return hosts

def ping_host(ip):
    """ping主机检查是否在线"""
    try:
        # 使用系统ping命令
        if os.name == 'nt':  # Windows
            command = ['ping', '-n', '1', '-w', '1000', ip]
        else:  # Linux/Mac
            command = ['ping', '-c', '1', '-W', '1', ip]
        
        # 使用subprocess运行ping命令
        result = subprocess.run(command, capture_output=True, text=True)
        return result.returncode == 0
    except Exception:
        return False

def get_hostname(ip):
    """尝试获取主机名"""
    try:
        socket.setdefaulttimeout(1)
        hostname = socket.gethostbyaddr(ip)
        return hostname[0]
    except (socket.herror, socket.gaierror, socket.timeout):
        return "未知设备"

def get_mac_address(ip):
    """获取MAC地址"""
    try:
        # 使用arp命令获取MAC地址
        if os.name == 'nt':  # Windows
            result = subprocess.run(["arp", "-a", ip], capture_output=True, text=True, encoding='gbk')
            lines = result.stdout.split('\n')
            
            for line in lines:
                if ip in line:
                    parts = line.split()
                    if len(parts) >= 2:
                        return parts[1]
        else:  # Linux/Mac
            result = subprocess.run(["arp", "-n", ip], capture_output=True, text=True)
            lines = result.stdout.split('\n')
            
            for line in lines:
                if ip in line:
                    parts = line.split()
                    if len(parts) >= 3:
                        return parts[2]
    except Exception:
        pass
    return "未知MAC"

def scan_single_ip(ip):
    """扫描单个IP地址并返回设备信息（如果在线）"""
    global scanned_ips
    if not scanning:  # 检查是否已停止扫描
        return None
        
    try:
        # 检查IP是否在线
        if ping_host(ip):
            # 获取设备信息
            hostname = get_hostname(ip)
            mac = get_mac_address(ip)
            
            return {
                "ip": ip,
                "mac": mac,
                "hostname": hostname,
                "first_seen": datetime.now().isoformat(),
                "last_seen": datetime.now().isoformat()
            }
    except Exception as e:
        print(f"扫描 {ip} 时出错: {str(e)}")
    finally:
        # 更新已扫描计数
        if scanning:
            scanned_ips += 1
    
    return None

def scan_network():
    """扫描网络中的设备，使用多线程并行处理"""
    global scanning, scanned_ips
    scanning = True
    scanned_ips = 0
    
    network_range = calculate_network_range()
    active_devices = []
    
    print(f"开始扫描网络，共 {total_ips} 个IP地址")
    
    # 使用线程池管理并发扫描
    with ThreadPoolExecutor(max_workers=max_threads) as executor:
        # 提交所有IP扫描任务
        futures = {executor.submit(scan_single_ip, ip): ip for ip in network_range}
        
        # 处理完成的任务
        for future in as_completed(futures):
            if not scanning:  # 如果已停止扫描，取消所有剩余任务
                executor.shutdown(wait=False, cancel_futures=True)
                break
                
            ip = futures[future]
            
            try:
                device = future.result()
                if device:
                    active_devices.append(device)
                    mac = device["mac"]
                    if mac in devices:
                        devices[mac]["last_seen"] = datetime.now().isoformat()
                    else:
                        devices[mac] = device
                    print(f"发现设备: {device['ip']} ({device['hostname']}) - {device['mac']}")
            except Exception as e:
                print(f"处理 {ip} 结果时出错: {str(e)}")
    
    scanning = False
    print(f"扫描完成，发现 {len(active_devices)} 台设备")
    return active_devices

# 添加pp目录的路由，允许访问pp文件夹中的图片
@app.route('/pp/<path:filename>')
def serve_pp_files(filename):
    return send_from_directory('pp', filename)

# HTML模板 - 半透明风格，自适应背景
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件共享与设备扫描</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#60A5FA', // 更浅的蓝色
                        secondary: '#6EE7B7', // 更浅的绿色
                        accent: '#A78BFA', // 更浅的紫色
                        neutral: '#1F2937',
                        danger: '#FCA5A5', // 更浅的红色
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .card-shadow {
                box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
            }
            .hover-lift {
                transition: transform 0.3s ease, box-shadow 0.3s ease, background-color 0.3s ease;
            }
            .hover-lift:hover {
                transform: translateY(-2px);
                box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
            }
            .progress-animate {
                transition: width 0.3s ease-in-out;
            }
            .pulse {
                animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
            }
            @keyframes pulse {
                0%, 100% {
                    opacity: 1;
                }
                50% {
                    opacity: 0.7;
                }
            }
        }
    </style>
</head>
<body class="font-inter text-neutral min-h-screen m-0 p-0">
    <!-- 背景图片容器 -->
    <div class="fixed inset-0 z-0">
        <img src="/pp/1.jpg" alt="背景图片" 
             class="w-full h-full object-cover object-center">
    </div>

    <main class="container mx-auto px-4 py-8 relative z-10">
        <!-- 文件共享部分 - 半透明卡片 -->
        <section class="mb-10 bg-white/30 backdrop-blur-sm rounded-xl shadow-md overflow-hidden border border-white/20">
            <div class="bg-primary/20 px-6 py-4 border-b border-primary/30">
                <h2 class="text-2xl font-bold text-neutral flex items-center">
                    <i class="fa fa-files-o text-primary mr-3"></i>文件共享
                </h2>
            </div>
            
            <div class="p-6">
                <!-- 上传区域 - 半透明 -->
                <div id="uploadArea" class="border-2 border-dashed border-gray-300/50 bg-white/20 rounded-lg p-8 text-center hover:border-primary transition-colors duration-300 mb-8">
                    <i class="fa fa-cloud-upload text-5xl text-gray-400 mb-4"></i>
                    <h3 class="text-xl font-semibold text-neutral mb-2">拖放文件到此处上传</h3>
                    <p class="text-gray-500 mb-6">或点击下方按钮选择文件</p>
                    
                    <label class="inline-block bg-primary/60 hover:bg-primary/80 text-white font-medium py-3 px-6 rounded-lg cursor-pointer transition-all duration-300 hover-lift">
                        <i class="fa fa-file-o mr-2"></i>选择文件
                        <input type="file" id="fileInput" multiple class="hidden" onchange="handleFiles(event)">
                    </label>
                    
                    <!-- 上传进度条区域 -->
                    <div id="uploadProgressContainer" class="mt-8 hidden">
                        <div class="mb-2 flex justify-between items-center">
                            <span id="currentFileName" class="font-medium"></span>
                            <span id="uploadPercent" class="text-sm text-gray-500">0%</span>
                        </div>
                        <div class="w-full bg-gray-200/50 rounded-full h-2.5">
                            <div id="uploadProgressBar" class="bg-secondary/70 h-2.5 rounded-full progress-animate" style="width: 0%"></div>
                        </div>
                        <div class="mt-2 text-sm text-gray-500 flex justify-between">
                            <span id="uploadedSize">0 B / 0 B</span>
                            <span id="uploadStatus">准备上传...</span>
                        </div>
                    </div>
                </div>
                
                <!-- 文件列表 -->
                <div>
                    <div class="flex justify-between items-center mb-4">
                        <h3 class="text-xl font-semibold text-neutral">已共享的文件</h3>
                        <span id="fileCount" class="bg-gray-100/60 text-gray-700 px-3 py-1 rounded-full text-sm">
                            {{ files|length }} 个文件
                        </span>
                    </div>
                    
                    <div id="fileList" class="space-y-3 max-h-[400px] overflow-y-auto pr-2">
                        {% if files %}
                            {% for file in files %}
                            <div class="file-item bg-white/40 rounded-lg p-4 flex justify-between items-center hover-lift" id="file-{{ file.name }}">
                                <div class="flex items-center">
                                    <i class="fa fa-file text-primary mr-3 text-xl"></i>
                                    <div>
                                        <p class="font-medium text-neutral">{{ file.name }}</p>
                                        <p class="text-sm text-gray-500">{{ file.size }}</p>
                                    </div>
                                </div>
                                <div class="flex items-center space-x-2">
                                    <a href="/download/{{ file.name }}" class="bg-secondary/60 hover:bg-secondary/80 text-white p-2 rounded transition-all duration-300">
                                        <i class="fa fa-download mr-1"></i> 下载
                                    </a>
                                    <button class="delete-btn bg-danger/60 hover:bg-danger/80 text-white p-2 rounded transition-all duration-300"
                                            onclick="deleteFile('{{ file.name }}')">
                                        <i class="fa fa-trash mr-1"></i> 删除
                                    </button>
                                </div>
                            </div>
                            {% endfor %}
                        {% else %}
                            <div class="bg-white/40 rounded-lg p-8 text-center">
                                <i class="fa fa-folder-open text-4xl text-gray-300 mb-4"></i>
                                <p class="text-gray-500">暂无共享文件</p>
                                <p class="text-sm text-gray-400 mt-2">上传文件以开始共享</p>
                            </div>
                        {% endif %}
                    </div>
                </div>
            </div>
        </section>
        
        <!-- 设备扫描部分 - 半透明卡片 -->
        <section class="bg-white/30 backdrop-blur-sm rounded-xl shadow-md overflow-hidden border border-white/20">
            <div class="bg-accent/20 px-6 py-4 border-b border-accent/30">
                <h2 class="text-2xl font-bold text-neutral flex items-center">
                    <i class="fa fa-desktop text-accent mr-3"></i>设备扫描
                </h2>
            </div>
            
            <div class="p-6">
                <!-- 扫描控制 - 按钮颜色变浅且半透明 -->
                <div class="flex flex-wrap gap-4 mb-6">
                    <button id="startScanBtn" class="bg-secondary/60 hover:bg-secondary/80 text-white font-medium py-3 px-6 rounded-lg cursor-pointer transition-all duration-300 hover-lift flex items-center">
                        <i class="fa fa-play mr-2"></i>开始扫描
                    </button>
                    <button id="stopScanBtn" class="bg-danger/60 hover:bg-danger/80 text-white font-medium py-3 px-6 rounded-lg cursor-pointer transition-all duration-300 hover-lift flex items-center hidden">
                        <i class="fa fa-stop mr-2"></i>停止扫描
                    </button>
                    <button id="refreshDevicesBtn" class="bg-primary/60 hover:bg-primary/80 text-white font-medium py-3 px-6 rounded-lg cursor-pointer transition-all duration-300 hover-lift flex items-center">
                        <i class="fa fa-refresh mr-2"></i>刷新设备列表
                    </button>
                </div>
                
                <!-- 扫描进度 -->
                <div id="scanProgressContainer" class="mb-6 hidden">
                    <div class="mb-2 flex justify-between items-center">
                        <span class="font-medium">扫描进度</span>
                        <span id="scanPercent" class="text-sm text-gray-500">0%</span>
                    </div>
                    <div class="w-full bg-gray-200/50 rounded-full h-2.5">
                        <div id="scanProgressBar" class="bg-accent/70 h-2.5 rounded-full progress-animate" style="width: 0%"></div>
                    </div>
                    <div class="mt-2 text-sm text-gray-500 flex justify-between">
                        <span id="scanStatus">准备扫描...</span>
                        <span id="scanCount">0/0 个IP</span>
                    </div>
                </div>
                
                <!-- 设备列表 -->
                <div>
                    <div class="flex justify-between items-center mb-4">
                        <h3 class="text-xl font-semibold text-neutral">发现的设备</h3>
                        <span id="deviceCount" class="bg-gray-100/60 text-gray-700 px-3 py-1 rounded-full text-sm">
                            {{ devices|length }} 台设备
                        </span>
                    </div>
                    
                    <div id="deviceList" class="space-y-3 max-h-[400px] overflow-y-auto pr-2">
                        {% if devices %}
                            {% for device in devices %}
                            <div class="device-item bg-white/40 rounded-lg p-4 hover-lift" id="device-{{ device.ip }}">
                                <div class="flex flex-col md:flex-row md:justify-between">
                                    <div>
                                        <p class="font-medium text-neutral flex items-center">
                                            {{ device.hostname }}
                                            {% if device.ip == ip_address %}
                                                <span class="ml-2 bg-primary/30 text-primary text-xs px-2 py-0.5 rounded-full">本机</span>
                                            {% endif %}
                                        </p>
                                        <p class="text-sm text-gray-500 font-mono mt-1">{{ device.ip }}</p>
                                    </div>
                                    <div class="mt-3 md:mt-0">
                                        <p class="text-sm text-gray-600">MAC: {{ device.mac }}</p>
                                        {% if device.ip != ip_address %}
                                            <a href="http://{{ device.ip }}:{{ port }}" target="_blank" 
                                               class="text-primary hover:text-primary/80 text-sm mt-1 inline-block">
                                                <i class="fa fa-external-link mr-1"></i>访问该设备共享
                                            </a>
                                        {% endif %}
                                    </div>
                                </div>
                            </div>
                            {% endfor %}
                        {% else %}
                            <div class="bg-white/40 rounded-lg p-8 text-center">
                                <i class="fa fa-wifi text-4xl text-gray-300 mb-4"></i>
                                <p class="text-gray-500">暂无设备</p>
                                <p class="text-sm text-gray-400 mt-2">点击"开始扫描"按钮发现局域网中的设备</p>
                            </div>
                        {% endif %}
                    </div>
                </div>
            </div>
        </section>
    </main>

    <script>
        // 文件上传功能
        const uploadArea = document.getElementById('uploadArea');
        const fileInput = document.getElementById('fileInput');
        const uploadProgressContainer = document.getElementById('uploadProgressContainer');
        const currentFileNameEl = document.getElementById('currentFileName');
        const uploadProgressBar = document.getElementById('uploadProgressBar');
        const uploadPercentEl = document.getElementById('uploadPercent');
        const uploadedSizeEl = document.getElementById('uploadedSize');
        const uploadStatusEl = document.getElementById('uploadStatus');
        const fileList = document.getElementById('fileList');
        const fileCount = document.getElementById('fileCount');
        
        // 设备扫描功能
        const startScanBtn = document.getElementById('startScanBtn');
        const stopScanBtn = document.getElementById('stopScanBtn');
        const refreshDevicesBtn = document.getElementById('refreshDevicesBtn');
        const scanProgressContainer = document.getElementById('scanProgressContainer');
        const scanProgressBar = document.getElementById('scanProgressBar');
        const scanPercentEl = document.getElementById('scanPercent');
        const scanStatusEl = document.getElementById('scanStatus');
        const scanCountEl = document.getElementById('scanCount');
        const deviceList = document.getElementById('deviceList');
        const deviceCount = document.getElementById('deviceCount');
        
        // 防止默认拖放行为
        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
            uploadArea.addEventListener(eventName, preventDefaults, false);
            document.body.addEventListener(eventName, preventDefaults, false);
        });
        
        // 高亮拖放区域
        ['dragenter', 'dragover'].forEach(eventName => {
            uploadArea.addEventListener(eventName, highlight, false);
        });
        
        ['dragleave', 'drop'].forEach(eventName => {
            uploadArea.addEventListener(eventName, unhighlight, false);
        });
        
        // 处理文件投放
        uploadArea.addEventListener('drop', handleDrop, false);
        
        // 点击上传区域也可以选择文件
        uploadArea.addEventListener('click', function(e) {
            // 确保点击的不是按钮内部元素
            if (!e.target.closest('label') && e.target !== fileInput) {
                fileInput.click();
            }
        });
        
        function preventDefaults(e) {
            e.preventDefault();
            e.stopPropagation();
        }
        
        function highlight() {
            uploadArea.classList.add('border-primary', 'bg-white/30');
        }
        
        function unhighlight() {
            uploadArea.classList.remove('border-primary', 'bg-white/30');
        }
        
        function handleDrop(e) {
            const dt = e.dataTransfer;
            const files = dt.files;
            handleFiles({target: {files: files}});
        }
        
        function handleFiles(e) {
            const files = e.target.files;
            if (!files || files.length === 0) return;

            // 逐个上传文件
            Array.from(files).forEach((file, index) => {
                // 为多个文件添加延迟，避免同时上传冲突
                setTimeout(() => uploadFile(file), index * 200);
            });
            
            // 重置文件输入，允许重复选择同一文件
            fileInput.value = '';
        }
        
        function uploadFile(file) {
            // 显示上传进度区域
            uploadProgressContainer.classList.remove('hidden');
            
            // 更新文件名和初始状态
            currentFileNameEl.textContent = file.name;
            uploadStatusEl.textContent = '上传中...';
            uploadStatusEl.className = 'text-sm text-gray-500';
            
            const formData = new FormData();
            formData.append('file', file);
            
            const xhr = new XMLHttpRequest();
            
            // 上传进度事件
            xhr.upload.addEventListener('progress', function(e) {
                if (e.lengthComputable) {
                    const percentComplete = (e.loaded / e.total) * 100;
                    const uploadedSize = formatFileSize(e.loaded);
                    const totalSize = formatFileSize(e.total);
                    
                    uploadProgressBar.style.width = percentComplete + '%';
                    uploadPercentEl.textContent = percentComplete.toFixed(1) + '%';
                    uploadedSizeEl.textContent = `${uploadedSize} / ${totalSize}`;
                }
            }, false);
            
            // 上传完成事件
            xhr.addEventListener('load', function(e) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    uploadStatusEl.textContent = '上传成功!';
                    uploadStatusEl.className = 'text-sm text-green-600';
                    
                    // 上传成功后延迟500毫秒刷新页面
                    setTimeout(() => {
                        window.location.reload();
                    }, 500);
                } else {
                    uploadStatusEl.textContent = '上传失败!';
                    uploadStatusEl.className = 'text-sm text-danger';
                }
            }, false);
            
            // 上传错误事件
            xhr.addEventListener('error', function(e) {
                uploadStatusEl.textContent = '上传失败!';
                uploadStatusEl.className = 'text-sm text-danger';
            }, false);
            
            xhr.open('POST', '/upload', true);
            xhr.send(formData);
        }
        
        function deleteFile(filename) {
            if (confirm(`确定要删除文件 "${filename}" 吗？`)) {
                fetch(`/delete/${filename}`, {
                    method: 'DELETE'
                })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        // 从界面移除文件项并添加动画效果
                        const fileElement = document.getElementById(`file-${filename}`);
                        if (fileElement) {
                            fileElement.classList.add('opacity-0', 'transform', 'translate-x-4');
                            fileElement.style.transition = 'all 0.3s ease-out';
                            setTimeout(() => {
                                fileElement.remove();
                                // 更新文件计数
                                const count = parseInt(fileCount.textContent);
                                fileCount.textContent = `${count - 1} 个文件`;
                                
                                // 如果没有文件了，显示空状态
                                if (fileList.children.length === 0) {
                                    fileList.innerHTML = `
                                        <div class="bg-white/40 rounded-lg p-8 text-center">
                                            <i class="fa fa-folder-open text-4xl text-gray-300 mb-4"></i>
                                            <p class="text-gray-500">暂无共享文件</p>
                                            <p class="text-sm text-gray-400 mt-2">上传文件以开始共享</p>
                                        </div>
                                    `;
                                }
                            }, 300);
                        }
                    } else {
                        alert('文件删除失败: ' + data.message);
                    }
                })
                .catch(error => {
                    alert('删除文件时发生错误: ' + error);
                });
            }
        }
        
        function refreshFileList() {
            fetch('/')
                .then(response => response.text())
                .then(html => {
                    // 创建临时元素解析HTML
                    const tempDiv = document.createElement('div');
                    tempDiv.innerHTML = html;
                    const newFileList = tempDiv.getElementById('fileList').innerHTML;
                    const newFileCount = tempDiv.getElementById('fileCount').textContent;
                    
                    // 更新当前页面的文件列表和计数
                    fileList.innerHTML = newFileList;
                    fileCount.textContent = newFileCount;
                });
        }
        
        function formatFileSize(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
        }
        
        // 设备扫描功能
        startScanBtn.addEventListener('click', startScan);
        stopScanBtn.addEventListener('click', stopScan);
        refreshDevicesBtn.addEventListener('click', refreshDeviceList);
        
        function startScan() {
            startScanBtn.classList.add('hidden');
            stopScanBtn.classList.remove('hidden');
            scanProgressContainer.classList.remove('hidden');
            
            fetch('/start_scan', {
                method: 'POST'
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    scanStatusEl.textContent = '正在扫描...';
                    // 开始定期检查扫描进度
                    checkScanProgress();
                } else {
                    alert('启动扫描失败: ' + data.message);
                    resetScanUI();
                }
            })
            .catch(error => {
                alert('启动扫描时发生错误: ' + error);
                resetScanUI();
            });
        }
        
        function stopScan() {
            fetch('/stop_scan', {
                method: 'POST'
            })
            .then(response => response.json())
            .then(data => {
                scanStatusEl.textContent = '扫描已停止';
                resetScanUI();
            })
            .catch(error => {
                alert('停止扫描时发生错误: ' + error);
                resetScanUI();
            });
        }
        
        function resetScanUI() {
            startScanBtn.classList.remove('hidden');
            stopScanBtn.classList.add('hidden');
        }
        
        function checkScanProgress() {
            // 如果停止按钮隐藏了，说明扫描已停止，不再检查进度
            if (stopScanBtn.classList.contains('hidden')) {
                return;
            }
            
            fetch('/scan_progress')
            .then(response => response.json())
            .then(data => {
                if (data.scanning) {
                    const percent = data.total_ips > 0 ? Math.round((data.scanned_ips / data.total_ips) * 100) : 0;
                    scanProgressBar.style.width = percent + '%';
                    scanPercentEl.textContent = percent + '%';
                    scanCountEl.textContent = `${data.scanned_ips}/${data.total_ips} 个IP`;
                    
                    // 如果有新设备，更新设备列表
                    if (data.device_count > parseInt(deviceCount.textContent)) {
                        refreshDeviceList();
                    }
                    
                    // 继续检查进度
                    setTimeout(checkScanProgress, 1000);
                } else {
                    // 扫描完成，延迟50-500毫秒刷新页面
                    const delay = Math.floor(Math.random() * (500 - 50 + 1)) + 50;
                    scanStatusEl.textContent = `扫描完成，发现 ${data.device_count} 台设备，即将刷新...`;
                    scanProgressBar.style.width = '100%';
                    scanPercentEl.textContent = '100%';
                    refreshDeviceList();
                    resetScanUI();
                    
                    setTimeout(() => {
                        window.location.reload();
                    }, delay);
                }
            })
            .catch(error => {
                console.error('检查扫描进度时出错:', error);
                setTimeout(checkScanProgress, 1000);
            });
        }
        
        function refreshDeviceList() {
            fetch('/')
                .then(response => response.text())
                .then(html => {
                    const tempDiv = document.createElement('div');
                    tempDiv.innerHTML = html;
                    const newDeviceList = tempDiv.getElementById('deviceList').innerHTML;
                    const newDeviceCount = tempDiv.getElementById('deviceCount').textContent;
                    
                    deviceList.innerHTML = newDeviceList;
                    deviceCount.textContent = newDeviceCount;
                });
        }
    </script>
</body>
</html>
'''

@app.route('/')
def index():
    """主页面，显示文件列表和设备列表"""
    files = []
    for filename in os.listdir(app.config['UPLOAD_FOLDER']):
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        if os.path.isfile(filepath):
            size = os.path.getsize(filepath)
            # 格式化文件大小
            if size < 1024:
                size_str = f"{size} B"
            elif size < 1024 * 1024:
                size_str = f"{size/1024:.2f} KB"
            elif size < 1024 * 1024 * 1024:
                size_str = f"{size/(1024*1024):.2f} MB"
            else:
                size_str = f"{size/(1024*1024*1024):.2f} GB"
                
            files.append({'name': filename, 'size': size_str})
    
    # 准备设备列表数据
    device_list = []
    for mac, device_info in devices.items():
        device_list.append({
            'ip': device_info['ip'],
            'mac': device_info['mac'],
            'hostname': device_info['hostname']
        })
    
    # 获取当前年份用于页脚
    current_year = datetime.now().year
    local_ip = get_local_ip()
    port = 5000
    
    return render_template_string(
        HTML_TEMPLATE, 
        files=files, 
        devices=device_list,
        ip_address=local_ip,
        port=port,
        year=current_year
    )

@app.route('/upload', methods=['POST'])
def upload_file():
    """处理文件上传"""
    if 'file' not in request.files:
        return jsonify({'error': '没有文件部分'}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': '没有选择文件'}), 400
    
    if file:
        # 处理文件名重复
        filename = file.filename
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        counter = 1
        while os.path.exists(filepath):
            name, ext = os.path.splitext(filename)
            filename = f"{name}_{counter}{ext}"
            filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            counter += 1
            
        file.save(filepath)
        return jsonify({'success': True, 'message': '文件上传成功'}), 200

@app.route('/download/<filename>')
def download_file(filename):
    """处理文件下载"""
    try:
        # 安全检查，防止路径遍历
        safe_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        if not os.path.exists(safe_path) or not os.path.isfile(safe_path):
            return jsonify({'success': False, 'message': '文件不存在'}), 404
            
        # 确保文件在上传目录内
        if not os.path.abspath(safe_path).startswith(os.path.abspath(app.config['UPLOAD_FOLDER'])):
            return jsonify({'success': False, 'message': '非法访问'}), 403
            
        return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

@app.route('/delete/<filename>', methods=['DELETE'])
def delete_file(filename):
    """处理文件删除"""
    try:
        # 安全检查
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        if not os.path.exists(filepath):
            return jsonify({'success': False, 'message': '文件不存在'}), 404
            
        if not os.path.isfile(filepath):
            return jsonify({'success': False, 'message': '不是文件'}), 400
            
        # 确保文件在上传目录内
        if not os.path.abspath(filepath).startswith(os.path.abspath(app.config['UPLOAD_FOLDER'])):
            return jsonify({'success': False, 'message': '非法操作'}), 403
        
        os.remove(filepath)
        return jsonify({'success': True, 'message': '文件删除成功'})
    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

@app.route('/start_scan', methods=['POST'])
def start_scan():
    """开始设备扫描"""
    global scanning
    if scanning:
        return jsonify({'success': False, 'message': '扫描已在运行中'})
    
    # 在后台线程中运行扫描
    def run_scan():
        scan_network()
    
    thread = threading.Thread(target=run_scan)
    thread.daemon = True
    thread.start()
    
    return jsonify({'success': True, 'message': '设备扫描已启动'})

@app.route('/stop_scan', methods=['POST'])
def stop_scan():
    """停止设备扫描"""
    global scanning
    scanning = False
    return jsonify({'success': True, 'message': '设备扫描已停止'})

@app.route('/scan_progress')
def scan_progress():
    """获取扫描进度"""
    device_count = len(devices)
    return jsonify({
        'scanning': scanning,
        'scanned_ips': scanned_ips,
        'total_ips': total_ips,
        'device_count': device_count
    })

def start_server():
    """启动服务器"""
    local_ip = get_local_ip()
    port = 5000
    
    print("=" * 60)
    print(" 工具已启动，不要瞎几把上传奇怪的东西")
    print(f" 本地访问地址: http://localhost:{port}")
    print(f" 局域网访问地址: http://{local_ip}:{port}")
    print("=" * 60)
    print("官网工具记得star哦！github.com 支持一下吧真的没有star")
    print("我的邮箱naxid@caoshen.top，欢迎交流")
    print("在上学不一定会及时看和回复")
    
    # 自动打开浏览器
    try:
        webbrowser.open(f"http://localhost:{port}")
    except:
        pass
    
    # 启动Flask应用
    app.run(host='0.0.0.0', port=port, debug=False, threaded=True)

if __name__ == '__main__':
    start_server()
    