from django.contrib.auth.models import (
    AbstractBaseUser,
    BaseUserManager,
    PermissionsMixin,
)
from django.db import models
from django.utils.translation import gettext_lazy as _

from servala.core import odoo
from servala.core.models.mixins import ServalaModelMixin


class UserManager(BaseUserManager):
    """
    Use a separate model manager, as we do not have a username field.
    """

    use_in_migrations = True

    class Meta:
        verbose_name = _("User manager")
        verbose_name_plural = _("User managers")

    def create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError("Please provide an email address.")
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password, **extra_fields):
        """Create and save a SuperUser with the given email and password."""
        extra_fields["is_staff"] = True
        extra_fields["is_superuser"] = True
        return self.create_user(email, password, **extra_fields)


class User(ServalaModelMixin, PermissionsMixin, AbstractBaseUser):
    """The Django model provides a password and last_login field."""

    objects = UserManager()

    email = models.EmailField(unique=True, verbose_name=_("Email address"))
    first_name = models.CharField(
        max_length=30, blank=True, verbose_name=_("First name")
    )
    last_name = models.CharField(max_length=30, blank=True, verbose_name=_("Last name"))
    company = models.CharField(max_length=100, blank=True, verbose_name=_("Company"))

    is_staff = models.BooleanField(
        default=False,
        verbose_name=_("Is staff"),
        help_text=_("Staff users can log into this admin site."),
    )
    is_superuser = models.BooleanField(
        default=False,
        verbose_name=_("Is superuser"),
        help_text=_(
            "Superusers have all permissions without explicitly assigning them. Use with caution."
        ),
    )

    EMAIL_FIELD = "email"
    USERNAME_FIELD = "email"

    class Meta:
        verbose_name = _("User")
        verbose_name_plural = _("Users")

    def __str__(self):
        return f"{self.first_name} {self.last_name}".strip() or self.email

    def normalize_username(self, username):
        return super().normalize_username(username).strip().lower()

    def get_odoo_contact(self, organization):
        if (
            not organization.billing_entity
            or not organization.billing_entity.odoo_company_id
        ):
            return
        result = odoo.CLIENT.search_read(
            model="res.partner",
            domain=[
                ("is_company", "=", False),
                ("type", "=", "contact"),
                ("email", "ilike", self.email),
                ("parent_id", "=", organization.billing_entity.odoo_company_id),
            ],
            fields=odoo.ADDRESS_FIELDS,
        )
        if result:
            return result[0]

    def get_or_create_odoo_contact(self, organization):
        if (
            not organization.billing_entity
            or not organization.billing_entity.odoo_company_id
        ):
            return None

        if existing_contact := self.get_odoo_contact(organization):
            return existing_contact["id"]

        partner_data = {
            "name": f"{self.first_name} {self.last_name}".strip() or self.email,
            "email": self.email,
            "is_company": False,
            "type": "contact",
            "parent_id": organization.billing_entity.odoo_company_id,
        }

        contact_id = odoo.CLIENT.execute("res.partner", "create", [partner_data])
        return contact_id
