import os
import unittest
import sys
import yaml

sys.path.insert(
    0,
    os.path.abspath(
        os.path.join(
            os.path.dirname(__file__),
            '../../../../../roles/web-app-bigbluebutton/filter_plugins'
        )
    )
)

from compose_mods import compose_mods

def sort_dict(obj):
    if isinstance(obj, dict):
        return {k: sort_dict(obj[k]) for k in sorted(obj)}
    elif isinstance(obj, list):
        return [sort_dict(v) for v in obj]
    else:
        return obj

class TestComposeModsFullFile(unittest.TestCase):
    def setUp(self):
        self.docker_repository_path = "/opt/docker/bigbluebutton/services/repository"
        self.env_file = "/opt/docker/bigbluebutton/.env/env"
        self.original = """# auto generated by ./scripts/generate-compose
# don't edit this directly.

services:
  bbb-web:
    build:
      context: mod/bbb-web
      additional_contexts:
        - src-web=./repos/bigbluebutton/bigbluebutton-web
    volumes:
      - ./data/bigbluebutton:/var/bigbluebutton
      - ./data/freeswitch-meetings:/var/freeswitch/meetings

  freeswitch:
    build:
      context: mod/freeswitch
      additional_contexts:
        - freeswitch=./repos/freeswitch/
    volumes:
      - ./data/freeswitch-meetings:/var/freeswitch/meetings

  nginx:
    build:
      context: mod/nginx

  redis:
    image: redis:7.2-alpine

  coturn:
    image: coturn/coturn:4.6-alpine
    volumes:
      - ./mod/coturn/turnserver.conf:/etc/coturn/turnserver.conf

  bbb-graphql-server:
    build:
      context: mod/bbb-graphql-server
"""

        self.expected = """services:
  bbb-web:
    build:
      context: /opt/docker/bigbluebutton/services/repository/mod/bbb-web
      additional_contexts:
        - src-web=/opt/docker/bigbluebutton/services/repository/repos/bigbluebutton/bigbluebutton-web
    volumes:
      - bigbluebutton:/var/bigbluebutton
      - freeswitch:/var/freeswitch/meetings
    env_file:
      - /opt/docker/bigbluebutton/.env/env

  freeswitch:
    build:
      context: /opt/docker/bigbluebutton/services/repository/mod/freeswitch
      additional_contexts:
        - freeswitch=/opt/docker/bigbluebutton/services/repository/repos/freeswitch/
    volumes:
      - freeswitch:/var/freeswitch/meetings
    env_file:
      - /opt/docker/bigbluebutton/.env/env

  nginx:
    build:
      context: /opt/docker/bigbluebutton/services/repository/mod/nginx
    env_file:
      - /opt/docker/bigbluebutton/.env/env

  redis:
    image: redis:7.2-alpine
    volumes:
      - redis:/data
    env_file:
      - /opt/docker/bigbluebutton/.env/env

  coturn:
    image: coturn/coturn:4.6-alpine
    volumes:
      - /opt/docker/bigbluebutton/services/repository/mod/coturn/turnserver.conf:/etc/coturn/turnserver.conf
      - coturn:/var/lib/coturn
    env_file:
      - /opt/docker/bigbluebutton/.env/env

  bbb-graphql-server:
    build:
      context: /opt/docker/bigbluebutton/services/repository/mod/bbb-graphql-server
    healthcheck:
      test:
        - CMD
        - curl
        - -f
        - http://localhost:8085/healthz
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 10s
    env_file:
      - /opt/docker/bigbluebutton/.env/env

volumes:
  database:
  greenlight:
  redis:
  coturn:
  freeswitch:
  bigbluebutton:
  mediasoup:
"""

    def test_full_file_semantic_match(self):
        actual_data = yaml.safe_load(compose_mods(self.original, self.docker_repository_path, self.env_file))
        expected_data = yaml.safe_load(self.expected)
        for key in expected_data:
            self.assertIn(key, actual_data)
            self.assertEqual(sort_dict(actual_data[key]), sort_dict(expected_data[key]))

if __name__ == "__main__":
    unittest.main()
