"""
LLM prompts for generating sparse primitive config deltas for GBP hierarchy nodes.

These prompts are used to populate L1 (sector) and L2 (category) nodes in the
GBP category tree with business-specific primitive configurations.

The output is a sparse delta that only includes primitives that need overrides
for that specific business type. Configuration inheritance handles the rest.
"""

# =============================================================================
# SYSTEM PROMPT
# =============================================================================

SYSTEM_PROMPT_GBP_PRIMITIVE_CONFIG = """You are a customer experience taxonomy configuration specialist. Your task is to generate sparse primitive configuration deltas for Google Business Profile (GBP) category nodes.

## YOUR ROLE

You configure how the Universal Review Taxonomy (URT) primitives should be weighted, labeled, and detected for specific business types. Each primitive represents a distinct dimension of customer experience that appears in reviews.

## THE 36 PRIMITIVES (Grouped by Domain)

### OFFERING (O) - What the business provides
- WORKS: Does the product/service function correctly?
- PERFORMANCE: How well does it perform?
- DURABILITY: How long does it last?
- RELIABILITY: Is it consistent over time?
- OUTCOME: Did the customer achieve their goal?
- MATERIALS: Quality of ingredients/components
- CRAFTSMANSHIP: Skill of construction/execution
- PRESENTATION: Visual/aesthetic quality
- ATTENTION_TO_DETAIL: Finishing touches
- CONDITION: State at delivery
- COMPLETENESS: All components present?
- FEATURES: Promised features available?
- SCOPE: Full scope delivered?
- DOCUMENTATION: Supporting materials
- SPEC_MATCH: Matches what was ordered?
- PERSONALIZATION: Adapted to individual
- FLEXIBILITY: Can be modified?
- APPROPRIATENESS: Right solution for need?

### PEOPLE (P) - Staff interactions
- WARMTH: Friendly manner
- RESPECT: Dignity and courtesy
- EMPATHY: Understanding feelings
- PATIENCE: Calm and tolerant
- ENTHUSIASM: Energy and engagement
- KNOWLEDGE: Expertise level
- SKILL: Technical ability
- PROBLEM_SOLVING: Finding solutions
- PROFESSIONALISM: Conduct standards
- EXPERIENCE: Depth of expertise
- ATTENTIVENESS: Being present
- INITIATIVE: Proactive help
- AVAILABILITY: Present when needed
- FOLLOW_THROUGH: Completing promises
- URGENCY: Appropriate prioritization
- CLARITY: Clear communication
- LISTENING: Understanding needs
- PROACTIVE_UPDATES: Keeping informed
- ACCURACY: Correct information
- TONE: Communication style

### JOURNEY (J) - Process and timing
- WAIT_TIME: Time spent waiting
- SPEED: How fast things happen
- RESPONSE_TIME: Time to respond
- PUNCTUALITY: On-time delivery
- PACING: Appropriate speed
- SIMPLICITY: Easy process
- NAVIGATION: Finding things
- PAPERWORK: Documentation burden
- HANDOFFS: Transitions
- SELF_SERVICE: Autonomy options
- CONSISTENCY: Same each time
- PROCESS_ACCURACY: Correct execution
- UPTIME: System availability
- PREDICTABILITY: Expectations met
- ERROR_RATE: Frequency of mistakes
- ACKNOWLEDGMENT: Recognizing issues
- RESOLUTION_PROCESS: How problems handled
- RESOLUTION_SPEED: Time to fix
- RESOLUTION_QUALITY: Adequacy of fix
- PREVENTION: Avoiding recurrence

### ENVIRONMENT (E) - Physical and digital space
- CLEANLINESS: Hygiene and tidiness
- MAINTENANCE: Condition and upkeep
- LAYOUT: Functional arrangement
- EQUIPMENT: Tools and amenities
- SIGNAGE: Navigation aids
- INTERFACE_DESIGN: Digital UX
- DIGITAL_FUNCTIONALITY: Features working
- DIGITAL_PERFORMANCE: Speed/responsiveness
- DIGITAL_NAVIGATION: Finding things online
- MOBILE_EXPERIENCE: Smartphone optimization
- ATMOSPHERE: Overall mood
- NOISE: Sound environment
- TEMPERATURE: Climate comfort
- CROWDING: Density/space
- AESTHETICS: Visual appeal
- PHYSICAL_SAFETY: Protection from harm
- HEALTH_HYGIENE: Sanitation standards
- SECURITY: Protection of person/property
- COMFORT: Physical ease
- EMERGENCY_READINESS: Preparedness

### ACCESS (A) - Availability and accessibility
- HOURS: Operating hours
- BOOKING: Appointment access
- INVENTORY: Product availability
- STAFFING: Personnel available
- GEOGRAPHIC_REACH: Service area
- PHYSICAL_ACCESSIBILITY: Mobility access
- VISUAL_ACCESSIBILITY: Sight accommodations
- HEARING_ACCESSIBILITY: Audio accommodations
- COGNITIVE_ACCESSIBILITY: Mental accommodations
- DIGITAL_ACCESSIBILITY: Assistive tech support
- LANGUAGE_SUPPORT: Multiple languages
- CULTURAL_SENSITIVITY: Background respect
- DIETARY_MEDICAL: Restriction accommodations
- FAMILY_FRIENDLY: Children accommodation
- EQUAL_TREATMENT: Non-discrimination
- LOCATION: Convenience
- PARKING: Vehicle accommodation
- TRANSIT: Public transport
- PAYMENT_OPTIONS: How you can pay
- CONTACT_OPTIONS: Ways to reach

### VALUE (V) - Cost and worth
- ABSOLUTE_PRICE: The actual cost
- PRICE_VS_EXPECTATION: Compared to anticipated
- PRICE_VS_MARKET: Compared to competitors
- HIDDEN_COSTS: Unexpected charges
- PAYMENT_FLEXIBILITY: Terms and options
- PRICING_CLARITY: Understanding costs
- FEE_DISCLOSURE: Upfront about charges
- ADVERTISING_ACCURACY: Marketing matches reality
- TERMS_FAIRNESS: Policy reasonableness
- HONEST_REPRESENTATION: Truthful claims
- TIME_INVESTMENT: Hours required
- MENTAL_EFFORT: Cognitive load
- PHYSICAL_EFFORT: Bodily exertion
- HASSLE_FACTOR: Cumulative frustration
- OPPORTUNITY_COST: What else could be done
- OVERALL_VALUE: Total assessment
- QUALITY_PRICE_RATIO: What you get for what you pay
- SATISFACTION: Contentment with exchange
- RECOMMENDATION: Would suggest to others
- RETURN_INTENT: Would come back

### RELATIONSHIP (R) - Trust and loyalty
- TRUTHFULNESS: Accurate representations
- PROMISE_KEEPING: Honoring commitments
- TRANSPARENCY: Openness about practices
- ETHICS: Moral business conduct
- FAIR_DEALING: Equitable treatment
- TRACK_RECORD: Historical performance
- DEPENDABILITY: Same over time
- STABILITY: Organizational continuity
- TRUSTWORTHINESS: Warranting confidence
- GUARANTEE_HONOR: Standing behind product
- ERROR_ACKNOWLEDGMENT: Admitting failures
- APOLOGY: Expression of regret
- COMPENSATION: Making amends
- IMPROVEMENT: Actions to prevent recurrence
- OWNERSHIP: Taking responsibility
- RECOGNITION: Acknowledging customers
- REWARDS: Loyalty benefits
- RELATIONSHIP_BUILDING: Investment in connection
- ONGOING_COMMUNICATION: Contact quality
- COMMUNITY: Belonging and connection

## META PRIMITIVES (DO NOT INCLUDE IN OUTPUT)

These are always globally active and should NEVER appear in your output:
- HONESTY, ETHICS, PROMISES, ACKNOWLEDGMENT, RESPONSE_QUALITY
- RECOVERY, RETURN_INTENT, RECOMMEND, RECOGNITION, UNMAPPED

## OUTPUT RULES

1. **SPARSE OUTPUT ONLY**: Only include primitives that DIFFER from parent configuration
   - If parent has WAIT_TIME at "normal" priority and this business needs "critical", include it
   - If parent already has the right configuration, do NOT include it

2. **PRIORITY LEVELS** (use exact strings):
   - "critical": Essential for this business (top 3-5 per business)
   - "high": Very important (next 5-8)
   - "normal": Standard relevance (default)
   - "low": Less common for this business
   - "very_low": Rarely relevant (prefer over active: false)

3. **WHEN TO SET active: false**:
   - Only when a primitive is truly IRRELEVANT (not just uncommon)
   - Example: PARKING for an online-only business
   - Prefer priority: "very_low" unless truly N/A

4. **SIGNALS**: 5-15 realistic customer phrases per side
   - Use actual language customers use in reviews
   - Include colloquial expressions, not formal descriptions
   - Positive and negative should be opposites of the same dimension
   - Use __replace__: true ONLY if parent signals are wrong (rare)

5. **MODES**: Only include if this business has distinct service modes
   - Examples: "dine_in" vs "delivery" for restaurants
   - "in_store" vs "online" for retailers
   - Most businesses: omit modes entirely

6. **business_context**: Include for L1 sectors and leaf categories
   - name: Human-friendly display name
   - description: 1-2 sentence description
   - modes: Array of applicable modes (if any)
   - default_mode: Primary mode (if modes exist)

## VALIDATION RULES

Your output MUST:
- Be valid JSON only (no markdown, no explanations)
- Use ONLY primitive codes from the dictionary provided
- NOT create new primitive codes
- NOT include meta primitives
- NOT include playbooks, solutions, or action recommendations
- Have at least one primitive_config entry
- Use exact priority strings: "critical", "high", "normal", "low", "very_low"

## OUTPUT SCHEMA

```json
{
  "business_context": {
    "name": "Human-Friendly Name",
    "description": "What this business type does and what matters to customers",
    "modes": ["mode1", "mode2"],
    "default_mode": "mode1"
  },
  "primitive_configs": {
    "PRIMITIVE_CODE": {
      "active": true,
      "priority": "critical|high|normal|low|very_low",
      "label": "Business-specific label for this primitive",
      "description": "What this primitive means for this specific business",
      "signals": {
        "positive": ["signal 1", "signal 2", "..."],
        "negative": ["signal 1", "signal 2", "..."],
        "__replace__": false
      },
      "modes": {
        "mode_name": {
          "applicable": true,
          "label": "Mode-specific label"
        }
      }
    }
  }
}
```

Return ONLY the JSON object. No preamble, no explanation, no markdown."""


# =============================================================================
# USER PROMPT TEMPLATE
# =============================================================================

USER_PROMPT_TEMPLATE = """Generate a sparse primitive configuration delta for this GBP node.

## NODE INFORMATION

**GBP Path**: {gbp_path}
**Node Name**: {node_name}
**Node Description**: {node_description}
**Node Level**: {node_level} (L1=Sector, L2=Category, L3=Subcategory, L4=Leaf)

## PARENT RESOLVED CONFIGURATION

This is the already-resolved configuration from all ancestors. Only include primitives that need to CHANGE from this:

```json
{parent_resolved_config}
```

## PRIMITIVE DICTIONARY

Reference for all available primitives with their base definitions:

```json
{primitive_dictionary}
```

## YOUR TASK

Generate a sparse delta configuration for "{node_name}" that:

1. Identifies the 5-10 MOST CRITICAL primitives for this business type
2. Adjusts priority levels to reflect what customers actually care about
3. Provides business-specific labels and signals where helpful
4. Only includes primitives that DIFFER from parent_resolved_config
5. Uses realistic customer language for signals

Think about:
- What do customers of {node_name} businesses typically praise or complain about?
- Which URT primitives are most actionable for this business type?
- What unique aspects distinguish this business type from others?

Return ONLY valid JSON matching the output schema."""


# =============================================================================
# HELPER FUNCTIONS
# =============================================================================

def build_user_prompt(
    gbp_path: str,
    node_name: str,
    node_description: str,
    node_level: int,
    parent_resolved_config: dict,
    primitive_dictionary: dict,
) -> str:
    """
    Build the user prompt with actual values substituted.

    Args:
        gbp_path: The ltree path (e.g., "Food_Beverage" or "Food_Beverage.Restaurants")
        node_name: Human-readable name (e.g., "Food & Beverage" or "Restaurants")
        node_description: Brief description of this business category
        node_level: 1-4 indicating hierarchy depth
        parent_resolved_config: Already-resolved config from ancestors (or {} for L1)
        primitive_dictionary: All primitives with definitions and base signals

    Returns:
        Formatted user prompt string
    """
    import json

    level_labels = {
        1: "L1=Sector",
        2: "L2=Category",
        3: "L3=Subcategory",
        4: "L4=Leaf",
    }

    return USER_PROMPT_TEMPLATE.format(
        gbp_path=gbp_path,
        node_name=node_name,
        node_description=node_description,
        node_level=level_labels.get(node_level, f"L{node_level}"),
        parent_resolved_config=json.dumps(parent_resolved_config, indent=2),
        primitive_dictionary=json.dumps(primitive_dictionary, indent=2),
    )


def validate_primitive_config_output(output: dict, primitive_codes: set[str]) -> list[str]:
    """
    Validate the LLM output against schema and rules.

    Args:
        output: Parsed JSON output from LLM
        primitive_codes: Set of valid primitive codes

    Returns:
        List of validation errors (empty if valid)
    """
    errors = []

    # Meta primitives that should never appear
    META_PRIMITIVES = {
        "HONESTY", "ETHICS", "PROMISES", "ACKNOWLEDGMENT", "RESPONSE_QUALITY",
        "RECOVERY", "RETURN_INTENT", "RECOMMEND", "RECOGNITION", "UNMAPPED"
    }

    VALID_PRIORITIES = {"critical", "high", "normal", "low", "very_low"}

    # Check required structure
    if not isinstance(output, dict):
        errors.append("Output must be a JSON object")
        return errors

    primitive_configs = output.get("primitive_configs", {})
    if not primitive_configs:
        errors.append("primitive_configs is required and must not be empty")

    if not isinstance(primitive_configs, dict):
        errors.append("primitive_configs must be an object")
        return errors

    for code, config in primitive_configs.items():
        # Check code is valid
        if code not in primitive_codes:
            errors.append(f"Unknown primitive code: {code}")
            continue

        # Check for meta primitives
        if code in META_PRIMITIVES:
            errors.append(f"Meta primitive should not appear: {code}")

        if not isinstance(config, dict):
            errors.append(f"{code}: config must be an object")
            continue

        # Check priority if present
        priority = config.get("priority")
        if priority and priority not in VALID_PRIORITIES:
            errors.append(f"{code}: invalid priority '{priority}', must be one of {VALID_PRIORITIES}")

        # Check signals structure if present
        signals = config.get("signals")
        if signals:
            if not isinstance(signals, dict):
                errors.append(f"{code}: signals must be an object")
            else:
                pos = signals.get("positive", [])
                neg = signals.get("negative", [])
                if pos and not isinstance(pos, list):
                    errors.append(f"{code}: signals.positive must be an array")
                if neg and not isinstance(neg, list):
                    errors.append(f"{code}: signals.negative must be an array")

    # Check business_context if present
    business_context = output.get("business_context")
    if business_context:
        if not isinstance(business_context, dict):
            errors.append("business_context must be an object")
        else:
            modes = business_context.get("modes")
            if modes and not isinstance(modes, list):
                errors.append("business_context.modes must be an array")

    return errors


# =============================================================================
# EXAMPLE PRIMITIVE DICTIONARY (subset for reference)
# =============================================================================

EXAMPLE_PRIMITIVE_DICTIONARY = {
    "WAIT_TIME": {
        "code": "WAIT_TIME",
        "domain": "J",
        "category": "Timing",
        "name": "Wait Time",
        "definition": "Time spent waiting for service",
        "base_signals": {
            "positive": ["no wait", "seated immediately", "right away", "quick turnaround"],
            "negative": ["long wait", "waited forever", "45 minutes", "hours to be seen"]
        }
    },
    "WARMTH": {
        "code": "WARMTH",
        "domain": "P",
        "category": "Attitude",
        "name": "Warmth/Friendliness",
        "definition": "Approachability and pleasantness of staff",
        "base_signals": {
            "positive": ["so friendly", "welcoming", "made us feel at home", "warm greeting"],
            "negative": ["cold", "unfriendly", "rude", "didn't acknowledge us"]
        }
    },
    "CRAFTSMANSHIP": {
        "code": "CRAFTSMANSHIP",
        "domain": "O",
        "category": "Quality",
        "name": "Craftsmanship",
        "definition": "Skill of construction or execution",
        "base_signals": {
            "positive": ["beautifully made", "expert work", "attention to detail", "quality craftsmanship"],
            "negative": ["sloppy work", "poorly made", "amateur job", "uneven"]
        }
    },
    # ... more primitives would be included in full dictionary
}


# =============================================================================
# EXAMPLE OUTPUT (for reference and testing)
# =============================================================================

EXAMPLE_OUTPUT_RESTAURANT = {
    "business_context": {
        "name": "Restaurants",
        "description": "Food service establishments where customers dine on-premises or order for delivery/takeout",
        "modes": ["dine_in", "takeout", "delivery"],
        "default_mode": "dine_in"
    },
    "primitive_configs": {
        "WAIT_TIME": {
            "priority": "critical",
            "label": "Wait for Table/Food",
            "description": "Time waiting to be seated and for food to arrive",
            "signals": {
                "positive": [
                    "seated immediately",
                    "food came out fast",
                    "no wait for a table",
                    "quick service",
                    "didn't have to wait long"
                ],
                "negative": [
                    "waited 45 minutes for a table",
                    "food took forever",
                    "an hour for appetizers",
                    "still waiting for our entrees",
                    "had to flag down the waiter"
                ]
            },
            "modes": {
                "dine_in": {
                    "applicable": True,
                    "label": "Wait for Table & Food"
                },
                "takeout": {
                    "applicable": True,
                    "label": "Order Ready Time"
                },
                "delivery": {
                    "applicable": True,
                    "label": "Delivery Time"
                }
            }
        },
        "CRAFTSMANSHIP": {
            "priority": "critical",
            "label": "Food Preparation Quality",
            "description": "Skill and care in cooking and food preparation",
            "signals": {
                "positive": [
                    "cooked to perfection",
                    "beautifully plated",
                    "chef knows what they're doing",
                    "perfectly seasoned",
                    "amazing flavor"
                ],
                "negative": [
                    "overcooked",
                    "bland and tasteless",
                    "clearly microwaved",
                    "burnt edges",
                    "undercooked chicken"
                ]
            }
        },
        "WARMTH": {
            "priority": "high",
            "label": "Server Friendliness",
            "description": "Warmth and hospitality from hosts, servers, and staff"
        },
        "CLEANLINESS": {
            "priority": "high",
            "label": "Restaurant Cleanliness",
            "description": "Hygiene of dining area, bathrooms, and visible kitchen areas"
        },
        "ATMOSPHERE": {
            "priority": "high",
            "label": "Dining Ambiance",
            "description": "Overall mood, decor, lighting, and vibe of the restaurant"
        },
        "PARKING": {
            "priority": "normal",
            "modes": {
                "dine_in": {"applicable": True},
                "takeout": {"applicable": True},
                "delivery": {"applicable": False}
            }
        },
        "DIGITAL_ACCESSIBILITY": {
            "priority": "very_low",
            "description": "Screen reader support and digital accessibility - rarely mentioned in restaurant reviews"
        }
    }
}
