"""Resumly Python SDK client -- full coverage of the Resumly API."""

from __future__ import annotations

import time
from pathlib import Path
from typing import Any, Dict, List, Optional, Union

import requests

from .exceptions import (
    AuthenticationError,
    InsufficientCreditsError,
    NotFoundError,
    RateLimitError,
    ResumlyError,
    ValidationError,
)

_DEFAULT_BASE_URL = "https://api.resumly.ai"


class ResumlyClient:
    """Official Python client for the Resumly API.

    Every user-facing endpoint in Resumly is accessible through this client.
    Authenticate with an API key created from your Resumly dashboard.

    Parameters
    ----------
    api_key : str
        Your Resumly API key (starts with ``rly_``).
    base_url : str, optional
        Override the API base URL (useful for local development).
    timeout : int, optional
        HTTP request timeout in seconds. Defaults to 180.
    max_retries : int, optional
        Auto-retry on 429 (rate limit). Defaults to 3.
    """

    def __init__(
        self,
        api_key: str,
        base_url: str = _DEFAULT_BASE_URL,
        timeout: int = 180,
        max_retries: int = 3,
    ):
        if not api_key:
            raise AuthenticationError("api_key is required")
        self._api_key = api_key
        self._base_url = base_url.rstrip("/")
        self._timeout = timeout
        self._max_retries = max_retries
        self._session = requests.Session()
        self._session.headers.update(
            {
                "X-API-Key": self._api_key,
                "Accept": "application/json",
            }
        )

    # ======================================================================
    # Internal helpers
    # ======================================================================

    def _url(self, path: str) -> str:
        return f"{self._base_url}{path}"

    def _request(self, method: str, path: str, **kwargs) -> Any:
        kwargs.setdefault("timeout", self._timeout)
        for attempt in range(self._max_retries + 1):
            resp = self._session.request(method, self._url(path), **kwargs)
            if resp.status_code == 429 and attempt < self._max_retries:
                wait = int(resp.headers.get("Retry-After", 5))
                time.sleep(min(wait, 60))
                continue
            return self._handle(resp)
        return self._handle(resp)  # last attempt

    def _handle(self, resp: requests.Response) -> Any:
        if resp.status_code == 401:
            raise AuthenticationError("Invalid or missing API key", status_code=401, response=self._json(resp))
        if resp.status_code == 403:
            msg = self._extract_message(resp, "Forbidden")
            raise InsufficientCreditsError(msg, status_code=403, response=self._json(resp))
        if resp.status_code == 404:
            msg = self._extract_message(resp, "Not found")
            raise NotFoundError(msg, status_code=404, response=self._json(resp))
        if resp.status_code == 422:
            raise ValidationError("Validation error", status_code=422, response=self._json(resp))
        if resp.status_code == 429:
            retry = resp.headers.get("Retry-After")
            raise RateLimitError(retry_after=int(retry) if retry else None, status_code=429, response=self._json(resp))
        if resp.status_code >= 400:
            msg = self._extract_message(resp, "API error")
            raise ResumlyError(msg, status_code=resp.status_code, response=self._json(resp))
        ct = resp.headers.get("Content-Type", "")
        if "application/json" in ct:
            return resp.json()
        return resp.content

    @staticmethod
    def _extract_message(resp: requests.Response, default: str) -> str:
        try:
            body = resp.json()
            detail = body.get("detail", default)
            if isinstance(detail, dict):
                return detail.get("user_message", default)
            return str(detail)
        except Exception:
            return default

    @staticmethod
    def _json(resp: requests.Response) -> Optional[dict]:
        try:
            return resp.json()
        except Exception:
            return None

    # ======================================================================
    # BASE RESUME
    # ======================================================================

    def upload_base_resume(self, file_path: Union[str, Path]) -> dict:
        """Upload a PDF or DOCX as your base resume."""
        p = Path(file_path)
        with open(p, "rb") as f:
            return self._request("POST", "/users/upload-base-resume", files={"resume_file": (p.name, f)})

    def get_base_resume(self) -> dict:
        """Get the parsed JSON of your base resume."""
        return self._request("GET", "/users/base-resume")

    def update_base_resume(self, resume_data: dict) -> dict:
        """Update your base resume with new JSON data."""
        return self._request("POST", "/users/base-resume", json=resume_data)

    def improve_base_resume(self, comments: str) -> dict:
        """Improve base resume based on feedback."""
        return self._request("POST", "/users/improve-base-resume", json={"user_comment": comments})

    def translate_base_resume(self, target_language: str) -> dict:
        """Translate base resume to a target language."""
        return self._request("POST", "/users/translate-base-resume", json={"target_language": target_language})

    def generate_base_resume_docx(self, resume_data: dict = None) -> bytes:
        """Generate a Word document from the base resume."""
        payload = resume_data or {}
        return self._request("POST", "/users/generate-modified-base-resume", json=payload)

    def freeze_base_resume_element(self, element_path: str, freeze: bool = True) -> dict:
        """Freeze or unfreeze a base resume element."""
        return self._request("POST", "/users/freeze-base-resume-element", json={"element_path": element_path, "freeze": freeze})

    def get_locked_elements(self) -> dict:
        """Get all locked elements in the base resume."""
        return self._request("GET", "/users/base-resume-locked-elements")

    # ======================================================================
    # USER PROFILE & SETTINGS
    # ======================================================================

    def get_profile(self) -> dict:
        """Get user profile information."""
        return self._request("GET", "/users/profile")

    def update_profile(self, email: str, **fields) -> dict:
        """Update user profile fields (name, location, etc.)."""
        return self._request("PUT", f"/users/{email}", json=fields)

    def upload_profile_picture(self, file_path: Union[str, Path]) -> dict:
        """Upload a profile picture."""
        p = Path(file_path)
        with open(p, "rb") as f:
            return self._request("POST", "/users/profile-pic", files={"file": (p.name, f)})

    def get_user_settings(self) -> dict:
        """Get all user settings."""
        return self._request("GET", "/users/user-settings")

    def update_user_settings(self, settings: dict) -> dict:
        """Update user settings (language, tone, style, etc.)."""
        return self._request("PUT", "/users/user-settings", json=settings)

    def reset_style_settings(self) -> dict:
        """Reset resume style settings to defaults."""
        return self._request("POST", "/users/user-settings/style/reset")

    def add_always_show_skill(self, skill: str) -> dict:
        """Add a skill to the always-show list."""
        return self._request("POST", "/users/user-settings/always-show-skills", json={"skill": skill})

    def remove_always_show_skill(self, skill: str) -> dict:
        """Remove a skill from the always-show list."""
        return self._request("DELETE", "/users/user-settings/always-show-skills", json={"skill": skill})

    def add_never_show_skill(self, skill: str) -> dict:
        """Add a skill to the never-show list."""
        return self._request("POST", "/users/user-settings/never-show-skills", json={"skill": skill})

    def remove_never_show_skill(self, skill: str) -> dict:
        """Remove a skill from the never-show list."""
        return self._request("DELETE", "/users/user-settings/never-show-skills", json={"skill": skill})

    # ======================================================================
    # JOB PREFERENCES
    # ======================================================================

    def get_job_preferences(self) -> dict:
        """Get job preferences."""
        return self._request("GET", "/users/job-preferences")

    def update_job_preferences(self, preferences: dict) -> dict:
        """Update all job preferences."""
        return self._request("PUT", "/users/job-preferences", json=preferences)

    def update_job_preference(self, key: str, value: Any) -> dict:
        """Update a single job preference."""
        return self._request("PATCH", f"/users/job-preferences/{key}", json={"value": value})

    def delete_job_preference(self, key: str) -> dict:
        """Delete a specific job preference."""
        return self._request("DELETE", f"/users/job-preferences/{key}")

    # ======================================================================
    # AUTOFILL ATTRIBUTES & CUSTOM INSTRUCTIONS
    # ======================================================================

    def get_autofill_attributes(self) -> dict:
        """Get autofill attributes for job applications."""
        return self._request("GET", "/users/autofill-attributes")

    def set_autofill_attributes(self, attributes: dict) -> dict:
        """Set autofill attributes."""
        return self._request("POST", "/users/autofill-attributes", json=attributes)

    def get_custom_instructions(self) -> dict:
        """Get custom instructions for resume generation."""
        return self._request("GET", "/users/custom-instructions")

    def set_custom_instructions(self, text: str) -> dict:
        """Set custom instructions for resume generation."""
        return self._request("POST", "/users/custom-instructions", json={"custom_instructions_text": text})

    # ======================================================================
    # MEMORY
    # ======================================================================

    def get_memory(self) -> dict:
        """Get all stored memory points."""
        return self._request("GET", "/users/memory")

    def clear_memory(self) -> dict:
        """Clear all memory."""
        return self._request("DELETE", "/users/memory")

    def delete_memory_point(self, index: int) -> dict:
        """Delete a specific memory point by index."""
        return self._request("DELETE", f"/users/memory/{index}")

    # ======================================================================
    # CREDITS, STATISTICS & ANALYTICS
    # ======================================================================

    def check_credit(self, email: str) -> dict:
        """Check credit balance."""
        return self._request("GET", f"/users/{email}/check-credit")

    def check_subscription(self, email: str) -> dict:
        """Check subscription status."""
        return self._request("GET", f"/users/{email}/check-subscription")

    def get_statistics(self, queue_statistics: bool = False) -> dict:
        """Get user statistics."""
        return self._request("GET", "/users/statistics", params={"queue_statistics": queue_statistics})

    def get_credit_utilization(self) -> dict:
        """Get credit utilization history."""
        return self._request("GET", "/users/credit-utilization")

    def get_ai_insights(self) -> dict:
        """Get AI insights for resume applications."""
        return self._request("GET", "/users/ai-insights")

    def trigger_ai_insights(self) -> dict:
        """Trigger AI insights recalculation."""
        return self._request("POST", "/users/ai-insights")

    def get_ai_insights_jobs(self) -> dict:
        """Get AI insights for job database."""
        return self._request("GET", "/users/ai-insights-jobs")

    def trigger_ai_insights_jobs(self) -> dict:
        """Trigger AI insights recalculation for jobs."""
        return self._request("POST", "/users/ai-insights-jobs")

    def get_application_flow(self) -> dict:
        """Get application flow data for Sankey chart."""
        return self._request("GET", "/users/application-flow-v2")

    def get_resume_timeline(self) -> dict:
        """Get resume creation timeline analytics."""
        return self._request("GET", "/analytics/resume-timeline")

    def get_resume_distribution(self) -> dict:
        """Get resume distribution analytics."""
        return self._request("GET", "/analytics/resume-distribution")

    # ======================================================================
    # TAILORED RESUMES -- CRUD
    # ======================================================================

    def list_recent_resumes(self, days: int = None, favorites_only: bool = False,
                            queue_only: bool = False, page: int = None, page_size: int = 10) -> dict:
        """List recent resumes with optional filters."""
        params: Dict[str, Any] = {"page_size": page_size}
        if days:
            params["days"] = days
        if favorites_only:
            params["favorites_only"] = True
        if queue_only:
            params["queue_only"] = True
        if page:
            params["page"] = page
        return self._request("GET", "/users/recent", params=params)

    def create_resume(self, *, job_url: str = None, job_description: str = None,
                      cover_letter: bool = False, interview_question: bool = False,
                      source: str = "api") -> dict:
        """Create a tailored resume. Provide job_url OR job_description.

        Returns the job_id which you use for all subsequent operations.
        This is a two-step process: init + create (handled automatically).
        """
        payload: Dict[str, Any] = {"source": source}
        if job_url:
            payload["job_url"] = job_url
        if job_description:
            payload["job_description"] = job_description
        if cover_letter:
            payload["cover_letter"] = True
        if interview_question:
            payload["interview_question"] = True

        init = self._request("POST", "/resumes/init_resume", json=payload)
        job_id = init["job_id"]
        result = self._request("POST", f"/resumes/create_resume/{job_id}")
        result["job_id"] = job_id
        return result

    def get_resume(self, job_id: str) -> dict:
        """Get the final tailored resume JSON."""
        return self._request("GET", f"/resumes/final-resume/{job_id}")

    def update_resume(self, job_id: str, resume_data: dict) -> dict:
        """Update a final resume with new data."""
        return self._request("POST", f"/resumes/final-resume/{job_id}", json=resume_data)

    def get_resume_comparison(self, job_id: str) -> dict:
        """Get base vs. tailored resume comparison."""
        return self._request("GET", f"/resumes/{job_id}/comparison")

    def get_resume_metadata(self, job_id: str) -> dict:
        """Get resume metadata (company, title, skills, etc.)."""
        return self._request("GET", f"/resumes/metadata/{job_id}")

    def get_resume_insights(self, job_id: str) -> dict:
        """Get AI-generated insights for a resume."""
        return self._request("GET", f"/resumes/insights/{job_id}")

    def regenerate_insights(self, job_id: str) -> dict:
        """Regenerate AI insights for a resume."""
        return self._request("POST", f"/resumes/regenerate-insights/{job_id}")

    def delete_resume(self, job_id: str) -> dict:
        """Delete a tailored resume."""
        return self._request("DELETE", f"/resumes/{job_id}")

    def download_resume(self, s3_url: str, path: Union[str, Path] = None) -> bytes:
        """Download a resume file from its S3 URL.

        Parameters
        ----------
        s3_url : str
            The ``resume_file_path`` / ``download_url`` from resume data.
        path : str or Path, optional
            If provided, save the file to disk.
        """
        content = self._request("GET", "/resumes/download", params={"s3_url": s3_url})
        if path:
            Path(path).write_bytes(content)
        return content

    def export_resume_pdf(self, job_id: str, document_type: str = "resume", path: Union[str, Path] = None) -> bytes:
        """Export resume or cover letter as PDF."""
        content = self._request("GET", f"/resumes/{job_id}/export-pdf", params={"document_type": document_type})
        if path:
            Path(path).write_bytes(content)
        return content

    def regenerate_resume(self, job_id: str) -> dict:
        """Regenerate a tailored resume."""
        return self._request("POST", f"/resumes/{job_id}/regenerate")

    def update_job_info(self, job_id: str, **fields) -> dict:
        """Update job info on a resume."""
        return self._request("PATCH", f"/resumes/{job_id}/job-info", json=fields)

    # ======================================================================
    # COVER LETTER
    # ======================================================================

    def create_cover_letter(self, job_id: str) -> dict:
        """Create a cover letter for a resume."""
        return self._request("POST", f"/resumes/create_cover_letter/{job_id}")

    def get_cover_letter(self, job_id: str) -> dict:
        """Get the cover letter for a resume."""
        return self._request("GET", f"/resumes/cover_letter/{job_id}")

    def update_cover_letter(self, job_id: str, data: dict) -> dict:
        """Update a cover letter."""
        return self._request("POST", f"/resumes/cover_letter/{job_id}", json=data)

    def regenerate_cover_letter(self, job_id: str) -> dict:
        """Regenerate a cover letter."""
        return self._request("POST", f"/resumes/cover_letter/{job_id}/regenerate")

    # ======================================================================
    # INTERVIEW QUESTIONS
    # ======================================================================

    def create_interview_questions(self, job_id: str) -> dict:
        """Generate interview questions based on a resume."""
        return self._request("POST", f"/resumes/create_interview_question/{job_id}")

    def get_interview_questions(self, job_id: str) -> dict:
        """Get interview questions for a resume."""
        return self._request("GET", f"/resumes/interview_questions/{job_id}")

    def check_interview_answer(self, job_id: str, question: str, answer: str) -> dict:
        """Check an interview answer."""
        return self._request("POST", f"/resumes/check_interview_answer/{job_id}",
                             json={"question": question, "answer": answer})

    # ======================================================================
    # RESUME ACTIONS -- rephrase, translate, improve, chat
    # ======================================================================

    def rephrase_resume(self, job_id: str, text: str, **kwargs) -> dict:
        """Rephrase resume content with multiple options."""
        payload = {"text": text, **kwargs}
        return self._request("POST", f"/resumes/{job_id}/rephrase", json=payload)

    def translate_resume(self, job_id: str, target_language: str) -> dict:
        """Translate a tailored resume."""
        return self._request("POST", f"/resumes/{job_id}/translate", json={"target_language": target_language})

    def improve_resume(self, job_id: str, user_comment: str) -> dict:
        """Improve a tailored resume based on feedback."""
        return self._request("POST", f"/resumes/{job_id}/improve", json={"user_comment": user_comment})

    def chat_with_resume(self, job_id: str, message: str) -> dict:
        """Chat with your resume (AI-assisted editing)."""
        return self._request("POST", f"/resumes/{job_id}/chat", json={"message": message})

    def generate_bullet_points(self, **kwargs) -> dict:
        """Generate bullet points for resume content."""
        return self._request("POST", "/resumes/generate-bullet-points", json=kwargs)

    def rephrase_text(self, text: str, **kwargs) -> dict:
        """Rephrase arbitrary text (user-level rephrase)."""
        return self._request("POST", "/users/rephrase", json={"text": text, **kwargs})

    # ======================================================================
    # FAVORITES & QUEUE
    # ======================================================================

    def favorite_resume(self, job_id: str) -> dict:
        """Toggle favorite status on a resume."""
        return self._request("POST", f"/resumes/favorite/{job_id}")

    def unfavorite_resume(self, job_id: str) -> dict:
        """Remove favorite status from a resume."""
        return self._request("DELETE", f"/resumes/favorite/{job_id}")

    def add_to_queue(self, job_id: str) -> dict:
        """Add a resume to the processing queue."""
        return self._request("POST", f"/resumes/queue/{job_id}")

    def remove_from_queue(self, job_id: str) -> dict:
        """Remove a resume from the queue."""
        return self._request("DELETE", f"/resumes/queue/{job_id}")

    def get_auto_apply_resumes(self) -> dict:
        """Get auto-apply eligible resumes."""
        return self._request("GET", "/users/auto-apply")

    # ======================================================================
    # PUBLIC LINKS (SHARE)
    # ======================================================================

    def create_public_link(self, job_id: str, **settings) -> dict:
        """Create a public shareable link for a resume."""
        return self._request("POST", f"/resumes/{job_id}/share", json=settings)

    def get_public_link(self, job_id: str) -> dict:
        """Get public link info for a resume."""
        return self._request("GET", f"/resumes/{job_id}/share")

    def update_public_link(self, job_id: str, **settings) -> dict:
        """Update public link settings."""
        return self._request("PATCH", f"/resumes/{job_id}/share", json=settings)

    def delete_public_link(self, job_id: str) -> dict:
        """Delete a public link."""
        return self._request("DELETE", f"/resumes/{job_id}/share")

    # ======================================================================
    # COMPANY RESEARCH
    # ======================================================================

    def research_company(self, job_id: str) -> dict:
        """Trigger company research for a resume's job posting."""
        return self._request("POST", f"/resumes/{job_id}/research-company")

    def get_company_research(self, job_id: str) -> dict:
        """Get company research results."""
        return self._request("GET", f"/resumes/{job_id}/research-company")

    # ======================================================================
    # AUTOFILL (APPLICATION)
    # ======================================================================

    def autofill_application(self, job_id: str, fields: dict) -> dict:
        """Autofill a job application form."""
        return self._request("POST", f"/resumes/{job_id}/autofill", json=fields)

    def submit_autofill_feedback(self, job_id: str, feedback: dict) -> dict:
        """Submit feedback on autofill quality."""
        return self._request("POST", f"/resumes/{job_id}/autofill/feedback", json=feedback)

    # ======================================================================
    # CHANGE SUMMARY & FEEDBACK
    # ======================================================================

    def save_change_summary(self, job_id: str, summary: str) -> dict:
        """Save a change summary for a resume and update memory."""
        return self._request("POST", f"/resumes/{job_id}/change-summary", json={"summary": summary})

    def get_change_summaries(self, job_id: str) -> dict:
        """Get all change summaries for a resume."""
        return self._request("GET", f"/resumes/{job_id}/change-summary")

    def submit_feedback(self, job_id: str, feedback: dict) -> dict:
        """Submit feedback on a resume."""
        return self._request("POST", f"/resumes/{job_id}/feedback", json=feedback)

    # ======================================================================
    # SEND EMAIL
    # ======================================================================

    def send_resume_email(self, job_id: str, **kwargs) -> dict:
        """Send resume and/or cover letter via email."""
        return self._request("POST", f"/resumes/{job_id}/send-email", json=kwargs)

    # ======================================================================
    # BATCH OPERATIONS
    # ======================================================================

    def init_batch(self, job_urls: List[str] = None, job_descriptions: List[str] = None, **kwargs) -> dict:
        """Initialize a batch of resumes."""
        payload: Dict[str, Any] = {**kwargs}
        if job_urls:
            payload["job_urls"] = job_urls
        if job_descriptions:
            payload["job_descriptions"] = job_descriptions
        return self._request("POST", "/batch/init_batch", json=payload)

    def process_batch(self, batch_id: str) -> dict:
        """Start processing a batch."""
        return self._request("POST", f"/batch/process_batch/{batch_id}")

    def get_batch(self, batch_id: str) -> dict:
        """Get batch status."""
        return self._request("GET", f"/batch/{batch_id}")

    def list_batches(self) -> dict:
        """List all batches."""
        return self._request("GET", "/batch/")

    def get_batch_resumes(self, batch_id: str) -> dict:
        """Get all resumes in a batch."""
        return self._request("GET", f"/batch/{batch_id}/resumes")

    # ======================================================================
    # JOB SEARCH
    # ======================================================================

    def generate_job_search_query(self) -> dict:
        """Generate a job search query from your base resume."""
        return self._request("POST", "/job-search/generate-query")

    def generate_and_run_search(self) -> dict:
        """Generate a query and run it immediately."""
        return self._request("POST", "/job-search/generate-query-and-run")

    def run_job_search(self, query_id: str = None) -> dict:
        """Run a job search and fetch results."""
        payload = {}
        if query_id:
            payload["query_id"] = query_id
        return self._request("POST", "/job-search/run", json=payload)

    def get_search_queries(self) -> dict:
        """Get all job search queries."""
        return self._request("GET", "/job-search/query")

    def create_search_query(self, query: dict) -> dict:
        """Create a new job search query."""
        return self._request("POST", "/job-search/query", json=query)

    def update_search_query(self, query_id: str, query: dict) -> dict:
        """Update a job search query."""
        return self._request("PUT", f"/job-search/query/{query_id}", json=query)

    def delete_search_query(self, query_id: str) -> dict:
        """Delete a job search query."""
        return self._request("DELETE", f"/job-search/query/{query_id}")

    def get_relevant_jobs(self) -> dict:
        """Get relevant jobs list."""
        return self._request("GET", "/job-search/relevant-jobs")

    def get_job_status_stats(self) -> dict:
        """Get counts and status statistics for relevant jobs."""
        return self._request("GET", "/job-search/status-stats")

    def get_job(self, job_id: str) -> dict:
        """Get full details for a single job."""
        return self._request("GET", f"/job-search/jobs/{job_id}")

    def get_related_jobs(self, job_id: str) -> dict:
        """Get related jobs for a given job."""
        return self._request("GET", f"/job-search/jobs/{job_id}/related")

    def save_job(self, job_id: str, save: bool = True) -> dict:
        """Save or unsave a job."""
        return self._request("POST", f"/job-search/jobs/{job_id}/save", json={"save": save})

    def block_job(self, job_id: str, block: bool = True) -> dict:
        """Block or unblock a job."""
        return self._request("POST", f"/job-search/jobs/{job_id}/block", json={"block": block})

    def skip_job(self, job_id: str, skip: bool = True) -> dict:
        """Skip or unskip a job."""
        return self._request("POST", f"/job-search/jobs/{job_id}/skip", json={"skip": skip})

    def reset_skipped_jobs(self) -> dict:
        """Reset all skipped jobs."""
        return self._request("POST", "/job-search/jobs/reset-skipped")

    def embed_base_resume(self) -> dict:
        """Create embeddings of your base resume for job matching."""
        return self._request("POST", "/job-search/embed-base-resume")

    # ======================================================================
    # JOB SEARCH AGENTS
    # ======================================================================

    def create_search_agent(self, agent: dict) -> dict:
        """Create a new job search agent."""
        return self._request("POST", "/job-search-agent/agent", json=agent)

    def update_search_agent(self, agent_id: str, agent: dict) -> dict:
        """Update a job search agent."""
        return self._request("PUT", f"/job-search-agent/agent/{agent_id}", json=agent)

    def get_search_agents(self) -> dict:
        """Get all job search agents."""
        return self._request("GET", "/job-search-agent/agent")

    def delete_search_agent(self, agent_id: str) -> dict:
        """Delete a job search agent."""
        return self._request("DELETE", f"/job-search-agent/agent/{agent_id}")

    def parse_and_store_job(self, raw_text: str) -> dict:
        """Parse raw job text and store in job database."""
        return self._request("POST", "/job-search-agent/parse-and-store-job", json={"raw_text": raw_text})

    # ======================================================================
    # JOB MATCH
    # ======================================================================

    def get_job_match_score(self, job_description: str = None, job_url: str = None) -> dict:
        """Get a job match score against your base resume."""
        payload: Dict[str, Any] = {}
        if job_description:
            payload["job_description"] = job_description
        if job_url:
            payload["job_url"] = job_url
        return self._request("POST", "/job-match/score", json=payload)

    # ======================================================================
    # TEMPLATES
    # ======================================================================

    def list_templates(self) -> dict:
        """List all available resume templates."""
        return self._request("GET", "/resumes/templates")

    def list_standard_templates(self) -> dict:
        """List standard templates."""
        return self._request("GET", "/resumes/templates/standard")

    def get_standard_template(self, template_id: str) -> dict:
        """Get a single standard template."""
        return self._request("GET", f"/resumes/templates/standard/{template_id}")

    def list_my_templates(self) -> dict:
        """List all template instances for the current user."""
        return self._request("GET", "/resumes/templates/all")

    def create_base_template(self, template_id: str, **kwargs) -> dict:
        """Create a base-resume template instance."""
        return self._request("POST", "/resumes/base/templates", json={"template_id": template_id, **kwargs})

    def list_base_templates(self) -> dict:
        """List base-resume template instances."""
        return self._request("GET", "/resumes/base/templates")

    def get_base_template(self, instance_id: str) -> dict:
        """Get a base-resume template instance."""
        return self._request("GET", f"/resumes/base/templates/{instance_id}")

    def update_base_template_html(self, instance_id: str, html: str) -> dict:
        """Update base-resume template HTML."""
        return self._request("PATCH", f"/resumes/base/templates/{instance_id}/html", json={"html": html})

    def reset_base_template(self, instance_id: str) -> dict:
        """Reset a base-resume template to original."""
        return self._request("POST", f"/resumes/base/templates/{instance_id}/reset")

    def revise_base_template(self, instance_id: str, feedback: str) -> dict:
        """Revise a base-resume template with AI feedback."""
        return self._request("POST", f"/resumes/base/templates/{instance_id}/revise", json={"feedback": feedback})

    def delete_base_template(self, instance_id: str) -> dict:
        """Delete a base-resume template instance."""
        return self._request("DELETE", f"/resumes/base/templates/{instance_id}")

    def create_resume_template(self, job_id: str, template_id: str, **kwargs) -> dict:
        """Create a template instance for a tailored resume."""
        return self._request("POST", f"/resumes/{job_id}/templates", json={"template_id": template_id, **kwargs})

    def list_resume_templates(self, job_id: str) -> dict:
        """List template instances for a tailored resume."""
        return self._request("GET", f"/resumes/{job_id}/templates")

    def get_resume_template(self, job_id: str, instance_id: str) -> dict:
        """Get a template instance for a tailored resume."""
        return self._request("GET", f"/resumes/{job_id}/templates/{instance_id}")

    def update_resume_template_html(self, job_id: str, instance_id: str, html: str) -> dict:
        """Update a resume template's HTML."""
        return self._request("PATCH", f"/resumes/{job_id}/templates/{instance_id}/html", json={"html": html})

    def reset_resume_template(self, job_id: str, instance_id: str) -> dict:
        """Reset a resume template to original."""
        return self._request("POST", f"/resumes/{job_id}/templates/{instance_id}/reset")

    def revise_resume_template(self, job_id: str, instance_id: str, feedback: str) -> dict:
        """Revise a resume template with AI feedback."""
        return self._request("POST", f"/resumes/{job_id}/templates/{instance_id}/revise", json={"feedback": feedback})

    def delete_resume_template(self, job_id: str, instance_id: str) -> dict:
        """Delete a resume template instance."""
        return self._request("DELETE", f"/resumes/{job_id}/templates/{instance_id}")

    def render_template(self, job_id: str, template_id: str) -> dict:
        """Render a resume template."""
        return self._request("POST", f"/resumes/{job_id}/templates/{template_id}/render")

    def compress_content(self, job_id: str) -> dict:
        """Compress resume content to fit template."""
        return self._request("POST", f"/resumes/{job_id}/compress-content")

    def convert_template_to_pdf(self, html: str) -> bytes:
        """Convert resume template HTML to PDF."""
        return self._request("POST", "/resumes/templates/convert-html-to-pdf", json={"html": html})

    # ======================================================================
    # LINKEDIN
    # ======================================================================

    def upload_linkedin_profile(self, profile_data: dict) -> dict:
        """Upload a LinkedIn profile."""
        return self._request("POST", "/linkedin/upload-profile", json=profile_data)

    def optimize_linkedin_profile(self) -> dict:
        """Get AI optimization suggestions for your LinkedIn profile."""
        return self._request("POST", "/linkedin/optimize-profile")

    def get_linkedin_profile(self) -> dict:
        """Get your stored LinkedIn profile."""
        return self._request("GET", "/linkedin/profile")

    # ======================================================================
    # FREE TOOLS (all use X-API-Key via verify_internal_key)
    # ======================================================================

    def _run_tool(self, tool_name: str, file_path: Union[str, Path]) -> dict:
        """Run a free tool: upload file, init, process, return report."""
        p = Path(file_path)
        with open(p, "rb") as f:
            init = self._request("POST", f"/{tool_name}/init_analyze", files={"file": (p.name, f)})
        analysis_id = init["id"]
        result = self._request("POST", f"/{tool_name}/process_analyze/{analysis_id}")
        return result

    def _get_tool_report(self, tool_name: str, analysis_id: str) -> dict:
        """Get a previously generated tool report."""
        return self._request("GET", f"/{tool_name}/report/{analysis_id}")

    def run_ats_check(self, file_path: Union[str, Path]) -> dict:
        """Run an ATS compatibility check on a resume file."""
        return self._run_tool("ats-checker", file_path)

    def get_ats_report(self, analysis_id: str) -> dict:
        """Get an existing ATS check report."""
        return self._get_tool_report("ats-checker", analysis_id)

    def run_resume_roast(self, file_path: Union[str, Path]) -> dict:
        """Get a brutally honest resume roast."""
        return self._run_tool("resume-roast", file_path)

    def get_resume_roast_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("resume-roast", analysis_id)

    def run_career_clock(self, file_path: Union[str, Path]) -> dict:
        """Run career clock analysis."""
        return self._run_tool("career-clock", file_path)

    def get_career_clock_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("career-clock", analysis_id)

    def run_interview_questions_tool(self, file_path: Union[str, Path]) -> dict:
        """Generate interview questions from a resume file (free tool)."""
        return self._run_tool("interview-questions", file_path)

    def get_interview_questions_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("interview-questions", analysis_id)

    def run_career_personality_test(self, file_path: Union[str, Path]) -> dict:
        """Run a career personality test."""
        return self._run_tool("career-personality-test", file_path)

    def get_career_personality_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("career-personality-test", analysis_id)

    def run_skills_gap_analyzer(self, file_path: Union[str, Path]) -> dict:
        """Analyze skills gaps in a resume."""
        return self._run_tool("skills-gap-analyzer", file_path)

    def get_skills_gap_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("skills-gap-analyzer", analysis_id)

    def run_readability_test(self, file_path: Union[str, Path]) -> dict:
        """Run a resume readability test."""
        return self._run_tool("resume-readability-test", file_path)

    def get_readability_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("resume-readability-test", analysis_id)

    def run_linkedin_profile_generator(self, file_path: Union[str, Path]) -> dict:
        """Generate an optimized LinkedIn profile from a resume."""
        return self._run_tool("linkedin-profile-generator", file_path)

    def get_linkedin_profile_generator_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("linkedin-profile-generator", analysis_id)

    def run_buzzword_detector(self, file_path: Union[str, Path]) -> dict:
        """Detect buzzwords and cliches in a resume."""
        return self._run_tool("buzzword-detector", file_path)

    def get_buzzword_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("buzzword-detector", analysis_id)

    def run_job_search_keywords(self, file_path: Union[str, Path]) -> dict:
        """Extract optimal job search keywords from a resume."""
        return self._run_tool("job-search-keywords", file_path)

    def get_job_search_keywords_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("job-search-keywords", analysis_id)

    def run_networking_copilot(self, file_path: Union[str, Path]) -> dict:
        """Get networking strategy recommendations."""
        return self._run_tool("networking-co-pilot", file_path)

    def get_networking_copilot_report(self, analysis_id: str) -> dict:
        return self._get_tool_report("networking-co-pilot", analysis_id)

    # ======================================================================
    # PERSONALIZED LEARNING
    # ======================================================================

    def create_course(self, **kwargs) -> dict:
        """Create a personalized learning course."""
        return self._request("POST", "/learning/create", json=kwargs)

    def list_courses(self) -> dict:
        """List all courses."""
        return self._request("GET", "/learning/list")

    def get_course(self, course_id: str) -> dict:
        """Get a course by ID."""
        return self._request("GET", f"/learning/{course_id}")

    def revise_slide(self, course_id: str, **kwargs) -> dict:
        """Revise a slide in a course."""
        return self._request("POST", f"/learning/{course_id}/revise-slide", json=kwargs)

    def create_mindmap(self, course_id: str) -> dict:
        """Create a mindmap for a course."""
        return self._request("POST", f"/learning/{course_id}/mindmap")

    def clarify_course(self, course_id: str, message: str) -> dict:
        """Ask a clarifying question about course content."""
        return self._request("POST", f"/learning/{course_id}/clarify", json={"message": message})

    # ======================================================================
    # WEBSITE RESUME (PORTFOLIO)
    # ======================================================================

    def list_website_styles(self) -> dict:
        """List available website resume styles."""
        return self._request("GET", "/website-resume/styles")

    def create_website_resume(self, **kwargs) -> dict:
        """Generate a new website resume."""
        return self._request("POST", "/website-resume", json=kwargs)

    def list_website_resumes(self) -> dict:
        """List your website resumes."""
        return self._request("GET", "/website-resume")

    def get_website_resume(self, website_resume_id: str) -> dict:
        """Get a website resume by ID."""
        return self._request("GET", f"/website-resume/{website_resume_id}")

    def regenerate_website_resume(self, website_resume_id: str, style_id: str) -> dict:
        """Regenerate HTML with a different style."""
        return self._request("POST", f"/website-resume/{website_resume_id}/regenerate", json={"style_id": style_id})

    def revise_website_resume(self, website_resume_id: str, feedback: str) -> dict:
        """Revise a website resume based on feedback."""
        return self._request("POST", f"/website-resume/{website_resume_id}/revise", json={"feedback": feedback})

    def reset_website_resume(self, website_resume_id: str) -> dict:
        """Reset to original generated HTML."""
        return self._request("POST", f"/website-resume/{website_resume_id}/reset")

    def update_website_resume_html(self, website_resume_id: str, html: str) -> dict:
        """Save HTML directly."""
        return self._request("PATCH", f"/website-resume/{website_resume_id}/html", json={"html": html})

    def delete_website_resume(self, website_resume_id: str) -> dict:
        """Delete a website resume."""
        return self._request("DELETE", f"/website-resume/{website_resume_id}")

    # ======================================================================
    # AFFILIATE
    # ======================================================================

    def create_affiliate_code(self) -> dict:
        """Create a new affiliate code."""
        return self._request("POST", "/affiliate/create")

    def get_affiliate_stats(self) -> dict:
        """Get affiliate statistics."""
        return self._request("GET", "/affiliate/stats")

    def get_affiliate_transactions(self) -> dict:
        """Get affiliate transaction history."""
        return self._request("GET", "/affiliate/transactions")

    def request_affiliate_payout(self) -> dict:
        """Request payout for available earnings."""
        return self._request("POST", "/affiliate/request-payout")

    # ======================================================================
    # CUSTOMER SERVICE
    # ======================================================================

    def customer_service_chat(self, message: str) -> dict:
        """Chat with the customer service bot."""
        return self._request("POST", "/customer-service/chat", json={"message": message})

    # ======================================================================
    # MISCELLANEOUS
    # ======================================================================

    def transcribe_audio(self, file_path: Union[str, Path]) -> dict:
        """Transcribe an audio file."""
        p = Path(file_path)
        with open(p, "rb") as f:
            return self._request("POST", "/resumes/transcribe-audio", files={"file": (p.name, f)})

    def report_bug(self, **kwargs) -> dict:
        """Report a bug."""
        return self._request("POST", "/bug-report/report-bug", json=kwargs)

    def get_latest_announcement(self) -> dict:
        """Get the latest announcement."""
        return self._request("GET", "/announcements/latest")

    def delete_account(self) -> dict:
        """Permanently delete your account."""
        return self._request("DELETE", "/users/delete-account")
