#!/usr/bin/env python3
"""
myls - A custom ls-like terminal tool
"""

import os
import sys
import stat
from datetime import datetime

RESET  = "\033[0m"
BLUE   = "\033[34m"
GREEN  = "\033[32m"
WHITE  = "\033[37m"
YELLOW = "\033[33m"


def color_name(name, full_path):
    if os.path.islink(full_path):
        return f"{YELLOW}{name}{RESET}"
    elif os.path.isdir(full_path):
        return f"{BLUE}{name}/{RESET}"
    elif os.access(full_path, os.X_OK):
        return f"{GREEN}{name}*{RESET}"
    else:
        return f"{WHITE}{name}{RESET}"


def format_size(size):
    for unit in ["B", "K", "M", "G"]:
        if size < 1024:
            return f"{size:>4}{unit}"
        size //= 1024
    return f"{size:>4}T"


def format_permissions(mode):
    kinds = [
        (stat.S_IRUSR, "r"), (stat.S_IWUSR, "w"), (stat.S_IXUSR, "x"),
        (stat.S_IRGRP, "r"), (stat.S_IWGRP, "w"), (stat.S_IXGRP, "x"),
        (stat.S_IROTH, "r"), (stat.S_IWOTH, "w"), (stat.S_IXOTH, "x"),
    ]
    prefix = "d" if stat.S_ISDIR(mode) else "-"
    bits = "".join(c if mode & flag else "-" for flag, c in kinds)
    return prefix + bits


def list_directory(path):
    if not os.path.exists(path):
        print(f"myls: cannot access '{path}': No such file or directory")
        sys.exit(1)

    entries = sorted(os.scandir(path), key=lambda e: e.name.lower())
    entries = [e for e in entries if not e.name.startswith(".")]

    if not entries:
        print("(empty directory)")
        return

    print(f"\n  Directory: {os.path.abspath(path)}\n")
    print(f"  {'PERMS':<11} {'SIZE':>6}  {'MODIFIED':<17}  NAME")
    print("  " + "─" * 55)

    for entry in entries:
        info     = entry.stat(follow_symlinks=False)
        perms    = format_permissions(info.st_mode)
        size     = format_size(info.st_size)
        modified = datetime.fromtimestamp(info.st_mtime).strftime("%Y-%m-%d %H:%M")
        name     = color_name(entry.name, entry.path)
        print(f"  {perms}  {size}  {modified}  {name}")

    print(f"\n  {len(entries)} items\n")


def main():
    path = sys.argv[1] if len(sys.argv) > 1 else "."
    list_directory(path)


if __name__ == "__main__":
    main()
