"""
Proposal Template Engine for AgileAdapt
=======================================

Enterprise proposal generation system for Australian Voice AI market.
NO hourly rates - subscription and buildout pricing only.

PRICING (Australian Market - MANDATORY):
- Voice AI Base: $497/month
- Voice AI Pro: $697-897/month
- Basic Setup (buildout): $1,500-2,500
- Full Automation (buildout): $3,500-5,000

VERIFICATION_STAMP
Story: STORY-2.1
Verified By: CLAUDE
Verified At: 2026-01-24
Tests: See tests/test_template_engine.py
Coverage: Core functionality
"""

import os
import re
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from pathlib import Path
from typing import Any, Dict, List, Optional, Union


class ProposalType(Enum):
    """Available proposal templates."""
    VOICE_AI_BASE = "voice_ai_base"
    VOICE_AI_PRO = "voice_ai_pro"
    FULL_AUTOMATION_SUITE = "full_automation_suite"


class PricingTier(Enum):
    """Pricing tiers for buildout complexity."""
    BASIC = "basic"
    STANDARD = "standard"
    ADVANCED = "advanced"
    ENTERPRISE = "enterprise"


# Australian Market Pricing - MANDATORY (no hourly rates)
MONTHLY_PRICING = {
    ProposalType.VOICE_AI_BASE: 497,
    ProposalType.VOICE_AI_PRO: {
        PricingTier.BASIC: 697,
        PricingTier.STANDARD: 747,
        PricingTier.ADVANCED: 847,
        PricingTier.ENTERPRISE: 897,
    },
    ProposalType.FULL_AUTOMATION_SUITE: 897,
}

BUILDOUT_PRICING = {
    ProposalType.VOICE_AI_BASE: {
        PricingTier.BASIC: 1500,
        PricingTier.STANDARD: 1800,
        PricingTier.ADVANCED: 2200,
        PricingTier.ENTERPRISE: 2500,
    },
    ProposalType.VOICE_AI_PRO: {
        PricingTier.BASIC: 2000,
        PricingTier.STANDARD: 2500,
        PricingTier.ADVANCED: 3000,
        PricingTier.ENTERPRISE: 3500,
    },
    ProposalType.FULL_AUTOMATION_SUITE: {
        PricingTier.BASIC: 3500,
        PricingTier.STANDARD: 4000,
        PricingTier.ADVANCED: 4500,
        PricingTier.ENTERPRISE: 5000,
    },
}


@dataclass
class BusinessContext:
    """Context data for proposal personalization."""
    business_name: str
    contact_name: str
    industry: str
    pain_points: List[str] = field(default_factory=list)
    current_challenges: str = ""
    business_size: str = "small"  # small, medium, large
    call_volume: str = "moderate"  # low, moderate, high, very_high
    integrations_needed: List[str] = field(default_factory=list)
    custom_requirements: Dict[str, Any] = field(default_factory=dict)
    discovery_date: Optional[str] = None
    follow_up_date: Optional[str] = None


@dataclass
class ProposalResult:
    """Generated proposal output."""
    content: str
    proposal_type: ProposalType
    pricing_tier: PricingTier
    monthly_price: int
    buildout_price: int
    total_first_month: int
    business_context: BusinessContext
    generated_at: str
    template_version: str = "1.0.0"


def calculate_monthly_price(
    proposal_type: ProposalType,
    pricing_tier: PricingTier = PricingTier.BASIC
) -> int:
    """
    Calculate monthly subscription price.

    Args:
        proposal_type: Type of proposal/service
        pricing_tier: Complexity tier for variable pricing

    Returns:
        Monthly price in AUD
    """
    price_config = MONTHLY_PRICING.get(proposal_type)

    if isinstance(price_config, dict):
        return price_config.get(pricing_tier, price_config[PricingTier.BASIC])
    elif isinstance(price_config, int):
        return price_config
    else:
        raise ValueError(f"Invalid proposal type: {proposal_type}")


def calculate_buildout_price(
    proposal_type: ProposalType,
    pricing_tier: PricingTier = PricingTier.BASIC
) -> int:
    """
    Calculate one-time buildout/setup price.

    Args:
        proposal_type: Type of proposal/service
        pricing_tier: Complexity tier

    Returns:
        Buildout price in AUD
    """
    tier_pricing = BUILDOUT_PRICING.get(proposal_type, {})
    return tier_pricing.get(pricing_tier, tier_pricing.get(PricingTier.BASIC, 1500))


def determine_pricing_tier(context: BusinessContext) -> PricingTier:
    """
    Automatically determine pricing tier from business context.

    Args:
        context: Business discovery context

    Returns:
        Recommended pricing tier
    """
    score = 0

    # Business size scoring
    size_scores = {"small": 0, "medium": 1, "large": 2}
    score += size_scores.get(context.business_size, 0)

    # Call volume scoring
    volume_scores = {"low": 0, "moderate": 1, "high": 2, "very_high": 3}
    score += volume_scores.get(context.call_volume, 0)

    # Integration complexity
    score += min(len(context.integrations_needed), 3)

    # Custom requirements
    score += min(len(context.custom_requirements), 2)

    # Map score to tier
    if score <= 2:
        return PricingTier.BASIC
    elif score <= 4:
        return PricingTier.STANDARD
    elif score <= 6:
        return PricingTier.ADVANCED
    else:
        return PricingTier.ENTERPRISE


def select_proposal_type(context: BusinessContext) -> ProposalType:
    """
    Automatically select best proposal type based on discovery intel.

    Args:
        context: Business discovery context

    Returns:
        Recommended proposal type
    """
    # Check for full automation indicators
    automation_keywords = ["crm", "booking", "scheduling", "workflow", "integration"]
    needs_automation = any(
        keyword in " ".join(context.integrations_needed).lower()
        or keyword in context.current_challenges.lower()
        for keyword in automation_keywords
    )

    # Check for high volume/complexity
    is_high_volume = context.call_volume in ["high", "very_high"]
    is_large = context.business_size in ["medium", "large"]

    # Selection logic
    if needs_automation and (is_high_volume or is_large):
        return ProposalType.FULL_AUTOMATION_SUITE
    elif is_high_volume or len(context.integrations_needed) >= 2:
        return ProposalType.VOICE_AI_PRO
    else:
        return ProposalType.VOICE_AI_BASE


class TemplateSlot:
    """Template slot for variable substitution."""

    PATTERN = re.compile(r'\{\{(\w+)\}\}')

    @classmethod
    def find_slots(cls, template: str) -> List[str]:
        """Find all slot names in a template."""
        return cls.PATTERN.findall(template)

    @classmethod
    def fill_slots(cls, template: str, values: Dict[str, str]) -> str:
        """Fill all slots with provided values."""
        result = template
        for slot_name, value in values.items():
            result = result.replace(f"{{{{{slot_name}}}}}", str(value))
        return result


class ProposalTemplateEngine:
    """
    Enterprise proposal template engine for AgileAdapt.

    Generates personalized proposals for Australian Voice AI market
    using discovery intelligence and configurable templates.
    """

    TEMPLATES_DIR = Path("/mnt/e/genesis-system/templates/proposals")

    def __init__(self, templates_dir: Optional[Path] = None):
        """
        Initialize template engine.

        Args:
            templates_dir: Custom templates directory (optional)
        """
        self.templates_dir = templates_dir or self.TEMPLATES_DIR
        self._template_cache: Dict[str, str] = {}

    def load_template(self, proposal_type: ProposalType) -> str:
        """
        Load template file for given proposal type.

        Args:
            proposal_type: Type of proposal template

        Returns:
            Template content as string
        """
        cache_key = proposal_type.value

        if cache_key in self._template_cache:
            return self._template_cache[cache_key]

        template_path = self.templates_dir / f"{proposal_type.value}.md"

        if not template_path.exists():
            raise FileNotFoundError(f"Template not found: {template_path}")

        content = template_path.read_text(encoding='utf-8')
        self._template_cache[cache_key] = content
        return content

    def _format_pain_points(self, pain_points: List[str]) -> str:
        """Format pain points as bullet list."""
        if not pain_points:
            return "- Managing incoming calls efficiently\n- Missing potential customers after hours\n- Staff overwhelmed with routine inquiries"
        return "\n".join(f"- {point}" for point in pain_points)

    def _format_integrations(self, integrations: List[str]) -> str:
        """Format integrations list."""
        if not integrations:
            return "Standard phone system integration"
        return ", ".join(integrations)

    def _generate_pricing_table(
        self,
        proposal_type: ProposalType,
        pricing_tier: PricingTier,
        monthly_price: int,
        buildout_price: int
    ) -> str:
        """Generate formatted pricing table."""
        total = monthly_price + buildout_price

        table = f"""| Item | Investment |
|------|-----------|
| **One-Time Setup** | ${buildout_price:,} |
| **Monthly Subscription** | ${monthly_price:,}/month |
| **First Month Total** | ${total:,} |

*All prices in AUD. No hidden fees. Cancel anytime after 3-month minimum term.*"""

        return table

    def _generate_solution_description(
        self,
        proposal_type: ProposalType,
        context: BusinessContext
    ) -> str:
        """Generate solution description based on type."""

        descriptions = {
            ProposalType.VOICE_AI_BASE: f"""Our **Voice AI Base** solution provides {context.business_name} with:

- **24/7 AI Receptionist** - Never miss a call, even after hours
- **Natural Conversations** - Australian-accented AI that sounds human
- **Call Screening & Routing** - Qualified leads transferred to the right person
- **Message Taking** - Accurate messages delivered via SMS or email
- **Basic Analytics** - See your call patterns and peak times

Perfect for businesses wanting to improve call handling without complexity.""",

            ProposalType.VOICE_AI_PRO: f"""Our **Voice AI Pro** solution gives {context.business_name} enhanced capabilities:

- **Everything in Base**, plus:
- **Smart Call Qualification** - AI asks discovery questions before transfer
- **Custom Call Flows** - Tailored scripts for your specific business needs
- **Multi-Location Support** - Route calls to the right branch automatically
- **Advanced Analytics Dashboard** - Deep insights into call performance
- **Priority Support** - 4-hour response time guaranteed
- **CRM Integration** - Sync call data with your existing systems

Ideal for growing businesses that need intelligent call handling.""",

            ProposalType.FULL_AUTOMATION_SUITE: f"""Our **Full Automation Suite** transforms {context.business_name}'s operations:

- **Everything in Pro**, plus:
- **Booking & Scheduling AI** - Customers book appointments directly
- **Workflow Automation** - Trigger actions in your tools automatically
- **Multi-Channel Support** - Voice, SMS, and web chat unified
- **Custom Integrations** - Connect to any tool your business uses
- **Dedicated Success Manager** - Quarterly reviews and optimization
- **White-Glove Onboarding** - We handle everything during setup

The complete solution for businesses ready to fully automate customer communications."""
        }

        return descriptions.get(proposal_type, descriptions[ProposalType.VOICE_AI_BASE])

    def _generate_next_steps(self, context: BusinessContext) -> str:
        """Generate next steps section."""
        follow_up = context.follow_up_date or "within 48 hours"

        return f"""1. **Review this proposal** - Take your time, we're here for questions
2. **Schedule a demo** - See the AI in action with a live demonstration
3. **Customize your solution** - We'll tailor everything to {context.business_name}'s needs
4. **Go live in 7 days** - From approval to live calls in about a week

**Ready to proceed?** Reply to this email or call us {follow_up}.

We're excited to help {context.business_name} never miss another opportunity!"""

    def generate_proposal(
        self,
        context: BusinessContext,
        proposal_type: Optional[ProposalType] = None,
        pricing_tier: Optional[PricingTier] = None
    ) -> ProposalResult:
        """
        Generate a complete proposal from business context.

        Args:
            context: Business discovery context
            proposal_type: Override automatic type selection
            pricing_tier: Override automatic tier selection

        Returns:
            ProposalResult with rendered content and metadata
        """
        # Auto-select if not provided
        if proposal_type is None:
            proposal_type = select_proposal_type(context)

        if pricing_tier is None:
            pricing_tier = determine_pricing_tier(context)

        # Calculate pricing
        monthly_price = calculate_monthly_price(proposal_type, pricing_tier)
        buildout_price = calculate_buildout_price(proposal_type, pricing_tier)

        # Load and fill template
        template = self.load_template(proposal_type)

        # Prepare slot values
        slot_values = {
            "business_name": context.business_name,
            "contact_name": context.contact_name,
            "industry": context.industry,
            "pain_points_summary": self._format_pain_points(context.pain_points),
            "current_challenges": context.current_challenges or "Improving customer communication efficiency",
            "solution_description": self._generate_solution_description(proposal_type, context),
            "pricing_table": self._generate_pricing_table(
                proposal_type, pricing_tier, monthly_price, buildout_price
            ),
            "integrations_list": self._format_integrations(context.integrations_needed),
            "next_steps": self._generate_next_steps(context),
            "proposal_date": datetime.now().strftime("%d %B %Y"),
            "valid_until": datetime.now().strftime("%d %B %Y"),  # 30 days validity
            "monthly_price": str(monthly_price),
            "buildout_price": str(buildout_price),
            "total_first_month": str(monthly_price + buildout_price),
        }

        # Fill template slots
        content = TemplateSlot.fill_slots(template, slot_values)

        return ProposalResult(
            content=content,
            proposal_type=proposal_type,
            pricing_tier=pricing_tier,
            monthly_price=monthly_price,
            buildout_price=buildout_price,
            total_first_month=monthly_price + buildout_price,
            business_context=context,
            generated_at=datetime.now().isoformat()
        )

    def get_available_templates(self) -> List[ProposalType]:
        """List all available proposal templates."""
        available = []
        for ptype in ProposalType:
            template_path = self.templates_dir / f"{ptype.value}.md"
            if template_path.exists():
                available.append(ptype)
        return available

    def validate_template(self, proposal_type: ProposalType) -> Dict[str, Any]:
        """
        Validate a template file for required slots.

        Args:
            proposal_type: Template to validate

        Returns:
            Validation result with found/missing slots
        """
        required_slots = [
            "business_name",
            "pain_points_summary",
            "solution_description",
            "pricing_table",
            "next_steps"
        ]

        template = self.load_template(proposal_type)
        found_slots = TemplateSlot.find_slots(template)

        missing = [s for s in required_slots if s not in found_slots]
        extra = [s for s in found_slots if s not in required_slots]

        return {
            "valid": len(missing) == 0,
            "found_slots": found_slots,
            "required_slots": required_slots,
            "missing_slots": missing,
            "extra_slots": extra
        }

    def clear_cache(self):
        """Clear template cache."""
        self._template_cache.clear()


# Convenience functions for quick access
def generate_voice_ai_base_proposal(context: BusinessContext) -> ProposalResult:
    """Generate Voice AI Base proposal."""
    engine = ProposalTemplateEngine()
    return engine.generate_proposal(context, ProposalType.VOICE_AI_BASE)


def generate_voice_ai_pro_proposal(context: BusinessContext) -> ProposalResult:
    """Generate Voice AI Pro proposal."""
    engine = ProposalTemplateEngine()
    return engine.generate_proposal(context, ProposalType.VOICE_AI_PRO)


def generate_full_automation_proposal(context: BusinessContext) -> ProposalResult:
    """Generate Full Automation Suite proposal."""
    engine = ProposalTemplateEngine()
    return engine.generate_proposal(context, ProposalType.FULL_AUTOMATION_SUITE)


if __name__ == "__main__":
    # Quick test
    context = BusinessContext(
        business_name="Smith's Plumbing",
        contact_name="John Smith",
        industry="Trades - Plumbing",
        pain_points=[
            "Missing calls while on jobs",
            "After-hours calls going to voicemail",
            "Spending too much time on phone quotes"
        ],
        call_volume="moderate",
        business_size="small"
    )

    engine = ProposalTemplateEngine()
    result = engine.generate_proposal(context)

    print(f"Generated {result.proposal_type.value} proposal")
    print(f"Monthly: ${result.monthly_price}, Buildout: ${result.buildout_price}")
    print(f"First month total: ${result.total_first_month}")
