import os
import django

from django.shortcuts import render,redirect
from django.http import HttpResponse, JsonResponse
from django.conf import settings
from django.apps import apps
from django.contrib import messages
from django.contrib.admin.views.decorators import staff_member_required
from .models import *
from django.apps import apps
from pathlib import Path
from django.core.management import call_command

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Station.settings")

class ModelMakette:
	def __init__(self,app="",model=None,name="",):
		self.app = app
		self.model = model
		self.name = name

	def __repr__(self):
		return self.name

def get_custom_apps():
	excludes_app = ["hubIA","maketteur","autograph","easylife","desidis",]
	base_dir = settings.BASE_DIR.resolve()  # Répertoire racine du projet
	custom_apps = []

	for app_config in apps.get_app_configs():
		try:
			app_path = Path(app_config.path).resolve()
			print(str(app_path))
			if str(app_path).startswith(str(base_dir)) and str(app_config.name) not in ["maketteur","autograph","easylife","desidis"]:
				custom_apps.append(app_config.name)
		except Exception as e:
			print(str(e))
	return custom_apps

# Create your views here.
def save_hub_model():
	nb_fields = request.POST["nb_fields"]
	nom_modele = request.POST["nom_modele"]
	
	cmds = ["# Added by Maketteur",f"class {nom_modele} ( models.Model ) : "]
	for i in range(nb_fields):
		name_field = request.POST["field_"+str(i)]
		type_field = request.POST["field_"+str(i)]
		"""
		attrs_fields = request.POST["attrs_"+str(i)]
		if attrs_fields not in ["",None] :
			pass
		"""
		cmds.append( f"\t{name_field} = models.{type_field}(blank = True, null=True)" )
		
def index(request):
	call_command('makemigrations')
	call_command('migrate')

	template = "maketteur/index.html"
	context = dict()
	list_apps = get_custom_apps()
	object_apps_list = list()
	for a in list_apps:
		print(str(a))
		if str(a) == "hubIA":
			continue
		tmp = {"app":str(a),"models":list()}
		for md in apps.get_app_config(a).get_models():
			tmp["models"].append( ModelMakette(a,md,md.__name__) )
		object_apps_list.append(tmp)

	#hub_models = apps.get_app_config('hub').get_models()
	context["list_apps"] = list_apps
	context["object_apps_list"] = object_apps_list
	context["link"] = 1
	return render(request,template,context)
	
def index_class(request):
	template = "maketteur/class_index.html"
	list_apps = get_custom_apps()
	context = {
	"list_apps":list_apps
	}
	return render(request,template,context)
	
def index_links(request):
	template = "maketteur/linker_index.html"
	context = dict()
	context["link"] = 2
	return render(request,template,context)
	
def index_modules(request):
	template = "maketteur/modules_index.html"
	list_apps = get_custom_apps()
	context = {
	"list_apps":list_apps
	}
	context["link"] = 0
	return render(request,template,context)

def auto_fields_index(request):
	template = "maketteur/auto_fields_index.html"
	context = dict()
	return render(request,template,context)

def new_class(request):
	template = "maketteur/auto_fields_index.html"
	context = dict()
	modeles_fields = [
		"models.CharField",
		"models.IntegerField",
		"models.DecimalField",
		"models.TextField",
		"models.DateTimeField",
		"models.FileField",
		"models.ImageField",
		"models.BooleanField"
	]

	modele_name    = request.POST["modele_name"]
	modele_type    = request.POST["modele_type"]
	modele_str_    = request.POST["modele_str_"]
	modele_classes = request.POST["modele_classes"].split("!$!")

	# CREATION DE LA CLASS
	#=================================================================================
	to_write = f"\nclass {modele_name.capitalize()} ( models.Model ):\n"
	for m_cls in modele_classes[:-1]:
		attr = m_cls.split("!:!") 
		if attr[2] == "1":
			modeles_blank = "blank = True, null = True"
		else:
			modeles_blank = ""
		# Default Parameters, gonna be changed in the future
		if attr[1] == "0":
			modeles_blank += ",max_length = 128"
		elif attr[1] == "2":
			modeles_blank += ",decimal_places = 4, max_digits = 18"

		to_write += f"\t{attr[0]} = {modeles_fields[ int( attr[1] ) ]}({modeles_blank})\n"
	to_write += f"\tdef __str__(self):\n\t\treturn self.{modele_str_}\n"
	# =================================================================================

	file = open("hub/models.py","a")
	file.write(to_write)
	file.close()
	file = open("hub/admin.py","a")
	file.write(f"admin.site.register({modele_name.capitalize()})\n")
	file.close()

	call_command('makemigrations')
	#call_command('migrate')

	messages.success(request, f"Le Modele {modele_name} a ete ajoute dans votre Hub.")

	return redirect("/maketteur/")

def delete_class(request):
	modele_name = request.POST["modele_name"]

def new_module(request):
	app_name = request.POST["module_name"].lower()
	module_logic = ""
	module_img = ""#request.POST["module_img"]
	os.system(f"python3 manage.py startapp {app_name}")

	settings_file = os.path.join("Station/", "settings.py")
	with open(settings_file, 'r') as file:
		content = file.read()
	if app_name in content:
		#print(f"L'app '{app_name}' est déjà dans INSTALLED_APPS.")
		pass

	# Insertion intelligente dans INSTALLED_APPS
	new_line = f"    '{app_name}',\n"
	updated = content.replace("INSTALLED_APPS = [", f"INSTALLED_APPS = [\n{new_line}")
	with open(settings_file, 'w') as file:
		file.write(updated)

	return redirect("/maketteur/")



def delete_module(request):
	pass

def new_link(request):
	if request.method == 'POST':
		source_model = request.POST.get("source_model")  # ex: Article
		target_model = request.POST.get("target_model")  # ex: Auteur
		relation_type = request.POST.get("relation_type", "ForeignKey")  # FK | O2O | M2M
		related_name = request.POST.get("related_name", "")  # facultatif

		if not source_model or not target_model or relation_type not in ["ForeignKey", "OneToOneField", "ManyToManyField"]:
			return JsonResponse({"error": "Paramètres invalides ou manquants."}, status=400)

		# Supposons que l'app a le même nom que le modèle source en minuscule (améliorable)
		app_name = source_model.lower()
		model_file_path = os.path.join(settings.BASE_DIR, app_name, "models.py")

		if not os.path.exists(model_file_path):
			return JsonResponse({"error": f"Fichier models.py introuvable pour l'app '{app_name}'."}, status=404)

		try:
			with open(model_file_path, "r") as f:
				lines = f.readlines()

			# Rechercher la classe source_model
			class_index = next(i for i, l in enumerate(lines) if f"class {source_model}(" in l)

			# Ajouter l'import models si absent
			if "from django.db import models" not in "".join(lines):
				lines.insert(0, "from django.db import models\n")

			# Nom du champ relationnel (ex: auteur pour target_model=Auteur)
			field_name = target_model.lower()

			# Préparer la ligne du champ
			relation_map = {
				"ForeignKey": f"models.ForeignKey('{target_model}', on_delete=models.CASCADE",
				"OneToOneField": f"models.OneToOneField('{target_model}', on_delete=models.CASCADE",
				"ManyToManyField": f"models.ManyToManyField('{target_model}'"
			}

			field_line = f"    {field_name} = {relation_map[relation_type]}"
			if related_name and relation_type != "ManyToManyField":
				field_line += f", related_name='{related_name}'"
			elif related_name and relation_type == "ManyToManyField":
				field_line += f", related_name='{related_name}'"
			field_line += ")\n"

			# Trouver où insérer dans la classe
			insert_index = class_index + 1
			while insert_index < len(lines) and not lines[insert_index].strip().startswith("class "):
				insert_index += 1
			lines.insert(insert_index, field_line)

			# Réécrire models.py
			with open(model_file_path, "w") as f:
				f.writelines(lines)

			# Lancer les migrations
			subprocess.run(["python", "manage.py", "makemigrations", app_name])
			subprocess.run(["python", "manage.py", "migrate", app_name])

			return JsonResponse({"message": f"{relation_type} vers {target_model} ajoutée avec succès à {source_model}."})

		except Exception as e:
			return JsonResponse({"error": str(e)}, status=500)

	return JsonResponse({"error": "Méthode non autorisée."}, status=405)