import os
from pathlib import Path
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError


MODULE_TEMPLATE_FILES = {
    'models.py': """from django.db import models

# Create your models here.
""",
    'views.py': """from rest_framework import viewsets

# Create your views here.
""",
    'serializers.py': """from rest_framework import serializers

# Create your serializers here.
""",
    'urls.py': """from django.urls import path

urlpatterns = []
""",
    'admin.py': """from django.contrib import admin

# Register your models here.
""",
    'apps.py': """from django.apps import AppConfig


class {AppConfigName}Config(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = '{app_path}'
""",
    '__init__.py': """# package init""",
}


SERVICE_INIT = """# services package"""

SERVICE_TEMPLATE = """# Service layer for {module}

def example_service_func(*args, **kwargs):
    return {{'ok': True}}
"""


class Command(BaseCommand):
    help = 'Create a new platform or business module skeleton under apps/{platform|business}.'

    def add_arguments(self, parser):
        parser.add_argument('module_name', type=str)
        parser.add_argument('--type', dest='module_type', required=True, choices=['platform', 'business'], help='Type of module: platform or business')

    def handle(self, *args, **options):
        module_name = options.get('module_name')
        module_type = options.get('module_type')
        if not module_name:
            raise CommandError('module_name is required')

        base_dir = Path(settings.BASE_DIR)
        apps_dir = base_dir / 'apps'
        target_base = apps_dir / module_type / module_name

        if target_base.exists():
            self.stdout.write(self.style.WARNING(f'Module {module_name} already exists at {target_base}'))
            return

        # create directory tree
        (target_base / 'services').mkdir(parents=True, exist_ok=True)
        for fname, content in MODULE_TEMPLATE_FILES.items():
            if fname == 'apps.py':
                app_path = f"apps.{module_type}.{module_name}"
                appcfg = content.format(AppConfigName=module_name.capitalize(), app_path=app_path)
                (target_base / fname).write_text(appcfg, encoding='utf-8')
            else:
                (target_base / fname).write_text(content, encoding='utf-8')

        # services
        (target_base / 'services' / '__init__.py').write_text(SERVICE_INIT, encoding='utf-8')
        svc = SERVICE_TEMPLATE.format(module=module_name)
        (target_base / 'services' / f'{module_name}_service.py').write_text(svc, encoding='utf-8')

        # ensure __init__.py
        (target_base / '__init__.py').write_text('# module package', encoding='utf-8')

        self.stdout.write(self.style.SUCCESS(f'Created module skeleton at {target_base}'))

        # append to modules.ENABLED_MODULES
        modules_file = base_dir / 'config' / 'modules.py'
        try:
            text = modules_file.read_text(encoding='utf-8')
            marker = f"\n# added by create_module for {module_name}\n"
            append_line = f'ENABLED_MODULES.append("{module_name}")\n'
            if module_name not in text:
                modules_file.write_text(text + marker + append_line, encoding='utf-8')
                self.stdout.write(self.style.SUCCESS(f'Appended "{module_name}" to config/modules.py'))
            else:
                self.stdout.write(self.style.NOTICE(f'"{module_name}" already referenced in config/modules.py'))
        except Exception as exc:
            self.stdout.write(self.style.WARNING(f'Failed to update config/modules.py: {exc}'))

        # add example include comment to config/urls.py
        urls_file = base_dir / 'config' / 'urls.py'
        try:
            include_line = f"# Example include for {module_name}: path('{module_name}/', include('apps.{module_type}.{module_name}.urls'))\n"
            urls_text = urls_file.read_text(encoding='utf-8')
            if include_line.strip() not in urls_text:
                urls_file.write_text(urls_text + '\n' + include_line, encoding='utf-8')
                self.stdout.write(self.style.SUCCESS(f'Added example include comment to config/urls.py'))
            else:
                self.stdout.write(self.style.NOTICE('Example include already present in config/urls.py'))
        except Exception as exc:
            self.stdout.write(self.style.WARNING(f'Failed to update config/urls.py: {exc}'))

        # update README.md at repo root
        try:
            readme = base_dir.parent / 'README.md'
            usage = f"\n- Create module: python manage.py create_module {module_name} --type {module_type}\n"
            if readme.exists():
                rtext = readme.read_text(encoding='utf-8')
                if usage.strip() not in rtext:
                    readme.write_text(rtext + '\n## Module generator\n' + usage, encoding='utf-8')
                    self.stdout.write(self.style.SUCCESS('Updated README.md with usage example'))
            else:
                # fallback to backend/README.md
                broot = base_dir / 'README.md'
                if broot.exists():
                    btext = broot.read_text(encoding='utf-8')
                    if usage.strip() not in btext:
                        broot.write_text(btext + '\n## Module generator\n' + usage, encoding='utf-8')
                        self.stdout.write(self.style.SUCCESS('Updated backend/README.md with usage example'))
        except Exception as exc:
            self.stdout.write(self.style.WARNING(f'Failed to update README: {exc}'))
