from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile, File
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_
from typing import List, Optional, Dict, Any
from datetime import datetime
import csv
import io
from app.db.session import get_db
from app.db.models import User, Customer, Segment, Notification, Delivery
from app.api.deps import get_current_user
from pydantic import BaseModel
from fastapi.responses import StreamingResponse

router = APIRouter(prefix="/customer-management", tags=["customer-management"])


class CustomerSegment(BaseModel):
    id: int
    name: str
    description: str | None = None
    filter_criteria: Dict[str, Any]
    customer_count: int
    created_at: datetime


class CustomerSegmentCreate(BaseModel):
    name: str
    description: str | None = None
    filter_criteria: Dict[str, Any]


class CustomerBulkOperation(BaseModel):
    operation: str  # "add_tags", "remove_tags", "update_status"
    customer_ids: List[int]
    data: Dict[str, Any]  # {"tags": ["vip"], "status": "active"}


class CustomerInteraction(BaseModel):
    notification_id: int
    template_name: str
    channel: str
    status: str
    sent_at: datetime | None
    opened_at: datetime | None
    clicked_at: datetime | None


class CustomerDetail(BaseModel):
    id: int
    email: str | None
    phone: str | None
    tg_chat_id: str | None
    vk_user_id: str | None
    tags: List[str]
    meta: Dict[str, Any]
    created_at: datetime
    total_notifications: int
    total_opened: int
    total_clicked: int
    last_interaction: datetime | None
    interactions: List[CustomerInteraction]


@router.get("/segments", response_model=List[CustomerSegment])
def list_segments(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """List all customer segments"""
    # Mock data for now - in a real implementation, you'd query the Segment table
    return [
        CustomerSegment(
            id=1,
            name="VIP клиенты",
            description="Клиенты с тегом 'vip'",
            filter_criteria={"tags": {"contains": "vip"}},
            customer_count=25,
            created_at=datetime.utcnow()
        ),
        CustomerSegment(
            id=2,
            name="Активные пользователи",
            description="Клиенты с активностью за последние 30 дней",
            filter_criteria={"last_interaction": {"gte": "2024-09-10"}},
            customer_count=150,
            created_at=datetime.utcnow()
        ),
        CustomerSegment(
            id=3,
            name="Email подписчики",
            description="Клиенты с email адресом",
            filter_criteria={"email": {"is_not_null": True}},
            customer_count=300,
            created_at=datetime.utcnow()
        )
    ]


@router.post("/segments", response_model=CustomerSegment)
def create_segment(
    segment_data: CustomerSegmentCreate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """Create a new customer segment"""
    # Mock implementation - in a real implementation, you'd save to database
    return CustomerSegment(
        id=4,
        name=segment_data.name,
        description=segment_data.description,
        filter_criteria=segment_data.filter_criteria,
        customer_count=0,
        created_at=datetime.utcnow()
    )


@router.get("/segments/{segment_id}/customers", response_model=List[Dict])
def get_segment_customers(
    segment_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
    skip: int = 0,
    limit: int = 100,
):
    """Get customers in a specific segment"""
    # Mock implementation - in a real implementation, you'd apply filter criteria
    customers = (
        db.query(Customer)
        .filter(Customer.tenant_id == current_user.tenant_id)
        .offset(skip)
        .limit(limit)
        .all()
    )
    
    return [
        {
            "id": c.id,
            "email": c.email,
            "phone": c.phone,
            "tags": c.tags,
            "created_at": c.created_at
        }
        for c in customers
    ]


@router.post("/bulk-operation")
def bulk_operation(
    operation: CustomerBulkOperation,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """Perform bulk operations on customers"""
    if operation.operation == "add_tags":
        new_tags = operation.data.get("tags", [])
        customers = (
            db.query(Customer)
            .filter(
                and_(
                    Customer.tenant_id == current_user.tenant_id,
                    Customer.id.in_(operation.customer_ids)
                )
            )
            .all()
        )
        
        for customer in customers:
            existing_tags = set(customer.tags or [])
            customer.tags = list(existing_tags.union(set(new_tags)))
        
        db.commit()
        
        return {"message": f"Tags added to {len(customers)} customers", "status": "success"}
    
    elif operation.operation == "remove_tags":
        tags_to_remove = operation.data.get("tags", [])
        customers = (
            db.query(Customer)
            .filter(
                and_(
                    Customer.tenant_id == current_user.tenant_id,
                    Customer.id.in_(operation.customer_ids)
                )
            )
            .all()
        )
        
        for customer in customers:
            existing_tags = set(customer.tags or [])
            customer.tags = list(existing_tags - set(tags_to_remove))
        
        db.commit()
        
        return {"message": f"Tags removed from {len(customers)} customers", "status": "success"}
    
    else:
        raise HTTPException(status_code=400, detail="Unknown operation")


@router.get("/export")
def export_customers(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
    segment_id: Optional[int] = Query(None),
    format: str = Query("csv", regex="^(csv|json)$"),
):
    """Export customers data"""
    customers = (
        db.query(Customer)
        .filter(Customer.tenant_id == current_user.tenant_id)
        .all()
    )
    
    if format == "csv":
        output = io.StringIO()
        writer = csv.writer(output)
        
        # Write header
        writer.writerow([
            "ID", "Email", "Phone", "Telegram ID", "VK ID", 
            "Tags", "Meta", "Created At"
        ])
        
        # Write data
        for customer in customers:
            writer.writerow([
                customer.id,
                customer.email or "",
                customer.phone or "",
                customer.tg_chat_id or "",
                customer.vk_user_id or "",
                ",".join(customer.tags) if customer.tags else "",
                str(customer.meta) if customer.meta else "",
                customer.created_at.isoformat() if customer.created_at else ""
            ])
        
        output.seek(0)
        
        return StreamingResponse(
            io.BytesIO(output.getvalue().encode('utf-8')),
            media_type="text/csv",
            headers={"Content-Disposition": "attachment; filename=customers.csv"}
        )
    
    else:  # JSON format
        return [
            {
                "id": c.id,
                "email": c.email,
                "phone": c.phone,
                "tg_chat_id": c.tg_chat_id,
                "vk_user_id": c.vk_user_id,
                "tags": c.tags,
                "meta": c.meta,
                "created_at": c.created_at.isoformat() if c.created_at else None
            }
            for c in customers
        ]


@router.post("/import")
async def import_customers(
    file: UploadFile = File(...),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """Import customers from CSV file"""
    if not file.filename.endswith('.csv'):
        raise HTTPException(status_code=400, detail="Only CSV files are supported")
    
    content = await file.read()
    csv_content = content.decode('utf-8')
    
    csv_reader = csv.DictReader(io.StringIO(csv_content))
    
    imported_count = 0
    errors = []
    
    for row_num, row in enumerate(csv_reader, start=2):
        try:
            # Parse tags if present
            tags = []
            if row.get('Tags'):
                tags = [tag.strip() for tag in row['Tags'].split(',') if tag.strip()]
            
            customer = Customer(
                tenant_id=current_user.tenant_id,
                email=row.get('Email') or None,
                phone=row.get('Phone') or None,
                tg_chat_id=row.get('Telegram ID') or None,
                vk_user_id=row.get('VK ID') or None,
                tags=tags,
                meta={}
            )
            
            db.add(customer)
            imported_count += 1
            
        except Exception as e:
            errors.append(f"Row {row_num}: {str(e)}")
    
    if imported_count > 0:
        db.commit()
    
    return {
        "message": f"Imported {imported_count} customers",
        "imported_count": imported_count,
        "errors": errors
    }


@router.get("/{customer_id}/detail", response_model=CustomerDetail)
def get_customer_detail(
    customer_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """Get detailed customer information with interaction history"""
    customer = (
        db.query(Customer)
        .filter(Customer.id == customer_id, Customer.tenant_id == current_user.tenant_id)
        .first()
    )
    
    if not customer:
        raise HTTPException(status_code=404, detail="Customer not found")
    
    # Get interaction history
    interactions = (
        db.query(Notification, Delivery, Customer)
        .join(Delivery, Notification.id == Delivery.notification_id)
        .join(Customer, Notification.customer_id == Customer.id)
        .filter(
            and_(
                Customer.id == customer_id,
                Customer.tenant_id == current_user.tenant_id
            )
        )
        .order_by(Notification.created_at.desc())
        .limit(50)
        .all()
    )
    
    # Calculate stats
    total_notifications = len(interactions)
    total_opened = sum(1 for _, delivery, _ in interactions if delivery.opened_at)
    total_clicked = sum(1 for _, delivery, _ in interactions if delivery.clicked_at)
    
    last_interaction = None
    if interactions:
        last_interaction = interactions[0][0].created_at
    
    # Format interactions
    interaction_list = []
    for notification, delivery, _ in interactions:
        interaction_list.append(CustomerInteraction(
            notification_id=notification.id,
            template_name=f"Template {notification.template_id}",  # You'd join with Template table
            channel=delivery.channel,
            status=delivery.status,
            sent_at=delivery.sent_at,
            opened_at=delivery.opened_at,
            clicked_at=delivery.clicked_at
        ))
    
    return CustomerDetail(
        id=customer.id,
        email=customer.email,
        phone=customer.phone,
        tg_chat_id=customer.tg_chat_id,
        vk_user_id=customer.vk_user_id,
        tags=customer.tags or [],
        meta=customer.meta or {},
        created_at=customer.created_at,
        total_notifications=total_notifications,
        total_opened=total_opened,
        total_clicked=total_clicked,
        last_interaction=last_interaction,
        interactions=interaction_list
    )
























