from decimal import Decimal

from dishka import FromDishka
from dishka.integrations.fastapi import DishkaRoute
from fastapi import APIRouter
from pydantic import BaseModel, Field

from template_project.application.resume.entity import ResumeId
from template_project.application.resume.interactors.predict_model import (
    PredictModelInteractor,
    PredictSalaryRequest,
    VacancyInput,
)

router = APIRouter(route_class=DishkaRoute, tags=["Prediction"])


class VacancyInputModel(BaseModel):
    vacancy_id: str = Field(description="Vacancy ID", examples=["vacancy_123"])
    from_salary: Decimal = Field(description="Minimum salary", examples=[Decimal(100000)])
    to_salary: Decimal = Field(description="Maximum salary", examples=[Decimal(150000)])
    key_skills: list[str] = Field(description="List of key skills", examples=[["Python", "FastAPI", "PostgreSQL"]])
    resume_similarity: float = Field(
        ge=0.0, le=1.0, description="Resume similarity score (0.0 to 1.0)", examples=[0.85]
    )

    model_config = {
        "json_schema_extra": {
            "example": {
                "vacancy_id": "vacancy_123",
                "from_salary": "100000",
                "to_salary": "150000",
                "key_skills": ["Python", "FastAPI", "PostgreSQL"],
                "resume_similarity": 0.85,
            }
        }
    }


class PredictSalaryRequestModel(BaseModel):
    resume_id: ResumeId = Field(description="Resume ID", examples=["01234567-89ab-cdef-0123-456789abcdef"])
    key_skills: list[str] = Field(
        description="List of key skills from resume", examples=[["Python", "FastAPI", "PostgreSQL"]]
    )
    vacancies: list[VacancyInputModel] = Field(description="List of relevant vacancies", examples=[[]], min_length=0)

    model_config = {
        "json_schema_extra": {
            "example": {
                "resume_id": "01234567-89ab-cdef-0123-456789abcdef",
                "key_skills": ["Python", "FastAPI", "PostgreSQL"],
                "vacancies": [
                    {
                        "vacancy_id": "vacancy_123",
                        "from_salary": "100000",
                        "to_salary": "150000",
                        "key_skills": ["Python", "FastAPI", "PostgreSQL", "Docker"],
                        "resume_similarity": 0.85,
                    }
                ],
            }
        }
    }


class PredictSalaryResponseModel(BaseModel):
    salary_from: Decimal = Field(description="Minimum predicted salary", examples=[Decimal(100000)])
    salary_to: Decimal = Field(description="Maximum predicted salary", examples=[Decimal(150000)])
    recommended_skills: list[str] = Field(
        description="Top 3 recommended skills", examples=[["Kubernetes", "Redis", "Docker"]]
    )

    model_config = {
        "json_schema_extra": {
            "example": {
                "salary_from": "100000",
                "salary_to": "150000",
                "recommended_skills": ["Kubernetes", "Redis", "Docker"],
            }
        }
    }


@router.post(
    "/predict",
    summary="Predict salary and recommend skills",
    description="Predict salary range and recommend skills based on resume and relevant vacancies",
    responses={
        200: {
            "description": "Salary prediction and skills recommendation generated successfully",
            "model": PredictSalaryResponseModel,
        },
    },
)
async def predict(
    request: PredictSalaryRequestModel,
    interactor: FromDishka[PredictModelInteractor],
) -> PredictSalaryResponseModel:
    vacancy_inputs = [
        VacancyInput(
            vacancy_id=vacancy.vacancy_id,
            from_salary=vacancy.from_salary,
            to_salary=vacancy.to_salary,
            key_skills=vacancy.key_skills,
            resume_similarity=vacancy.resume_similarity,
        )
        for vacancy in request.vacancies
    ]

    predict_request = PredictSalaryRequest(
        resume_id=request.resume_id,
        key_skills=request.key_skills,
        vacancies=vacancy_inputs,
    )

    response = await interactor.execute(predict_request)

    return PredictSalaryResponseModel(
        salary_from=response.salary_from,
        salary_to=response.salary_to,
        recommended_skills=response.recommended_skills,
    )
