import re
from users.models import Users
from django.contrib.auth.hashers import check_password


class PasswordValidator:
    def __init__(self, new_password, confirm_password, old_password=None):
        self.new_password = new_password
        self.confirm_password = confirm_password
        self.old_password = old_password

    def validate_password_similarity(self):
        if self.old_password:
            if self.old_password == self.new_password:
                raise Exception("New password cannot be the same as the old password.")

            if self.old_password == self.confirm_password:
                raise Exception(
                    "Confirm password cannot be the same as the old password."
                )

        if self.new_password != self.confirm_password:
            raise Exception("Passwords do not match.")

    def validate_password_length(self, required_length=8):
        if len(self.new_password) < required_length:
            raise Exception(
                f"New Password must be at least {required_length} characters long."
            )

        if len(self.confirm_password) < required_length:
            raise Exception(
                f"Confirm password must be at least {required_length} characters long."
            )

    def validate_password_complexity(
        self, contains_digits=True, contains_special_characters=True
    ):
        if contains_digits:
            new_password_has_digit = any(char.isdigit() for char in self.new_password)
            confirm_password_has_digit = any(
                char.isdigit() for char in self.confirm_password
            )

            if not new_password_has_digit:
                raise Exception("New password must contain at least one digit.")

            if not confirm_password_has_digit:
                raise Exception("Confirm password must contain at least one digit.")

        if contains_special_characters:
            new_password_has_special_characters = bool(
                re.search(r"[^a-zA-Z0-9\s]", self.new_password)
            )
            confirm_password_has_special_characters = bool(
                re.search(r"[^a-zA-Z0-9\s]", self.confirm_password)
            )

            if not new_password_has_special_characters:
                raise Exception(
                    "New password must contain at least one special character."
                )

            if not confirm_password_has_special_characters:
                raise Exception(
                    "Confirm password must contain at least one special character."
                )

    def validate_old_password(self, user: Users):
        if not self.old_password:
            raise Exception("Old password field is required.")

        is_old_password_correct = check_password(self.old_password, user.password)

        if not is_old_password_correct:
            raise Exception(
                "Invalid old password. Entered old password is not the same with the current password. Try again."
            )

    def validate_new_and_old_password_similarity(self, user: Users):
        is_new_password_same_with_old_password = check_password(
            self.new_password, user.password
        )
        is_confirm_password_same_with_old_password = check_password(
            self.confirm_password, user.password
        )

        if is_new_password_same_with_old_password:
            raise Exception("New password cannot be the same as the old password.")

        if is_confirm_password_same_with_old_password:
            raise Exception("Confirm password cannot be the same as the old password.")
