from datetime import datetime
from typing import List, Optional
from uuid import UUID
from dataclasses import field

from pydantic import BaseModel

from ..util.enum import to_enum
from ..vacancies.models import Feed, Vacancy as VacancyModel, SalaryFrequency, RemoteType


class VacancyLocation(BaseModel):
    zip_code: str | None = None
    city: str | None = None
    address: str | None = None
    state: str | None = None
    country: str | None = None


class Salary(BaseModel):
    min: float | None = None
    max: float | None = None
    currency: str = "EUR"
    frequency: SalaryFrequency = "month"


class Hours(BaseModel):
    min: int = 0
    max: int = 40
    fte: float = 1.0


class ContactDetails(BaseModel):
    email: str | None = None
    first_name: str | None = None
    last_name: str | None = None
    phone_number: str | None = None
    role: str | None = None


class VacancyData(BaseModel):

    # Required fields
    reference_number: str
    requisition_id: str
    title: str
    description: str
    job_site_url: str
    company_name: str
    publish_date: datetime | None = None
    category: List[str] = field(default_factory=list)
    experience: List[str] = field(default_factory=list)
    education: List[str] = field(default_factory=list)

    # Connected data
    hours: Hours = field(default_factory=Hours)
    location: VacancyLocation = field(default_factory=VacancyLocation)
    salary: Salary = field(default_factory=Salary)
    recruiter: ContactDetails = field(default_factory=ContactDetails)

    # Optional fields
    status: str | None = None
    parent_company_name: str | None = None
    remote_type: RemoteType | None = None
    expiration_date: datetime | None = None
    last_updated_date: datetime | None = None

    def to_model(self, feed: Feed):
        return VacancyModel(
            feed_id=feed.id,
            organization=feed.organization,
            reference_number=self.reference_number,
            requisition_id=self.requisition_id,
            title=self.title,
            description=self.description,
            status=self.status,
            job_site_url=self.job_site_url,
            company_name=self.company_name,
            parent_company_name=self.parent_company_name,
            remote_type=self.remote_type.value if self.remote_type else None,
            publish_date=self.publish_date,
            expiration_date=self.expiration_date,
            last_updated_date=self.last_updated_date,
            category=self.category,
            experience=self.experience,
            education=self.education,
            hours_fte=self.hours.fte,
            hours_min=self.hours.min,
            hours_max=self.hours.max,
            location_address=self.location.address,
            location_zipcode=self.location.zip_code,
            location_city=self.location.city,
            location_state=self.location.state,
            location_country=self.location.country,
            salary_min=self.salary.min,
            salary_max=self.salary.max,
            salary_currency=self.salary.currency,
            salary_frequency=self.salary.frequency.value if self.salary.frequency else SalaryFrequency.MONTH,
            recruiter_first_name=self.recruiter.first_name,
            recruiter_last_name=self.recruiter.last_name,
            recruiter_phone_number=self.recruiter.phone_number,
            recruiter_email=self.recruiter.email,
            recruiter_role=self.recruiter.role,
        )

class Vacancy(VacancyData):
    id: UUID
    created_at: datetime
    updated_at: Optional[datetime]
    organization: UUID

    @classmethod
    def from_model(cls: "Vacancy", model: VacancyModel) -> "Vacancy":
        hours = Hours(
            min=model.hours_min,
            max=model.hours_max,
            fte=model.hours_fte,
        )

        location = VacancyLocation(
            address=getattr(model, "location_address", None),
            zip_code=getattr(model, "location_zipcode", None),
            city=getattr(model, "location_city", None),
            state=getattr(model, "location_state", None),
            country=getattr(model, "location_country", None),
        )

        salary = Salary(
            min=getattr(model, "salary_min", None),
            max=getattr(model, "salary_max", None),
            currency=getattr(model, "salary_currency", "EUR") or "EUR",
            frequency=to_enum(SalaryFrequency, getattr(model, "salary_frequency", SalaryFrequency.MONTH) or SalaryFrequency.MONTH),
        )

        recruiter = ContactDetails(
            first_name=getattr(model, "recruiter_first_name", None),
            last_name=getattr(model, "recruiter_last_name", None),
            phone_number=getattr(model, "recruiter_phone_number", None),
            email=getattr(model, "recruiter_email", None),
            role=getattr(model, "recruiter_role", None),
        )

        remote_type = to_enum(RemoteType, getattr(model, "remote_type", None))

        return cls(
            organization=getattr(model, "organization", None),
            id=model.id,
            created_at=model.created_at,
            updated_at=model.updated_at,

            reference_number=model.reference_number,
            requisition_id=model.requisition_id,
            title=model.title,
            description=model.description,
            job_site_url=model.job_site_url,
            company_name=model.company_name,
            publish_date=model.publish_date,
            category=list(model.category or []),
            experience=list(model.experience or []),
            education=list(model.education or []),

            hours=hours,
            location=location,
            salary=salary,
            recruiter=recruiter,

            status=getattr(model, "status", None),
            parent_company_name=getattr(model, "parent_company_name", None),
            remote_type=remote_type,
            expiration_date=getattr(model, "expiration_date", None),
            last_updated_date=getattr(model, "last_updated_date", None),
        )