import os
import sys
import subprocess
from pathlib import Path

REQUIRED_PACKAGES = [
    "django",
    "djangorestframework",
    "drf-yasg",
    "djangorestframework-simplejwt",
    "Pillow",
    "django-cors-headers",
    "django-jazzmin"
]


def run_command(command, cwd=None):
    subprocess.run(command, cwd=cwd, check=True)


def install_required_packages():
    print("Pip yangilanmoqda...")
    run_command([sys.executable, "-m", "pip", "install", "--upgrade", "pip"])

    print("Kerakli kutubxonalar o‘rnatilmoqda...")
    run_command([sys.executable, "-m", "pip", "install", *REQUIRED_PACKAGES])


def update_settings(base: Path):
    settings_path = base / "core" / "settings.py"

    if not settings_path.exists():
        print(f"Xatolik: settings.py topilmadi: {settings_path}")
        sys.exit(1)

    with open(settings_path, "r", encoding="utf-8") as f:
        lines = f.readlines()

    extra_apps = [
        "rest_framework",
        "rest_framework_simplejwt",
        "drf_yasg",
        "corsheaders",
        "main",
    ]

    new_lines = []
    inside_installed_apps = False
    apps_inserted = False

    for line in lines:
        stripped = line.strip()

        if stripped == "INSTALLED_APPS = [":
            inside_installed_apps = True
            new_lines.append(line)
            continue

        if inside_installed_apps and stripped == "'django.contrib.admin',":
            existing_text = "".join(new_lines) + "".join(lines)

            if "'jazzmin'" not in existing_text:
                new_lines.append("    'jazzmin',\n")

            new_lines.append(line)
            continue

        if inside_installed_apps and stripped == "]" and not apps_inserted:
            existing_text = "".join(new_lines)

            for app in extra_apps:
                if f"'{app}'" not in existing_text:
                    new_lines.append(f"    '{app}',\n")

            new_lines.append(line)
            inside_installed_apps = False
            apps_inserted = True
            continue

        new_lines.append(line)

    content = "".join(new_lines)

    if "from datetime import timedelta" not in content:
        if "from pathlib import Path" in content:
            content = content.replace(
                "from pathlib import Path",
                "from pathlib import Path\nfrom datetime import timedelta"
            )
        else:
            content = "from datetime import timedelta\n" + content

    if "ALLOWED_HOSTS = []" in content:
        content = content.replace("ALLOWED_HOSTS = []", "ALLOWED_HOSTS = ['*']")
    elif "ALLOWED_HOSTS = ['*']" not in content:
        content += "\nALLOWED_HOSTS = ['*']\n"

    cors_middleware = "    'corsheaders.middleware.CorsMiddleware',\n"
    if "'corsheaders.middleware.CorsMiddleware'" not in content:
        middleware_lines = content.splitlines(keepends=True)
        updated_middleware_lines = []
        inside_middleware = False
        middleware_inserted = False

        for line in middleware_lines:
            updated_middleware_lines.append(line)

            if line.strip() == "MIDDLEWARE = [":
                inside_middleware = True
                continue

            if inside_middleware and not middleware_inserted:
                updated_middleware_lines.append(cors_middleware)
                middleware_inserted = True
                inside_middleware = False

        content = "".join(updated_middleware_lines)

    static_count = content.count("STATIC_URL = 'static/'")
    if static_count > 1:
        first_seen = False
        cleaned_lines = []

        for line in content.splitlines(keepends=True):
            if line.strip() == "STATIC_URL = 'static/'":
                if not first_seen:
                    cleaned_lines.append(line)
                    first_seen = True
            else:
                cleaned_lines.append(line)

        content = "".join(cleaned_lines)

    extra_blocks = []

    if "CORS_ALLOW_ALL_ORIGINS = True" not in content:
        extra_blocks.append("CORS_ALLOW_ALL_ORIGINS = True\n")

    if "REST_FRAMEWORK = {" not in content:
        extra_blocks.append(
            """REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
}
"""
        )

    if "SIMPLE_JWT = {" not in content:
        extra_blocks.append(
            """SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(days=30),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=180),
}
"""
        )

    if "SWAGGER_SETTINGS = {" not in content:
        extra_blocks.append(
            """SWAGGER_SETTINGS = {
    'SECURITY_DEFINITIONS': {
        'Bearer': {
            'type': 'apiKey',
            'name': 'Authorization',
            'in': 'header',
        }
    }
}
"""
        )

    if "MEDIA_URL = '/media/'" not in content:
        extra_blocks.append("MEDIA_URL = '/media/'\n")

    if "MEDIA_ROOT = BASE_DIR / 'media'" not in content:
        extra_blocks.append("MEDIA_ROOT = BASE_DIR / 'media'\n")

    if "STATICFILES_DIRS = [BASE_DIR / 'static']" not in content and "STATIC_ROOT = BASE_DIR / 'staticfiles'" not in content:
        extra_blocks.append(
            """if DEBUG:
    STATICFILES_DIRS = [BASE_DIR / 'static']
else:
    STATIC_ROOT = BASE_DIR / 'staticfiles'
"""
        )

    if "DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'" not in content:
        extra_blocks.append("DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'\n")

    if extra_blocks:
        content = content.rstrip() + "\n\n" + "\n".join(extra_blocks) + "\n"

    with open(settings_path, "w", encoding="utf-8") as f:
        f.write(content)

def update_urls(base: Path):
    urls_path = base / "core" / "urls.py"

    content = """from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

schema_view = get_schema_view(
    openapi.Info(
        title="API",
        default_version='v1',
        description="API",
    ),
    public=True,
    permission_classes=(permissions.AllowAny,),
)

urlpatterns = [
    path('', include('main.urls')),
    path('admin/', admin.site.urls),
    path('token/', TokenObtainPairView.as_view()),
    path('token/refresh/', TokenRefreshView.as_view()),
    path('swagger/', schema_view.with_ui('swagger', cache_timeout=0)),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
"""

    with open(urls_path, "w", encoding="utf-8") as f:
        f.write(content)


def create_main_files(base: Path):
    (base / "main" / "urls.py").write_text(
        """from django.urls import path
from .views import hello_view

urlpatterns = [
    path('', hello_view),
]
""",
        encoding="utf-8",
    )

    (base / "main" / "views.py").write_text(
        """from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET'])
def hello_view(request):
    return Response({"message": "Hello from ABZ"})
""",
        encoding="utf-8",
    )


def create_other_files(base: Path):
    (base / ".gitignore").write_text(
        """__pycache__/
*.py[cod]
*.sqlite3
db.sqlite3
media/
staticfiles/
.env
.idea/
.vscode/
""",
        encoding="utf-8",
    )

    with open(base / "requirements.txt", "w") as f:
        for pkg in REQUIRED_PACKAGES:
            f.write(pkg + "\n")

    (base / "static").mkdir(exist_ok=True)
    (base / "media").mkdir(exist_ok=True)


def main():
    print("ABZ Django Starter...")

    base = Path.cwd()

    if (base / "manage.py").exists():
        print("Bu papkada allaqachon Django loyiha bor.")
        return

    install_required_packages()

    print("Django project yaratilmoqda...")
    run_command([sys.executable, "-m", "django", "startproject", "core", "."], cwd=base)
    run_command([sys.executable, "manage.py", "startapp", "main"], cwd=base)

    update_settings(base)
    update_urls(base)
    create_main_files(base)
    create_other_files(base)

    print("Migratsiya...")
    run_command([sys.executable, "manage.py", "migrate"], cwd=base)

    print("\nTAYYOR!")
    print("python manage.py runserver")
    print("Swagger: http://127.0.0.1:8000/swagger/")
    print("Admin:   http://127.0.0.1:8000/admin/")


if __name__ == "__main__":
    main()