# Imports
import subprocess
import sys
import os
import importlib.util
from pathlib import Path

# Install Django
"""Install Django only if not already installed"""
if importlib.util.find_spec("django") is None:
    subprocess.check_call([sys.executable, "-m", "pip", "install", "Django"])
else:
    print("Django is already installed.")

# Create Project & App
"""Create Django project if not already created"""
project_name = input("Enter your project name (e.g MyProject): \n")
if not os.path.exists(project_name):
    subprocess.check_call(["django-admin", "startproject", project_name])
else:
    print(f"Project '{project_name}' already exists.")
"""Create Django app if not already created"""
app_name = input("Enter your app name (website or domain name e.g. if example.com - example): \n")
app_path = Path(project_name) / app_name
if not app_path.exists():
    cwd = Path.cwd()
    os.chdir(project_name)
    subprocess.check_call([sys.executable, "manage.py", "startapp", app_name])
    os.chdir(cwd)
else:
    print(f"App '{app_name}' already exists inside '{project_name}'.")

# Add app to settings
settings_path = Path(project_name) / project_name / "settings.py"
with open(settings_path, "r") as f:
    settings_content = f.read()

if f"{app_name}" not in settings_content:
    insert_point = "'django.contrib.staticfiles',"
    replacement = insert_point + f"\n    '{app_name}',"
    new_content = settings_content.replace(insert_point, replacement)
    with open(settings_path, 'w') as f:
        f.write(new_content)
        print(f"App '{app_name}' added to INSTALLED_APPS in settings.py")
else:
    print(f"App '{app_name}' is already in INSTALLED_APPS.")

# ------ Create a website folders -----
# Scripts
scripts_path = Path(app_path) / "scripts"
if not scripts_path.exists():
    scripts_path.mkdir(parents=True, exist_ok=True)
    print(f"Created directory: {scripts_path}")
else:
    print(f"Directory already exists: {scripts_path}")

init_file = Path(scripts_path) / "__init__.py"
if not init_file.exists():
    with open(init_file, "w") as f:
        f.write("# scripts package")
    print(f"Created file: {init_file}")
else:
    print(f"File already exists: {init_file}")

# Templates, Static, CSS, JS & Images
template_path = Path(app_path) / "templates"
if not template_path.exists():
    template_path.mkdir(parents=True, exist_ok=True)
    print(f"Created directory: {template_path}")
else:
    print(f"Directory already exists: {template_path}")

static_path = Path(app_path) /  "static"
if not static_path.exists():
    static_path.mkdir(parents=True, exist_ok=True)
    print(f"Created directory: {static_path}")
else:
    print(f"Directory already exists: {static_path}")

folders = ['css', 'js', 'images']
for folder in folders:
    folder_path = Path(app_path) / "static" / folder
    if not folder_path.exists():
        folder_path.mkdir(parents=True, exist_ok=True)
        print(f"Created directory: {folder_path}")
    else:
        print(f"Directory already exists: {folder_path}")

# Add static, dirs, templates to settings.py
with open(settings_path, "r") as f:
    settings_content = f.read()

if "import os" not in settings_content:
    insert_point = 'from pathlib import Path'
    new_block = """import os"""
    settings_content = settings_content.replace(insert_point, insert_point + "\n" + new_block)
    print("Imports added to settings.py")
else:
    print("Imports already in settings.py")

if "BASE_DIR = Path(__file__).resolve().parent.parent" not in settings_content:
    insert_point = "# Build paths inside the project like this: BASE_DIR / 'subdir'."
    new_block = "BASE_DIR = Path(__file__).resolve().parent.parent"
    settings_content = settings_content.replace(insert_point, insert_point + "\n" + new_block)
    print("Parent DIR added to settings.py")
else:
    print("Parent DIR already in settings.py")

if f'[BASE_DIR / "{app_name}" / "templates"],' not in settings_content:
    settings_content = settings_content.replace(
        "'DIRS': [],",
        f"'DIRS': [BASE_DIR / \"{app_name}\" / \"templates\"],"
    )
    print("Templates added to settings.py")
else:
    print("Templates already in settings.py")

static_block = (
    "STATIC_URL = 'static/'\n"
    "STATIC_ROOT = BASE_DIR / 'staticfiles'\n"
    f"STATICFILES_DIRS = [BASE_DIR / '{app_name}' / 'static']"
)

if "STATIC_ROOT" not in settings_content and f"BASE_DIR / '{app_name}' / 'static'" not in settings_content:
    settings_content = settings_content.replace("STATIC_URL = 'static/'", static_block)
    with open(settings_path, "w") as f:
        f.write(settings_content)
    print(f"Added STATIC_ROOT and STATICFILES_DIRS for '{app_name}'")
else:
    print("STATIC_ROOT / STATICFILES_DIRS already configured.")

with open(settings_path, "w") as f:
    f.write(settings_content)

# Create Homepage (Index file)
index_path = Path(app_path) / template_path
content = """
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" type="text/css" href="{% static 'css/Style.css' %}">
    <link rel="icon" type="image/x-icon" href="{% static 'images/code-library-icon.jpg' %}">
    <title>{{ app_name }}</title>
</head>
<body id="Home">
    <div>
        <h1>Django Homepage</h1>
        <p>Congratulations, you have successfully installed Django. You can now start your journey in creating a stunning webpage!<p>
    </div>
</body>
</html>
"""
with open(Path(app_path) / "templates" / "index.html", "w", encoding="utf-8") as f:
    f.write(content)

# Add index to views.py
views_path = Path(app_path) / "views.py"

content = """
from django.shortcuts import render

def index(request):
    return render(request, "index.html")
"""

with open(views_path, "r+") as f:
    views_content = f.read()
    if "def index(" not in views_content:
        f.write("\n" + content)
        print("Added index view to views.py")
    else:
        print("Index view already exists in views.py")

# Add index to urls.py
urls_path = Path(project_name) / project_name / "urls.py"
imports = f"from {app_name} import views"
import_insert_point = "from django.urls import path"
url_insert_point = "path('admin/', admin.site.urls),"
urls_block = """   
path('', views.index, name='home'),
path('', views.index, name='index'),
"""

# add paths to urls.py
with open(urls_path, "r+", encoding="utf-8") as f:
    urls_content = f.read()
    modified = False

    if imports not in urls_content:
        urls_content = urls_content.replace(
            import_insert_point,
            import_insert_point + "\n" + imports
        )
        modified = True
        print("Added import to urls.py")

    if "path('', views.index, name='home')," not in urls_content:
        if "urlpatterns = [" in urls_content:
            urls_content = urls_content.replace(url_insert_point, url_insert_point + urls_block)
            modified = True
            print("Added index view to urls.py")
        else:
            print("Could not find urlpatterns list in urls.py")

    if modified:
        f.seek(0)
        f.write(urls_content)
        f.truncate()
    else:
        print("No changes needed in urls.py")

# add website security
with open(settings_path, "r") as f:
    settings_content = f.read()

security_content = f"""
# ==============================
# Django Security Settings
# ==============================

# Use HTTPS everywhere
SECURE_SSL_REDIRECT = False
SECURE_HSTS_SECONDS = 31536000  # 1 year (adjust if testing)
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

# Protect against content sniffing
SECURE_CONTENT_TYPE_NOSNIFF = True

# Prevent XSS
SECURE_BROWSER_XSS_FILTER = True  # Some browsers (older)
X_FRAME_OPTIONS = "DENY"  # Prevent clickjacking (use "SAMEORIGIN" if you need iframes)

# CSRF Protection
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True

# Session / Cookie Security
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True

# Referrer Policy (optional, but good practice)
SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"
    """
security_insert_point = "DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'"

if "Django Security Settings" not in settings_content:
    settings_content = settings_content.replace(
        security_insert_point, security_insert_point + "\n\n" + security_content
    )
    with open(settings_path, "w", encoding="utf-8") as f:
        f.write(settings_content)
    print("✅ Security settings added to settings.py")
else:
    print("ℹ️ Security settings already present — no changes made.")

# Set hosts
with open(settings_path, "r") as f:
    settings_content = f.read()

if "ALLOWED_HOSTS = []" in settings_content:
    allowed_hosts = input("Enter your allowed hosts (comma-separated, e.g. example.com,127.0.0.1): \n")
    allowed_hosts_list = [h.strip() for h in allowed_hosts.split(",") if h.strip()]
    allowed_hosts_str = "[" + ", ".join(f'"{h}"' for h in allowed_hosts_list) + "]"

    csrf_trusted_list = ["https://" + h for h in allowed_hosts_list if not h.startswith("http")]
    csrf_trusted_str = "[" + ", ".join(f'"{h}"' for h in csrf_trusted_list) + "]"

    settings_content = settings_content.replace(
        "ALLOWED_HOSTS = []",
        f"ALLOWED_HOSTS = {allowed_hosts_str}"
    )

    if "CSRF_COOKIE_HTTPONLY = True" in settings_content:
        settings_content = settings_content.replace(
            "CSRF_COOKIE_HTTPONLY = True",
            f"CSRF_COOKIE_HTTPONLY = True\nCSRF_TRUSTED_ORIGINS = {csrf_trusted_str}"
        )

    with open(settings_path, "w", encoding="utf-8") as f:
        f.write(settings_content)

    print("✅ Allowed Hosts added to settings.py")
else:
    print("ℹ️ Allowed Hosts already set — no changes made.")

# Set debug mode to FALSE
with open(settings_path, "r") as f:
    settings_content = f.read()

if "DEBUG = True" in settings_content:
    settings_content = settings_content.replace(
        "DEBUG = True",
        "DEBUG = False"
    )
    with open(settings_path, "w", encoding="utf-8") as f:
        f.write(settings_content)
    print("✅ Debug Mode set to False in settings.py")
else:
    print("ℹ️ Debug Mode already set — no changes made.")

# Start Django server
subprocess.check_call([sys.executable,"manage.py", "runserver"])
