import os
import yaml
from pathlib import Path

def recursiveSearchForDockerComposeFiles(watchFolder: Path):
    dockerComposeList = []
    for root, _, files in os.walk(watchFolder):
        for file in files:
            if file == "docker-compose.yaml":
                dockerComposeList.append(Path(root) / file)
    return dockerComposeList

def readDockerComposeFile(dockerComposeFile: Path) -> yaml:
    # Load the Docker Compose file
    with open(dockerComposeFile, 'r') as file:
        docker_compose = yaml.safe_load(file)
    return docker_compose

def getExposedPortsFromDockerComposeFile(dockerComposeFile: str):
    exposedPorts = []
    services = readDockerComposeFile(dockerComposeFile).get('services', {})
    # Iterate through services to find ports
    for service, config in services.items():
        ports = config.get('ports', [])
        for port in ports:
            # Split the port mapping if it's in the "host:container" format
            exposedPort = port.split(':')[0]  # Get the host port
            exposedPorts.append(exposedPort)
    return exposedPorts

def checkPortUnique(ports: dict) -> bool:
    portNumbers = []
    wrong = False
    for project in ports:
        for port in ports[project]:
            if port in portNumbers:
                if not wrong:
                    print("\n\nšŸ”“ Some ports are not unique šŸ–\n")
                print(f"šŸ”“ ERROR : Port *{port}* is not unique")
                wrong = True
                for project2 in ports:
                    if port in ports[project2]:
                        print(f"\t{project} and {project2}")
            portNumbers.append(port)
    return wrong

def main(watchFolder: str):
    # For each folder, read docker-compose.yaml and look for exposed ports
    dockerComposeList = recursiveSearchForDockerComposeFiles(watchFolder)
    ports = {}
    for dockerComposeFile in dockerComposeList:
        # Get exposed ports
        exposedPorts = getExposedPortsFromDockerComposeFile(dockerComposeFile)
        ports[dockerComposeFile] = exposedPorts
        if len(exposedPorts) == 0:
            print(f"\nšŸ“¦ {dockerComposeFile}"
                  f"\nšŸ”“ No exposed ports found"
                  f"\n")
        else:
            print(f"\nšŸ“¦ {dockerComposeFile}"
                f"\nšŸ”— Exposed ports: {exposedPorts}"
                f"\n")
    
    wrong = checkPortUnique(ports)
    
    if wrong:
        exit(1)
    else:
        print("\n\nāœ… All ports are unique\n\n")
        exit(0)

if __name__ == "__main__":
    print("Traefik label watcher CI/CD")
    # Read folder from env
    watchFolder = os.getenv("WATCH_FOLDER")
    if watchFolder == None:
        watchFolder = "."
        
    watchFolder = Path(watchFolder)
    
    main(watchFolder)