import re
from dataclasses import dataclass
from uuid import UUID, uuid4

from api.domain import DomainValidationError
from api.domain.entity import DomainEntity
from api.domain.user.model import UserId
from api.domain.value_obj import DomainValueObject


@dataclass(frozen=True)
class CompanyEmail(DomainValueObject):
    value: str

    def __post_init__(self) -> None:
        pattern = r"^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,}$"

        if not re.match(pattern, self.value):
            raise DomainValidationError("Invalid email format. Email must be in the format 'example@example.com'.")


@dataclass(frozen=True)
class CompanyName(DomainValueObject):
    value: str

    def __post_init__(self) -> None:
        if len(self.value) < 1:
            raise DomainValidationError("First name must be at least 1 character long.")
        if len(self.value) > 100:
            raise DomainValidationError("First name must be at most 100 characters long.")
        if not self.value.isalpha():
            raise DomainValidationError("First name must only contain letters.")


@dataclass(frozen=True)
class CompanyId(DomainValueObject):
    value: UUID


@dataclass(frozen=True)
class CompanyAddress(DomainValueObject):
    value: str

    def __post_init__(self) -> None:
        if len(self.value) < 1:
            raise DomainValidationError("Address must be at least 1 character long.")
        if len(self.value) > 100:
            raise DomainValidationError("Address must be at most 100 characters long.")
        if not self.value.isalpha():
            raise DomainValidationError("Address must only contain letters.")


@dataclass
class Company(DomainEntity[CompanyId]):
    name: CompanyName
    email: CompanyEmail
    address: CompanyAddress
    owner_id: UserId

    @staticmethod
    def create(name: str, email: str, address: str, owner_id: str) -> "Company":
        return Company(
            id=CompanyId(uuid4()),
            name=CompanyName(name),
            email=CompanyEmail(email),
            address=CompanyAddress(address),
            owner_id=UserId(UUID(owner_id)),
        )