"""
Purchase Order Event Consumer
Listens for PO events and sends email notifications to suppliers
"""
import json
import structlog
from pathlib import Path
from typing import Dict, Any
from jinja2 import Environment, FileSystemLoader
from datetime import datetime

from shared.messaging.rabbitmq import RabbitMQClient
from app.services.email_service import EmailService

logger = structlog.get_logger()


class POEventConsumer:
    """
    Consumes purchase order events from RabbitMQ and sends notifications
    """

    def __init__(self, email_service: EmailService):
        self.email_service = email_service

        # Setup Jinja2 template environment
        template_dir = Path(__file__).parent.parent / 'templates'
        self.jinja_env = Environment(
            loader=FileSystemLoader(str(template_dir)),
            autoescape=True
        )

    async def consume_po_approved_event(
        self,
        rabbitmq_client: RabbitMQClient
    ):
        """
        Start consuming PO approved events from RabbitMQ
        """
        async def process_message(message):
            """Process a single PO approved event message"""
            try:
                async with message.process():
                    # Parse event data
                    event_data = json.loads(message.body.decode())
                    logger.info(
                        "Received PO approved event",
                        event_id=event_data.get('event_id'),
                        po_id=event_data.get('data', {}).get('po_id')
                    )

                    # Send notification email
                    success = await self.send_po_approved_email(event_data)

                    if success:
                        logger.info(
                            "PO approved email sent successfully",
                            po_id=event_data.get('data', {}).get('po_id')
                        )
                    else:
                        logger.error(
                            "Failed to send PO approved email",
                            po_id=event_data.get('data', {}).get('po_id')
                        )

            except Exception as e:
                logger.error(
                    "Error processing PO approved event",
                    error=str(e),
                    exc_info=True
                )

        # Start consuming events
        await rabbitmq_client.consume_events(
            exchange_name="procurement.events",
            queue_name="notification.po.approved",
            routing_key="po.approved",
            callback=process_message
        )

        logger.info("Started consuming PO approved events")

    async def send_po_approved_email(self, event_data: Dict[str, Any]) -> bool:
        """
        Send PO approved email to supplier

        Args:
            event_data: Full event payload from RabbitMQ

        Returns:
            bool: True if email sent successfully
        """
        try:
            # Extract data from event
            data = event_data.get('data', {})

            # Required fields
            supplier_email = data.get('supplier_email')
            if not supplier_email:
                logger.warning(
                    "No supplier email in event, skipping notification",
                    po_id=data.get('po_id')
                )
                return False

            # Prepare template context
            context = self._prepare_email_context(data)

            # Render HTML email from template
            template = self.jinja_env.get_template('po_approved_email.html')
            html_content = template.render(**context)

            # Prepare plain text version (fallback)
            text_content = self._generate_text_email(context)

            # Send email
            subject = f"New Purchase Order #{data.get('po_number', 'N/A')}"

            success = await self.email_service.send_email(
                to_email=supplier_email,
                subject=subject,
                text_content=text_content,
                html_content=html_content,
                from_name=context.get('bakery_name', 'Bakery Management System'),
                reply_to=context.get('bakery_email')
            )

            return success

        except Exception as e:
            logger.error(
                "Error sending PO approved email",
                error=str(e),
                po_id=data.get('po_id'),
                exc_info=True
            )
            return False

    def _prepare_email_context(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Prepare context data for email template

        Args:
            data: Event data from RabbitMQ

        Returns:
            Dict with all template variables
        """
        # Extract items and format them
        items = data.get('items', [])
        formatted_items = []
        for item in items:
            formatted_items.append({
                'product_name': item.get('product_name', 'N/A'),
                'ordered_quantity': f"{item.get('ordered_quantity', 0):.2f}",
                'unit_of_measure': item.get('unit_of_measure', 'units'),
                'unit_price': f"{item.get('unit_price', 0):.2f}",
                'line_total': f"{item.get('line_total', 0):.2f}"
            })

        # Determine currency symbol
        currency = data.get('currency', 'EUR')
        currency_symbol = '€' if currency == 'EUR' else '$'

        # Format dates
        order_date = self._format_datetime(data.get('approved_at'))
        required_delivery_date = self._format_date(data.get('required_delivery_date'))

        # Build context
        context = {
            # PO Details
            'po_number': data.get('po_number', 'N/A'),
            'order_date': order_date,
            'required_delivery_date': required_delivery_date or 'To be confirmed',
            'total_amount': f"{data.get('total_amount', 0):.2f}",
            'currency': currency,
            'currency_symbol': currency_symbol,

            # Supplier Info
            'supplier_name': data.get('supplier_name', 'Valued Supplier'),

            # Items
            'items': formatted_items,

            # Bakery Info (these should come from tenant settings, defaulting for now)
            'bakery_name': 'Your Bakery Name',  # TODO: Fetch from tenant settings
            'bakery_email': 'orders@yourbakery.com',  # TODO: Fetch from tenant settings
            'bakery_phone': '+34 XXX XXX XXX',  # TODO: Fetch from tenant settings
            'bakery_address': 'Your Bakery Address',  # TODO: Fetch from tenant settings
            'delivery_address': 'Bakery Delivery Address',  # TODO: Fetch from PO/tenant
            'contact_person': 'Bakery Manager',  # TODO: Fetch from tenant settings
            'contact_phone': '+34 XXX XXX XXX',  # TODO: Fetch from tenant settings

            # Payment & Delivery Terms
            'payment_terms': 'Net 30 days',  # TODO: Fetch from supplier/tenant settings
            'delivery_instructions': 'Please deliver to main entrance between 7-9 AM',  # TODO: Fetch from PO
            'notes': None,  # TODO: Extract from PO notes if available
        }

        return context

    def _generate_text_email(self, context: Dict[str, Any]) -> str:
        """
        Generate plain text version of email

        Args:
            context: Template context

        Returns:
            Plain text email content
        """
        items_text = "\n".join([
            f"  - {item['product_name']}: {item['ordered_quantity']} {item['unit_of_measure']} "
            f"× {context['currency_symbol']}{item['unit_price']} = {context['currency_symbol']}{item['line_total']}"
            for item in context['items']
        ])

        text = f"""
New Purchase Order #{context['po_number']}

Dear {context['supplier_name']},

We would like to place the following purchase order:

ORDER DETAILS:
- PO Number: {context['po_number']}
- Order Date: {context['order_date']}
- Required Delivery: {context['required_delivery_date']}
- Delivery Address: {context['delivery_address']}

ORDER ITEMS:
{items_text}

TOTAL AMOUNT: {context['currency_symbol']}{context['total_amount']} {context['currency']}

PAYMENT & DELIVERY:
- Payment Terms: {context['payment_terms']}
- Delivery Instructions: {context['delivery_instructions']}
- Contact Person: {context['contact_person']}
- Phone: {context['contact_phone']}

Please confirm receipt of this order by replying to this email.

Thank you for your continued partnership.

Best regards,
{context['bakery_name']}
{context['bakery_address']}
Phone: {context['bakery_phone']}
Email: {context['bakery_email']}

---
This is an automated email from your Bakery Management System.
"""
        return text.strip()

    def _format_datetime(self, iso_datetime: str) -> str:
        """Format ISO datetime string to readable format"""
        if not iso_datetime:
            return 'N/A'
        try:
            dt = datetime.fromisoformat(iso_datetime.replace('Z', '+00:00'))
            return dt.strftime('%B %d, %Y at %H:%M')
        except Exception:
            return iso_datetime

    def _format_date(self, iso_date: str) -> str:
        """Format ISO date string to readable format"""
        if not iso_date:
            return None
        try:
            if 'T' in iso_date:
                dt = datetime.fromisoformat(iso_date.replace('Z', '+00:00'))
            else:
                dt = datetime.fromisoformat(iso_date)
            return dt.strftime('%B %d, %Y')
        except Exception:
            return iso_date
