from __future__ import annotations

from typing import Dict, List, Optional

from .agents import (
    InterviewCoachAgent,
    JobDescriptionParserAgent,
    PortfolioCoachAgent,
    ResumeTailorAgent,
)
from .models import (
    CandidateProfile,
    InterviewSession,
    JobDescription,
    PortfolioSuggestion,
    TailoredCoverLetter,
    TailoredResume,
)


class JobSearchOrchestrator:
    """
    High-level multi-agent orchestrator for the job search workflow.
    """

    def __init__(
        self,
        jd_parser: Optional[JobDescriptionParserAgent] = None,
        resume_tailor: Optional[ResumeTailorAgent] = None,
        portfolio_coach: Optional[PortfolioCoachAgent] = None,
        interview_coach: Optional[InterviewCoachAgent] = None,
    ) -> None:
        self.jd_parser = jd_parser or JobDescriptionParserAgent()
        self.resume_tailor = resume_tailor or ResumeTailorAgent()
        self.portfolio_coach = portfolio_coach or PortfolioCoachAgent()
        self.interview_coach = interview_coach or InterviewCoachAgent()

    # --- end-to-end flows ---

    def full_pipeline(
        self,
        raw_job_description: str,
        candidate: CandidateProfile,
        *,
        url: Optional[str] = None,
        title_override: Optional[str] = None,
    ) -> Dict[str, object]:
        """
        Run the full multi-agent pipeline:
        - Parse JD
        - Tailor resume + cover letter
        - Suggest portfolio tweaks
        - Prepare mock interview session (questions only)
        """
        job = self.jd_parser.parse(raw_job_description, url=url, title_override=title_override)
        tailored_resume = self.resume_tailor.tailor_resume(candidate, job)
        tailored_cover = self.resume_tailor.tailor_cover_letter(candidate, job)
        portfolio_suggestions = self.portfolio_coach.suggest(candidate, job)
        interview_session = self.interview_coach.create_session(candidate, job)

        return {
            "job": job,
            "tailored_resume": tailored_resume,
            "tailored_cover_letter": tailored_cover,
            "portfolio_suggestions": portfolio_suggestions,
            "interview_session": interview_session,
        }

    # --- convenience accessors for individual agents ---

    def parse_job(self, raw_job_description: str) -> JobDescription:
        return self.jd_parser.parse(raw_job_description)

    def full_pipeline_for_job(
        self, job_hint: JobDescription, candidate: CandidateProfile
    ) -> Dict[str, object]:
        """
        Accepts a JobDescription hint from a source (raw_text + title/url),
        then parses it and runs tailoring independently.
        """
        job = self.jd_parser.parse(
            job_hint.raw_text,
            url=job_hint.url,
            title_override=job_hint.title,
        )
        tailored_resume = self.resume_tailor.tailor_resume(candidate, job)
        tailored_cover = self.resume_tailor.tailor_cover_letter(candidate, job)
        portfolio_suggestions = self.portfolio_coach.suggest(candidate, job)
        interview_session = self.interview_coach.create_session(candidate, job)
        return {
            "job": job,
            "tailored_resume": tailored_resume,
            "tailored_cover_letter": tailored_cover,
            "portfolio_suggestions": portfolio_suggestions,
            "interview_session": interview_session,
        }

    def tailor_resume(
        self, candidate: CandidateProfile, job: JobDescription
    ) -> TailoredResume:
        return self.resume_tailor.tailor_resume(candidate, job)

    def tailor_cover_letter(
        self, candidate: CandidateProfile, job: JobDescription
    ) -> TailoredCoverLetter:
        return self.resume_tailor.tailor_cover_letter(candidate, job)

    def suggest_portfolio(
        self, candidate: CandidateProfile, job: JobDescription
    ) -> List[PortfolioSuggestion]:
        return self.portfolio_coach.suggest(candidate, job)

    def start_mock_interview(
        self, candidate: CandidateProfile, job: JobDescription
    ) -> InterviewSession:
        return self.interview_coach.create_session(candidate, job)

    def review_mock_interview(
        self, session: InterviewSession, answers: List[str]
    ) -> InterviewSession:
        return self.interview_coach.review_answers(session, answers)

    # --- serialization helpers ---

    @staticmethod
    def serialize_interview(session: InterviewSession) -> Dict:
        return session.model_dump()

