import paramiko
import os
import time
from concurrent.futures import ThreadPoolExecutor, as_completed

LOCAL_DIR = r"E:\Git_new\spider\py_spider"
REMOTE_DIR = "/mnt/py_spider"
HOST = "hg221.bovps.cn"
PORT = 20092
USER = "root"
PASSWORD = "yswg2023"
WORKERS = 8

files_to_check = []
dirs_to_ensure = set()
for root, dirs, files in os.walk(LOCAL_DIR):
    rel_dir = os.path.relpath(root, LOCAL_DIR).replace("\\", "/")
    remote_dir = f"{REMOTE_DIR}/{rel_dir}" if rel_dir != "." else REMOTE_DIR
    dirs_to_ensure.add(remote_dir)
    for f in files:
        local_path = os.path.join(root, f)
        remote_path = f"{remote_dir}/{f}"
        local_mtime = int(os.path.getmtime(local_path))
        local_size = os.path.getsize(local_path)
        files_to_check.append((local_path, remote_path, local_mtime, local_size))

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(HOST, port=PORT, username=USER, password=PASSWORD, timeout=15, banner_timeout=20)
sftp = client.open_sftp()

for d in sorted(dirs_to_ensure):
    parts = d.split("/")
    for i in range(1, len(parts) + 1):
        p = "/".join(parts[:i])
        if not p:
            continue
        try:
            sftp.stat(p)
        except:
            try:
                sftp.mkdir(p)
            except:
                pass

to_upload = []
for local_path, remote_path, local_mtime, local_size in files_to_check:
    try:
        rstat = sftp.stat(remote_path)
        if rstat.st_size == local_size and rstat.st_mtime >= local_mtime:
            continue
    except:
        pass
    to_upload.append((local_path, remote_path))

sftp.close()
client.close()

print(f"Total: {len(files_to_check)} files, Changed: {len(to_upload)} files")

if not to_upload:
    print("Nothing to upload, already up to date!")
else:
    uploaded = 0
    failed = 0
    start = time.time()

    def upload_one(item):
        lp, rp = item
        c = paramiko.SSHClient()
        c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        c.connect(HOST, port=PORT, username=USER, password=PASSWORD, timeout=15, banner_timeout=20)
        s = c.open_sftp()
        s.put(lp, rp)
        s.close()
        c.close()
        return rp

    with ThreadPoolExecutor(max_workers=WORKERS) as pool:
        futures = {pool.submit(upload_one, item): item for item in to_upload}
        for f in as_completed(futures):
            try:
                f.result()
                uploaded += 1
            except Exception as e:
                failed += 1
                print(f"  FAIL: {futures[f][1]} - {e}")

    elapsed = time.time() - start
    print(f"Done! {uploaded} files uploaded in {elapsed:.1f}s ({failed} failed)")
