from datetime import UTC
from decimal import Decimal
from uuid import UUID, uuid4

from template_project.application.common.enums import EducationGrade, ExperienceType
from template_project.application.resume.entity import (
    Resume,
    ResumeEducation,
    ResumeEmbedding,
    ResumeExperience,
    ResumeId,
    ResumePrediction,
    ResumeProject,
)
from template_project.application.user.entity import UserId


def test_resume_factory_creates_valid_resume() -> None:
    user_id = UserId(uuid4())
    resume = Resume.factory(
        user_id=user_id,
        position="Python Developer",
        location="Moscow",
        about_me="Experienced developer",
        key_skills=["Python", "FastAPI"],
        experience_type=ExperienceType.BETWEEN_3_AND_6,
    )

    assert isinstance(resume.id, UUID)
    assert resume.user_id == user_id
    assert resume.position == "Python Developer"
    assert resume.location == "Moscow"
    assert resume.about_me == "Experienced developer"
    assert resume.key_skills == ["Python", "FastAPI"]
    assert resume.experience_type == ExperienceType.BETWEEN_3_AND_6
    assert resume.down_resume_id is None
    assert resume.up_resume_id is None
    assert resume.deleted_at is None
    assert resume.created_at.tzinfo == UTC


def test_resume_factory_with_history_links() -> None:
    user_id = UserId(uuid4())
    old_resume_id = ResumeId(uuid4())

    resume = Resume.factory(
        user_id=user_id,
        position="Python Developer",
        location="Moscow",
        about_me="Updated",
        key_skills=["Python"],
        experience_type=ExperienceType.BETWEEN_3_AND_6,
        down_resume_id=old_resume_id,
    )

    assert resume.down_resume_id == old_resume_id


def test_resume_embedding_factory_creates_valid_embedding() -> None:
    resume_id = ResumeId(uuid4())
    vector = [0.1, 0.2, 0.3, 0.4, 0.5]

    embedding = ResumeEmbedding.factory(
        resume_id=resume_id,
        vector=vector,
    )

    assert isinstance(embedding.id, UUID)
    assert embedding.resume_id == resume_id
    assert embedding.vector == vector
    assert embedding.deleted_at is None
    assert embedding.created_at.tzinfo == UTC


def test_resume_embedding_vector_dimension() -> None:
    resume_id = ResumeId(uuid4())
    vector = [0.1] * 384

    embedding = ResumeEmbedding.factory(
        resume_id=resume_id,
        vector=vector,
    )

    assert len(embedding.vector) == 384
    assert all(isinstance(x, float) for x in embedding.vector)


def test_resume_prediction_factory_creates_valid_prediction() -> None:
    resume_id = ResumeId(uuid4())

    prediction = ResumePrediction.factory(
        resume_id=resume_id,
        from_salary=Decimal(100000),
        to_salary=Decimal(150000),
        recommended_skills=["Kubernetes", "Docker"],
    )

    assert isinstance(prediction.id, UUID)
    assert prediction.resume_id == resume_id
    assert prediction.from_salary == Decimal(100000)
    assert prediction.to_salary == Decimal(150000)
    assert prediction.recommended_skills == ["Kubernetes", "Docker"]
    assert prediction.deleted_at is None
    assert prediction.created_at.tzinfo == UTC


def test_resume_prediction_salary_order() -> None:
    resume_id = ResumeId(uuid4())

    prediction = ResumePrediction.factory(
        resume_id=resume_id,
        from_salary=Decimal(100000),
        to_salary=Decimal(150000),
        recommended_skills=[],
    )

    assert prediction.from_salary <= prediction.to_salary


def test_resume_prediction_empty_recommended_skills() -> None:
    resume_id = ResumeId(uuid4())

    prediction = ResumePrediction.factory(
        resume_id=resume_id,
        from_salary=Decimal(100000),
        to_salary=Decimal(150000),
        recommended_skills=[],
    )

    assert prediction.recommended_skills == []


def test_resume_experience_positive_duration() -> None:
    resume_id = ResumeId(uuid4())

    experience = ResumeExperience.factory(
        resume_id=resume_id,
        place="Company",
        description="Work",
        months_duration=12,
    )

    assert experience.months_duration > 0


def test_resume_key_skills_empty_list() -> None:
    user_id = UserId(uuid4())

    resume = Resume.factory(
        user_id=user_id,
        position="Developer",
        location="Moscow",
        about_me="Test",
        key_skills=[],
        experience_type=ExperienceType.NO_EXPERIENCE,
    )

    assert resume.key_skills == []


def test_resume_experience_factory_creates_valid_experience() -> None:
    resume_id = ResumeId(uuid4())

    experience = ResumeExperience.factory(
        resume_id=resume_id,
        place="T-bank",
        description="Backend development",
        months_duration=24,
    )

    assert isinstance(experience.id, UUID)
    assert experience.resume_id == resume_id
    assert experience.place == "T-bank"
    assert experience.description == "Backend development"
    assert experience.months_duration == 24
    assert experience.months_duration > 0
    assert experience.deleted_at is None
    assert experience.created_at.tzinfo == UTC


def test_resume_education_factory_creates_valid_education() -> None:
    resume_id = ResumeId(uuid4())

    education = ResumeEducation.factory(
        resume_id=resume_id,
        place="University",
        grade=EducationGrade.BACHELOR,
        specialization="Computer Science",
        description="Optional description",
    )

    assert isinstance(education.id, UUID)
    assert education.resume_id == resume_id
    assert education.place == "University"
    assert education.grade == EducationGrade.BACHELOR
    assert education.specialization == "Computer Science"
    assert education.description == "Optional description"
    assert education.deleted_at is None
    assert education.created_at.tzinfo == UTC


def test_resume_education_factory_without_description() -> None:
    resume_id = ResumeId(uuid4())

    education = ResumeEducation.factory(
        resume_id=resume_id,
        place="University",
        grade=EducationGrade.MASTER,
        specialization="Data Science",
    )

    assert education.description is None


def test_resume_project_factory_creates_valid_project() -> None:
    resume_id = ResumeId(uuid4())

    project = ResumeProject.factory(
        resume_id=resume_id,
        name="ML Service",
        description="Machine learning service",
    )

    assert isinstance(project.id, UUID)
    assert project.resume_id == resume_id
    assert project.name == "ML Service"
    assert project.description == "Machine learning service"
    assert project.deleted_at is None
    assert project.created_at.tzinfo == UTC
