"""Personalized message generator — the core product engine.

Generates LinkedIn invitation messages that:
1. Sound like the user (voice signature matching)
2. Reference prospect-specific details
3. Stay under 200 chars (regular LinkedIn limit)
4. Follow sales methodology from 56 prompt versions
"""

from __future__ import annotations

import json
import logging
from typing import Any

from .llm import LLMClient

logger = logging.getLogger(__name__)

MESSAGE_SYSTEM = """You are an expert at writing LinkedIn connection request messages. You write brief, genuine, personal messages that get accepted.

Key principles:
- Sound like a real person, not a bot or salesperson
- Reference something SPECIFIC about the prospect (their work, posts, expertise)
- Never use salesy phrases like "leverage", "synergy", "exciting opportunity", "I noticed"
- Keep it under 200 characters
- End with a soft question or observation, not a hard sell
- Match the sender's voice and tone exactly

You output ONLY the message text. No explanation, no quotes, no formatting."""

MESSAGE_PROMPT = """Write a LinkedIn connection request message.

## SENDER (you are writing AS this person)
Name: {sender_name}
Title: {sender_title}
Company: {sender_company}
Voice: {voice_tone}
Sentence style: {voice_sentence}
Vocabulary preferences: {voice_vocab}
No-go (NEVER use these): {voice_nogo}

## PROSPECT (the person receiving this message)
Name: {prospect_name}
Title: {prospect_title}
Company: {prospect_company}
Headline: {prospect_headline}
Location: {prospect_location}

## CAMPAIGN CONTEXT
Target: {campaign_target}
Relevance: {relevance_hook}

## CONSTRAINTS
- MAXIMUM 200 characters (this is a hard limit — LinkedIn enforces it)
- Use the sender's voice — match their tone, formality, and vocabulary
- Reference something specific about the prospect
- Soft CTA: ask a question or make an observation. NEVER say "let's hop on a call"
- First name only for the prospect (e.g., "Sarah" not "Sarah Chen")
- NO emojis unless the sender's voice uses them
- NO "I noticed you..." or "I came across your profile..."

## OUTPUT
Write ONLY the message text. Nothing else. Under 200 characters."""


async def generate_message(
    prospect: dict[str, Any],
    sender_profile: dict[str, Any],
    voice_signature: dict[str, Any],
    campaign_context: dict[str, Any],
) -> str:
    """Generate a personalized LinkedIn invitation message.

    Args:
        prospect: Prospect profile data (name, title, company, headline, etc.)
        sender_profile: User's own profile data
        voice_signature: Voice analysis results (tone, vocabulary, patterns)
        campaign_context: Campaign ICP and target description

    Returns:
        Generated message text (≤200 chars).
    """
    # Extract voice details
    voice_vocab = voice_signature.get("vocabulary_preferences", [])
    if isinstance(voice_vocab, list):
        voice_vocab = ", ".join(voice_vocab)

    # Get prospect's first name
    prospect_name = prospect.get("name", "").split()[0] if prospect.get("name") else "there"

    prompt = MESSAGE_PROMPT.format(
        sender_name=sender_profile.get("name", ""),
        sender_title=sender_profile.get("title", ""),
        sender_company=sender_profile.get("company", ""),
        voice_tone=voice_signature.get("tone", "Professional, direct"),
        voice_sentence=voice_signature.get("sentence_length", "Medium"),
        voice_vocab=voice_vocab or "None specified",
        voice_nogo=voice_signature.get("no_go", "Generic sales phrases"),
        prospect_name=prospect_name,
        prospect_title=prospect.get("title", ""),
        prospect_company=prospect.get("company", ""),
        prospect_headline=prospect.get("headline", ""),
        prospect_location=prospect.get("location", ""),
        campaign_target=campaign_context.get("target_description", ""),
        relevance_hook=campaign_context.get("relevance_hook", ""),
    )

    client = LLMClient()
    message = await client.generate(prompt, system=MESSAGE_SYSTEM, temperature=0.7)

    # Clean up — strip quotes, whitespace, etc.
    message = message.strip().strip('"').strip("'").strip()

    # Enforce 200 char limit
    if len(message) > 200:
        # Try to truncate at last complete sentence/phrase
        truncated = message[:197]
        last_space = truncated.rfind(" ")
        if last_space > 150:
            message = truncated[:last_space] + "..."
        else:
            message = truncated + "..."

    return message
