"""
Email Templates API Router
Management of system and customer-specific email templates
"""
from typing import List, Optional, Dict, Any
from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel, Json
from app.core.database import execute_query
import json
import logging
from datetime import datetime

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/email-templates", tags=["Email Templates"])

# --- Models ---

class EmailTemplateBase(BaseModel):
    name: str
    slug: str
    subject: str
    body: str
    category: str = "general"
    description: Optional[str] = None
    variables: Dict[str, str] = {}
    customer_id: Optional[int] = None

class EmailTemplateCreate(EmailTemplateBase):
    pass

class EmailTemplateUpdate(BaseModel):
    name: Optional[str] = None
    subject: Optional[str] = None
    body: Optional[str] = None
    category: Optional[str] = None
    description: Optional[str] = None
    variables: Optional[Dict[str, str]] = None
    customer_id: Optional[int] = None

class EmailTemplate(BaseModel):
    id: int
    name: str
    slug: str
    subject: str
    body: str
    category: str
    description: Optional[str] = None
    variables: Optional[Dict[str, str]] = {}
    is_system: bool
    customer_id: Optional[int] = None
    created_at: datetime
    updated_at: datetime

# --- Endpoints ---

@router.get("/", response_model=List[EmailTemplate])
async def get_email_templates(
    category: Optional[str] = None, 
    customer_id: Optional[int] = None
):
    """
    Get all email templates.
    Optionally filter by category or specific customer.
    """
    sql = """
        SELECT id, name, slug, subject, body, category, description, variables, 
               is_system, customer_id, created_at, updated_at
        FROM email_templates
        WHERE 1=1
    """
    params = []
    
    if category:
        sql += " AND category = %s"
        params.append(category)
        
    if customer_id is not None:
        # Fetch global templates (customer_id IS NULL) AND this specific customer's templates
        sql += " AND (customer_id IS NULL OR customer_id = %s)"
        params.append(customer_id)
        
    sql += " ORDER BY category, name"
    
    rows = execute_query(sql, tuple(params))
    return rows

@router.get("/{template_id}", response_model=EmailTemplate)
async def get_email_template(template_id: int):
    """Get a single template by ID"""
    sql = """
        SELECT id, name, slug, subject, body, category, description, variables, 
               is_system, customer_id, created_at, updated_at
        FROM email_templates
        WHERE id = %s
    """
    rows = execute_query(sql, (template_id,))
    if not rows:
        raise HTTPException(status_code=404, detail="Template not found")
    return rows[0]

@router.post("/", response_model=EmailTemplate)
async def create_email_template(template: EmailTemplateCreate):
    """Create a new email template"""
    # Check for slug uniqueness
    check_sql = "SELECT id FROM email_templates WHERE slug = %s AND (customer_id IS NULL OR customer_id = %s)"
    check_val = (template.customer_id,) if template.customer_id else (None,)
    # If customer_id is None, we check where customer_id IS NULL.
    # Actually, SQL `slug = %s AND customer_id = %s` works if we handle NULL correctly in python -> SQL
    
    # Simpler uniqueness check in python logic tailored to the constraint
    if template.customer_id:
        existing = execute_query(
            "SELECT id FROM email_templates WHERE slug = %s AND customer_id = %s", 
            (template.slug, template.customer_id)
        )
    else:
        existing = execute_query(
            "SELECT id FROM email_templates WHERE slug = %s AND customer_id IS NULL", 
            (template.slug,)
        )
        
    if existing:
        raise HTTPException(status_code=400, detail=f"A template with slug '{template.slug}' already exists for this context.")

    sql = """
        INSERT INTO email_templates 
        (name, slug, subject, body, category, description, variables, customer_id, is_system)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, FALSE)
        RETURNING id, name, slug, subject, body, category, description, variables, 
                  is_system, customer_id, created_at, updated_at
    """
    
    params = (
        template.name,
        template.slug,
        template.subject,
        template.body,
        template.category,
        template.description,
        json.dumps(template.variables),
        template.customer_id
    )
    
    try:
        rows = execute_query(sql, params)
        return rows[0]
    except Exception as e:
        logger.error(f"Error creating template: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@router.put("/{template_id}", response_model=EmailTemplate)
async def update_email_template(template_id: int, update: EmailTemplateUpdate):
    """Update an existing template"""
    # Verify existence
    current = execute_query("SELECT is_system FROM email_templates WHERE id = %s", (template_id,))
    if not current:
        raise HTTPException(status_code=404, detail="Template not found")
        
    is_system = current[0]['is_system']
    
    # Prevent changing critical fields on system templates?
    # Usually we allow editing subject/body, but maybe not slug.
    # For now, we allow everything except slug changes on system templates if defined so,
    # but the logic below updates whatever is provided.
    
    fields = []
    params = []
    
    if update.name is not None:
        fields.append("name = %s")
        params.append(update.name)
        
    if update.subject is not None:
        fields.append("subject = %s")
        params.append(update.subject)
        
    if update.body is not None:
        fields.append("body = %s")
        params.append(update.body)
        
    if update.category is not None:
        fields.append("category = %s")
        params.append(update.category)
        
    if update.description is not None:
        fields.append("description = %s")
        params.append(update.description)
        
    if update.variables is not None:
        fields.append("variables = %s")
        params.append(json.dumps(update.variables))
        
    if update.customer_id is not None:
        fields.append("customer_id = %s")
        params.append(update.customer_id)

    # Don't change slug if it's a system template?
    # Usually slugs are fixed for system templates so the code can find them.
    # But for now we don't expose slug update in the provided model if we want to be strict.
    # Wait, the frontend might need to update other things.
    # Let's assume we don't update slug for now via this endpoint as per my minimalist implementation.
    
    if not fields:
        raise HTTPException(status_code=400, detail="No fields to update")
        
    fields.append("updated_at = NOW()")
    
    sql = f"UPDATE email_templates SET {', '.join(fields)} WHERE id = %s RETURNING *"
    params.append(template_id)
    
    rows = execute_query(sql, tuple(params))
    return rows[0]

@router.delete("/{template_id}")
async def delete_email_template(template_id: int):
    """Delete a template (Non-system only)"""
    current = execute_query("SELECT is_system FROM email_templates WHERE id = %s", (template_id,))
    if not current:
        raise HTTPException(status_code=404, detail="Template not found")
        
    if current[0]['is_system']:
        raise HTTPException(status_code=403, detail="Cannot delete system templates")
        
    execute_query("DELETE FROM email_templates WHERE id = %s", (template_id,))
    return {"message": "Template deleted successfully"}
