import os, shutil
import time
import subprocess
import json
from datetime import datetime
import psutil
import stat

# اطلاعات Gitea شما
REPO_DIR = "bot_ea_db"
GIT_REPO = "http://pythonkoft:2f135dee41b069f92413dd3f234e12cb8c20a96a@188.245.173.247:3080/pythonkoft/ea_shadow.git"
LOG_FILE = "log.json"
LAST_COMMIT_FILE = "last_commit.txt"
PROCESS_NAME = "main.bat"
PID_FILE = "main_pid.txt"

def write_log(event, message):
    log_entry = {
        "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "event": event,
        "message": message
    }
    if not os.path.exists(LOG_FILE):
        with open(LOG_FILE, "w", encoding="utf-8") as f:
            json.dump([log_entry], f, ensure_ascii=False, indent=2)
    else:
        try:
            with open(LOG_FILE, "r+", encoding="utf-8") as f:
                try:
                    logs = json.load(f)
                except json.JSONDecodeError:
                    f.seek(0)
                    f.truncate()
                    logs = []
                logs.append(log_entry)
                f.seek(0)
                json.dump(logs, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print("خطا در نوشتن لاگ:", e)

def kill_old_process():
    if not os.path.exists(PID_FILE):
        write_log("kill", "هیچ PIDی برای بستن وجود نداشت.")
        return

    try:
        with open(PID_FILE, "r") as f:
            pid = int(f.read().strip())

        parent = psutil.Process(pid)
        children = parent.children(recursive=True)

        for child in children:
            child.terminate()

        gone, still_alive = psutil.wait_procs(children, timeout=5)
        write_log("kill", f"{len(gone)} تا subprocess بسته شد. هنوز زنده‌ها: {len(still_alive)}")

        os.remove(PID_FILE)

    except (psutil.NoSuchProcess, ValueError):
        write_log("kill", "PID معتبر نبود یا پروسه پیدا نشد.")
    except Exception as e:
        write_log("kill", f"خطا در بستن subprocessها: {str(e)}")

def get_latest_commit():
    try:
        result = subprocess.run(
            ["git", "-C", REPO_DIR, "rev-parse", "HEAD"],
            capture_output=True,
            text=True
        )
        return result.stdout.strip()
    except Exception as e:
        write_log("error", f"get commit error: {str(e)}")
        return None

def save_last_commit(commit_hash):
    with open(LAST_COMMIT_FILE, "w") as f:
        f.write(commit_hash)

def load_last_commit():
    if os.path.exists(LAST_COMMIT_FILE):
        with open(LAST_COMMIT_FILE, "r") as f:
            return f.read().strip()
    return None

def clean_gitconfig():
    home_dir = os.path.expanduser("~")
    gitconfig_path = os.path.join(home_dir, ".gitconfig")

    if not os.path.exists(gitconfig_path):
        return

    try:
        with open(gitconfig_path, "r", encoding="utf-8") as f:
            lines = f.readlines()

        new_lines = []
        skip_next = False
        for line in lines:
            if line.strip().startswith('[credential "http://188.245.173.247:3080"]'):
                skip_next = True
                continue
            if skip_next:
                if line.strip().startswith("provider"):
                    skip_next = False
                    continue
            new_lines.append(line)

        # رفع مشکل Read-Only ویندوز
        if not os.access(gitconfig_path, os.W_OK):
            os.chmod(gitconfig_path, stat.S_IWRITE)

        with open(gitconfig_path, "w", encoding="utf-8") as f:
            f.writelines(new_lines)

        write_log("cleanup", ".gitconfig پاکسازی شد.")

    except Exception as e:
        write_log("error", f"خطا در پاکسازی .gitconfig: {e}")

def clear_git_credentials():
    # حذف credential helper
    subprocess.run(["git", "config", "--global", "--unset", "credential.helper"], capture_output=True)

    # پاک کردن فایل‌هایی که اسمشون git داره توی Home
    home_dir = os.path.expanduser("~")
    for fname in os.listdir(home_dir):
        if fname.lower().startswith(".git"):
            try:
                file_path = os.path.join(home_dir, fname)
                if not os.access(file_path, os.W_OK):
                    os.chmod(file_path, stat.S_IWRITE)
                os.remove(file_path)
                write_log("cleanup", f"فایل {fname} از Home پاک شد.")
            except Exception as e:
                write_log("error", f"پاک کردن {fname} نشد: {e}")

def clone_or_update_repo():
    clean_gitconfig()
    clear_git_credentials()

    if os.path.exists(REPO_DIR):
        try:
            result = subprocess.run(
                ["git", "-C", REPO_DIR, "pull"],
                capture_output=True,
                text=True
            )
            if result.returncode == 0:
                write_log("pull", "مخزن آپدیت شد.")
            else:
                write_log("error", f"خطا در git pull: {result.stderr}")
        except Exception as e:
            write_log("error", f"git pull failed: {str(e)}")
    else:
        result = subprocess.run(
            ["git", "clone", GIT_REPO, REPO_DIR],
            capture_output=True,
            text=True
        )
        if result.returncode == 0:
            write_log("clone", "مخزن کلون شد.")
        else:
            write_log("error", f"خطا در کلون کردن: {result.stderr}")

def run_main_bat():
    try:
        shutil.copy(os.path.join(os.getcwd(), '.env'), os.path.join(os.getcwd(), 'bot_ea_db'))
        process = subprocess.Popen(
            ["cmd.exe", "/c", "main.bat"],
            cwd=REPO_DIR,
            creationflags=subprocess.CREATE_NEW_CONSOLE
        )

        with open(PID_FILE, "w") as f:
            f.write(str(process.pid))

        write_log("run", f"main.bat اجرا شد با PID={process.pid}.")
    except Exception as e:
        write_log("error", f"main.bat اجرا نشد: {str(e)}")

def main_loop():
    while True:
        try:
            print('1')
            clone_or_update_repo()
            print('2')
            latest_commit = get_latest_commit()
            print('3')
            saved_commit = load_last_commit()
            print('4')
            if latest_commit and latest_commit != saved_commit:
                print('5')
                write_log("update", f"کمیت جدید: {latest_commit}")
                print('6')
                kill_old_process()
                print('7')
                run_main_bat()
                print('8')
                save_last_commit(latest_commit)
            else:
                print(("check", "تغییری نبود."))
                write_log("check", "تغییری نبود.")
            print(60)
            time.sleep(60)
        except Exception as e:
            print('EROR MSG :>>> ', e)

def clean_initial_files():
    # پاک کردن log.json
    if os.path.exists(LOG_FILE):
        try:
            os.remove(LOG_FILE)
            print(f"{LOG_FILE} پاک شد.")
        except Exception as e:
            print(f"پاک کردن {LOG_FILE} نشد:", e)
    # پاک کردن PID_FILE
    if os.path.exists(PID_FILE):
        try:
            os.remove(PID_FILE)
            print(f"{PID_FILE} پاک شد.")
        except Exception as e:
            print(f"پاک کردن {PID_FILE} نشد:", e)
    if os.path.exists('last_commit.txt'):
        try:
            os.remove('last_commit.txt')
            print(f"{PID_FILE} پاک شد.")
        except Exception as e:
            print(f"پاک کردن {PID_FILE} نشد:", e)
if __name__ == "__main__":
    # پاکسازی اولیه قبل از حلقه
    clean_initial_files()
    main_loop()
