# customermanagement/service.py
from multiprocessing import context
from pyexpat.errors import messages
from urllib import request
from django.contrib.auth.hashers import make_password
from django.db import transaction
from django.core.exceptions import ValidationError
from django.shortcuts import render
from django.apps import apps
from django.db import transaction, models
from django.db.models import Q
from buyers.models import CustomerBuyer
from core.models import AppSettings, DeviceMoistureThreshold
from core.utils import get_or_create_app_settings
from fieldmanagement.models import CustomerField
from mydevicemanagement.models import CustomerDevice, MyDeviceMoistureThreshold, shareDevice
from results.models import Result
from .models import Customer, EmailOTP, Language, PasswordResetToken
from usermanagement.models import UserProfile
from django.core.exceptions import ObjectDoesNotExist

DEFAULT_BUYER_NAME = "Buyer 1"
DEFAULT_FIELD_NAME = "Field 1"
DEFAULT_GPS_LAT ="60.340162"
DEFAULT_GPS_LONG ="25.007860"

def hash_password(raw_password: str) -> str:
    
    if not raw_password:
        raise ValidationError("Password is required.")
    return make_password(raw_password)


@transaction.atomic
def create_customer_from_post(post_data, created_user) -> Customer:

    first_name = (post_data.get("first_name") or "").strip().upper()
    last_name  = (post_data.get("last_name")  or "").strip().upper()
    email      = (post_data.get("email")      or "").strip()
    mobile     = (post_data.get("mobile")     or "").strip()
    raw_pwd    = (post_data.get("password")   or "").strip()
    lang_id    = (post_data.get("language")   or "").strip()

    if not first_name:
        raise ValidationError("First name is required.")
    if not last_name:
        raise ValidationError("Last name is required.")
    if not email:
        raise ValidationError("Email is required.")
    if not mobile:
        raise ValidationError("Mobile is required.")

    hashed_pwd = hash_password(raw_pwd)
    language_obj = None
    if lang_id:
        try:
            language_obj = Language.objects.get(pk=int(lang_id))
        except (ValueError, ObjectDoesNotExist):
            messages.error(request, "Selected language not found.")
            return render(request, 'add-customer.html', context)
        
        
    customer = Customer.objects.create(
        first_name=first_name,
        last_name=last_name,
        email=email,
        mobile=mobile,
        password=hashed_pwd,        # <- hashed before saving
        language=language_obj,      # <- real FK instance (or None)
        created_user=created_user,
        updated_user=created_user,
        privacy_policy_version = "v1.0",
        privacy_policy_accepted = True,
    )
    return customer

def ensure_default_buyer_and_field(customer: Customer):
    buyer, _ = CustomerBuyer.objects.get_or_create(
        customer=customer,
        name=DEFAULT_BUYER_NAME,
        defaults={"description": ""},
    )

    field_obj, _ = CustomerField.objects.get_or_create(
        customer=customer,
        field_name=DEFAULT_FIELD_NAME,
        gps_lat = DEFAULT_GPS_LAT,
        gps_long = DEFAULT_GPS_LONG,
        defaults={"description": "",},
        
    )

    # ⬇️ also persist to AppSettings (idempotent – won’t overwrite if already set)
    settings = get_or_create_app_settings(customer)

    # only set if empty; change to unconditional if you always want to overwrite
    if not (settings.default_buyer or {}).get("id"):
        settings.default_buyer = {"id": buyer.id, "name": buyer.name}

    if not (settings.default_field or {}).get("id"):
        settings.default_field = {"id": field_obj.id, "name": field_obj.field_name}

    settings.save(update_fields=["default_buyer", "default_field", "updated_at"])
    
    
def delete_customer_with_related_data(customer: Customer):
    with transaction.atomic():
        devices_qs = CustomerDevice.objects.filter(customer=customer)
        fields_qs = CustomerField.objects.filter(customer=customer)
        buyers_qs = CustomerBuyer.objects.filter(customer=customer)

        results_qs = Result.objects.filter(
            Q(device__customer=customer) |
            Q(field__customer=customer) |
            Q(buyer__customer=customer)
        )

        app_settings_qs = AppSettings.objects.filter(customer_user=customer)
        share_qs = shareDevice.objects.filter(shared_with=customer)
        core_thresh_qs = DeviceMoistureThreshold.objects.filter(customer_device__customer=customer)
        mydevice_thresh_qs = MyDeviceMoistureThreshold.objects.filter(device__customer=customer)
        otp_qs = EmailOTP.objects.filter(customer=customer)
        reset_qs = PasswordResetToken.objects.filter(customer=customer)

        # Generic sweep for any other FK -> Customer models
        generic_qsets = []
        for model in apps.get_models():
            for field in model._meta.get_fields():
                if isinstance(field, models.ForeignKey) and getattr(field.remote_field, "model", None) is Customer:
                    try:
                        qs = model.objects.filter(**{field.name: customer})
                        if qs.exists():
                            generic_qsets.append(qs)
                    except Exception:
                        pass

        # Delete leaf records first
        core_thresh_qs.delete()
        mydevice_thresh_qs.delete()

        # Delete dependent rows
        results_qs.delete()
        share_qs.delete()
        app_settings_qs.delete()
        otp_qs.delete()
        reset_qs.delete()

        # Generic sweep
        for qs in generic_qsets:
            try:
                qs.delete()
            except Exception:
                pass

        # Primary children
        buyers_qs.delete()
        fields_qs.delete()
        devices_qs.delete()

        # Finally customer
        customer.delete()