from datetime import UTC, datetime
from decimal import Decimal
from typing import NewType, Self
from uuid import UUID

from uuid_utils.compat import uuid7

from template_project.application.common.entity import Entity, to_entity
from template_project.application.common.enums import EducationGrade, ExperienceType
from template_project.application.user.entity import UserId

ResumeId = NewType("ResumeId", UUID)
ResumeEmbeddingId = NewType("ResumeEmbeddingId", UUID)
ResumePredictionId = NewType("ResumePredictionId", UUID)
ResumeExperienceId = NewType("ResumeExperienceId", UUID)
ResumeEducationId = NewType("ResumeEducationId", UUID)
ResumeProjectId = NewType("ResumeProjectId", UUID)


@to_entity
class Resume(Entity[ResumeId]):
    user_id: UserId
    position: str
    location: str
    about_me: str
    key_skills: list[str]
    experience_type: ExperienceType
    down_resume_id: ResumeId | None = None
    up_resume_id: ResumeId | None = None

    @classmethod
    def factory(
        cls,
        user_id: UserId,
        position: str,
        location: str,
        about_me: str,
        key_skills: list[str],
        experience_type: ExperienceType,
        down_resume_id: ResumeId | None = None,
        up_resume_id: ResumeId | None = None,
    ) -> Self:
        return cls(
            id=ResumeId(uuid7()),
            created_at=datetime.now(tz=UTC),
            user_id=user_id,
            position=position,
            location=location,
            about_me=about_me,
            key_skills=key_skills,
            experience_type=experience_type,
            down_resume_id=down_resume_id,
            up_resume_id=up_resume_id,
        )


@to_entity
class ResumeEmbedding(Entity[ResumeEmbeddingId]):
    resume_id: ResumeId
    vector: list[float]

    @classmethod
    def factory(
        cls,
        resume_id: ResumeId,
        vector: list[float],
    ) -> Self:
        return cls(
            id=ResumeEmbeddingId(uuid7()),
            created_at=datetime.now(tz=UTC),
            resume_id=resume_id,
            vector=vector,
        )


@to_entity
class ResumePrediction(Entity[ResumePredictionId]):
    resume_id: ResumeId
    from_salary: Decimal
    to_salary: Decimal
    recommended_skills: list[str]

    @classmethod
    def factory(
        cls,
        resume_id: ResumeId,
        from_salary: Decimal,
        to_salary: Decimal,
        recommended_skills: list[str],
    ) -> Self:
        return cls(
            id=ResumePredictionId(uuid7()),
            created_at=datetime.now(tz=UTC),
            resume_id=resume_id,
            from_salary=from_salary,
            to_salary=to_salary,
            recommended_skills=recommended_skills,
        )


@to_entity
class ResumeExperience(Entity[ResumeExperienceId]):
    resume_id: ResumeId
    place: str
    description: str
    months_duration: int

    @classmethod
    def factory(
        cls,
        resume_id: ResumeId,
        place: str,
        description: str,
        months_duration: int,
    ) -> Self:
        return cls(
            id=ResumeExperienceId(uuid7()),
            created_at=datetime.now(tz=UTC),
            resume_id=resume_id,
            place=place,
            description=description,
            months_duration=months_duration,
        )


@to_entity
class ResumeEducation(Entity[ResumeEducationId]):
    resume_id: ResumeId
    place: str
    grade: EducationGrade
    specialization: str
    description: str | None = None

    @classmethod
    def factory(
        cls,
        resume_id: ResumeId,
        place: str,
        grade: EducationGrade,
        specialization: str,
        description: str | None = None,
    ) -> Self:
        return cls(
            id=ResumeEducationId(uuid7()),
            created_at=datetime.now(tz=UTC),
            resume_id=resume_id,
            place=place,
            grade=grade,
            specialization=specialization,
            description=description,
        )


@to_entity
class ResumeProject(Entity[ResumeProjectId]):
    resume_id: ResumeId
    name: str
    description: str

    @classmethod
    def factory(
        cls,
        resume_id: ResumeId,
        name: str,
        description: str,
    ) -> Self:
        return cls(
            id=ResumeProjectId(uuid7()),
            created_at=datetime.now(tz=UTC),
            resume_id=resume_id,
            name=name,
            description=description,
        )
