from typing import List, Optional
from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException, status, Query, Response
from fastapi.responses import StreamingResponse
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_current_user
from app.db.session import get_db
from app.services.vendor_service import (
    DEFAULT_NOTIFICATION_SUBJECT,
    DEFAULT_NOTIFICATION_MESSAGE,
)
from app.schemas.vendor import (
    VendorCreate,
    VendorOut,
    VendorUpdate,
    VendorListResponse,
    VendorDetailsOut,
    ExportRequest,
    ExportScrapingResultsRequest,
    ExportCombinedReportRequest,
    NotificationRequest,
    SendCustomNotificationRequest,
    ViolationOut,
)
from app.services import vendor_service

router = APIRouter()


@router.get("/vendors", response_model=VendorListResponse)
async def list_vendors(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    sort_by: Optional[str] = Query(None, regex="^(name|violation_count|average_discount)$"),
    search: Optional[str] = None,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> VendorListResponse:
    vendors, total = await vendor_service.list_vendors(
        db, page=page, page_size=page_size, sort_by=sort_by, search=search
    )
    items: List[VendorOut] = []
    for v in vendors:
        count, avg = await vendor_service.compute_metrics(db, v)
        items.append(
            VendorOut(
                id=v.id,
                name=v.name,
                brand_name=v.brand_name,
                email=v.email,
                website_url=v.website_url,
                is_active=v.is_active,
                violation_count=count,
                average_discount=round(avg, 2),
            )
        )
    return VendorListResponse(items=items, total=total, page=page, page_size=page_size)


@router.post("/vendors", response_model=VendorOut, status_code=status.HTTP_201_CREATED)
async def create_vendor(
    payload: VendorCreate,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> VendorOut:
    vendor = await vendor_service.create_vendor(
        db,
        name=payload.name,
        brand_name=payload.brand_name,
        email=payload.email,
        website_url=payload.website_url,
        is_active=payload.is_active,
    )
    return VendorOut.model_validate(vendor)


@router.get("/vendors/{vendor_id}", response_model=VendorOut)
async def get_vendor(vendor_id: UUID, db: AsyncSession = Depends(get_db), current_user=Depends(get_current_user)) -> VendorOut:
    vendor = await vendor_service.get_vendor(db, vendor_id=vendor_id)
    count, avg = await vendor_service.compute_metrics(db, vendor)
    return VendorOut(
        id=vendor.id,
        name=vendor.name,
        brand_name=vendor.brand_name,
        email=vendor.email,
        website_url=vendor.website_url,
        is_active=vendor.is_active,
        violation_count=count,
        average_discount=round(avg, 2),
    )


@router.put("/vendors/{vendor_id}", response_model=VendorOut)
async def edit_vendor(
    vendor_id: UUID,
    payload: VendorUpdate,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> VendorOut:
    data = payload.model_dump(exclude_none=True)
    vendor = await vendor_service.update_vendor(
        db, vendor_id=vendor_id, data=data, changed_by=str(current_user.email)
    )
    count, avg = await vendor_service.compute_metrics(db, vendor)
    return VendorOut(
        id=vendor.id,
        name=vendor.name,
        brand_name=vendor.brand_name,
        email=vendor.email,
        website_url=vendor.website_url,
        is_active=vendor.is_active,
        violation_count=count,
        average_discount=round(avg, 2),
    )


@router.delete("/vendors/{vendor_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_vendor(vendor_id: UUID, db: AsyncSession = Depends(get_db), current_user=Depends(get_current_user)):
    await vendor_service.delete_vendor(db, vendor_id=vendor_id)
    return Response(status_code=status.HTTP_204_NO_CONTENT)


@router.post("/vendors/export")
async def export_violations(
    payload: ExportRequest,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> StreamingResponse:
    content = await vendor_service.export_violations(
        db, 
        vendor_ids=payload.vendor_ids
    )
    return StreamingResponse(
        iter([content]),
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": "attachment; filename=violations.xlsx"},
    )


@router.get("/vendors/{vendor_id}/details", response_model=VendorDetailsOut)
async def vendor_details(
    vendor_id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> VendorDetailsOut:
    vendor, violations = await vendor_service.get_vendor_with_violations(db, vendor_id=vendor_id)
    count, avg = await vendor_service.compute_metrics(db, vendor)
    return VendorDetailsOut(
        id=vendor.id,
        name=vendor.name,
        brand_name=vendor.brand_name,
        email=vendor.email,
        website_url=vendor.website_url,
        is_active=vendor.is_active,
        violation_count=count,
        average_discount=round(avg, 2),
        violations=[ViolationOut.model_validate(v) for v in violations],
    )


@router.post("/vendors/notify")
async def send_notifications(
    payload: NotificationRequest,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> dict:
    await vendor_service.send_violation_notifications(db, violation_ids=payload.violation_ids)
    return {"message": "Notifications sent"}


@router.post("/vendors/notify-custom/prefill")
async def get_notification_prefill(
    payload: NotificationRequest,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> dict:
    """
    Get pre-fill data for the notification modal.
    
    Returns:
    - recipient_email: Auto-fetched from vendor (if single vendor)
    - subject: Default subject template
    - message_body: Default message template
    - violation_details: Details of violations
    """
    violations_data = await vendor_service.get_violations_prefill_data(db, violation_ids=payload.violation_ids)
    return violations_data

@router.post("/vendors/notify-custom")
async def send_custom_notification(
    payload: SendCustomNotificationRequest,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> dict:
    """
    Send custom violation notification email to ANY email address provided.
    
    REQUIRED fields:
    - violation_ids: List of violation IDs to include
    - recipient_email: Email address where the notification should be sent
    
    OPTIONAL fields (will use defaults if not provided):
    - subject: Email subject (defaults to "Price Violation Notice – Immediate Attention Required")
    - message_body: Email body in HTML format (defaults to standard template with all variables)
    
    Template variables supported in message_body:
    - {{VIOLATIONS}}: Placeholder for product violation details (repeats for each selected violation)
    - {{VENDOR_NAME}}: Vendor name (substituted once in header/footer)
    - {{PRODUCT_NAME}}: Product name (used within {{VIOLATIONS}} section for each violation)
    - {{MSP}}: Minimum Selling Price with ₹ currency (used within {{VIOLATIONS}} section)
    - {{SCRAPED_PRICE}}: Detected selling price with ₹ currency (used within {{VIOLATIONS}} section)
    - {{PRODUCT_URL}}: Link to product listing (used within {{VIOLATIONS}} section)
    - {{VIOLATION_DATE}}: Date violation was detected (used within {{VIOLATIONS}} section)
    - {{COMPANY_NAME}}: Your company name
    - {{SUPPORT_EMAIL}}: Support email address
    
    USAGE PATTERN:
    Include {{VIOLATIONS}} placeholder in your message where product details should appear.
    The system will replace {{VIOLATIONS}} with product details for each selected violation.
    Example: "Dear {{VENDOR_NAME}},\n\n...intro text...\n\n{{VIOLATIONS}}\n\n...closing text..."
    
    When 2 violations selected, {{VIOLATIONS}} becomes:
    - Product 1 details (all variables substituted)
    - Product 2 details (all variables substituted)
    """
    import logging
    logger = logging.getLogger(__name__)
    
    # Log received payload with FULL details
    logger.info(f"[/notify-custom] Request received:")
    logger.info(f"  - violation_ids: {payload.violation_ids}")
    logger.info(f"  - recipient_email: {payload.recipient_email}")
    logger.info(f"  - subject provided: {bool(payload.subject)}")
    logger.info(f"  - message_body provided: {bool(payload.message_body)}")
    
    if payload.message_body:
        logger.info(f"  - message_body LENGTH: {len(payload.message_body)} chars")
        logger.info(f"  - message_body PREVIEW (first 300 chars): {payload.message_body[:300]}")
        logger.info(f"  - message_body IS HTML: {'<' in payload.message_body}")
    else:
        logger.info(f"  - message_body is EMPTY/NULL - will use DEFAULT template")
    
    # Use defaults ONLY if not provided
    # If message_body is provided (even if just "heelo"), use it as-is
    subject = payload.subject if payload.subject else DEFAULT_NOTIFICATION_SUBJECT
    message_body = payload.message_body if payload.message_body else DEFAULT_NOTIFICATION_MESSAGE
    recipient_email = payload.recipient_email
    
    logger.info(f"[/notify-custom] FINAL content to send:")
    logger.info(f"  - Subject: {subject[:100]}")
    logger.info(f"  - Message_body source: {'CUSTOM (from user)' if payload.message_body else 'DEFAULT template'}")
    logger.info(f"  - Message_body length: {len(message_body)} chars")
    logger.info(f"  - Will send email to: {recipient_email}")
    
    await vendor_service.send_custom_violation_notification(
        db,
        violation_ids=payload.violation_ids,
        recipient_email=payload.recipient_email,
        subject=subject,
        message_body=message_body,
    )
    return {"message": f"Custom notification sent to {payload.recipient_email}"}

@router.post("/vendors/export-scraping-results")
async def export_scraping_results(
    payload: ExportScrapingResultsRequest,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> StreamingResponse:
    """
    Export scraping results to XLSX.
    
    Optional filters:
    - vendor_id: Filter by vendor
    - product_id: Filter by product
    - status_filter: Filter by compliance status ('compliant', 'violation', 'complaining', 'unknown')
    """
    content = await vendor_service.export_scraping_results(
        db,
        vendor_id=payload.vendor_id,
        product_id=payload.product_id,
        status_filter=payload.status_filter
    )
    return StreamingResponse(
        iter([content]),
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": "attachment; filename=scraping_results.xlsx"},
    )


@router.post("/vendors/export-combined-report")
async def export_combined_report(
    payload: ExportCombinedReportRequest,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
) -> StreamingResponse:
    """
    Export combined report with both violations and scraping results.
    
    Optional filters:
    - vendor_id: Filter by vendor
    - product_id: Filter by product
    """
    content = await vendor_service.export_combined_report(
        db,
        vendor_id=payload.vendor_id,
        product_id=payload.product_id
    )
    return StreamingResponse(
        iter([content]),
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": "attachment; filename=combined_report.xlsx"},
    )