import os
import json

BASE_DIR = "/srv/files"

visited_real_paths = set()


def is_inside_base(path):
    return os.path.commonpath([BASE_DIR, path]) == BASE_DIR


def walk(real_path, display_path):

    results = []

    try:
        entries = list(os.scandir(real_path))
    except PermissionError:
        return []

    for entry in entries:
        entry_real = os.path.realpath(entry.path)
        entry_display = os.path.join(display_path, entry.name)

        if entry.is_symlink():
            link_target = os.path.realpath(entry.path)

            node = {
                "name": entry.name,
                "path": entry_display,
                "type": "symlink",
                "target": os.readlink(entry.path),
                "resolved": link_target if is_inside_base(link_target) else link_target,
            }

            results.append(node)

            if os.path.exists(link_target) and link_target not in visited_real_paths:
                visited_real_paths.add(link_target)

                if os.path.isdir(link_target):
                    results.extend(
                        walk(link_target, entry_display)
                    )
                else:
                    results.append({
                        "name": entry.name,
                        "path": entry_display,
                        "type": "file",
                        "source": "symlink-resolved",
                        "real_path": link_target,
                        "size": os.path.getsize(link_target),
                    })

            continue

        if entry.is_dir(follow_symlinks=False):
            real_dir = os.path.realpath(entry.path)

            if real_dir in visited_real_paths:
                continue

            visited_real_paths.add(real_dir)

            results.append({
                "name": entry.name,
                "path": entry_display,
                "type": "dir"
            })

            results.extend(
                walk(entry_real, entry_display)
            )

        else:
            results.append({
                "name": entry.name,
                "path": entry_display,
                "type": "file",
                "size": entry.stat(follow_symlinks=False).st_size
            })

    return results


if __name__ == "__main__":
    visited_real_paths.add(os.path.realpath(BASE_DIR))

    tree = {
        "root": BASE_DIR,
        "items": walk(BASE_DIR, ".")
    }

    with open(os.path.join(BASE_DIR, "index.json"), "w") as f:
        json.dump(tree, f, indent=2)

    print("Generated full recursive symlink-expanded index.json")
