# app/api/v1/admin/vendors.py
"""
Vendor management endpoints for admin.

Architecture Notes:
- All business logic is in vendor_service (no direct DB operations here)
- Uses domain exceptions from app/exceptions/vendor.py
- Exception handler middleware converts domain exceptions to HTTP responses
"""

import logging

from fastapi import APIRouter, Body, Depends, Path, Query
from sqlalchemy.orm import Session

from app.api.deps import get_current_admin_api
from app.core.database import get_db
from app.exceptions import ConfirmationRequiredException
from app.services.admin_service import admin_service
from app.services.stats_service import stats_service
from app.services.vendor_service import vendor_service
from models.database.user import User
from models.schema.stats import VendorStatsResponse
from models.schema.vendor import (
    LetzshopExportRequest,
    LetzshopExportResponse,
    VendorCreate,
    VendorCreateResponse,
    VendorDetailResponse,
    VendorListResponse,
    VendorUpdate,
)

router = APIRouter(prefix="/vendors")
logger = logging.getLogger(__name__)


@router.post("", response_model=VendorCreateResponse)
def create_vendor(
    vendor_data: VendorCreate,
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Create a new vendor (storefront/brand) under an existing company (Admin only).

    This endpoint:
    1. Validates that the parent company exists
    2. Creates a new vendor record linked to the company
    3. Sets up default roles (Owner, Manager, Editor, Viewer)

    The vendor inherits owner and contact information from its parent company.
    """
    vendor = admin_service.create_vendor(db=db, vendor_data=vendor_data)
    db.commit()

    return VendorCreateResponse(
        # Vendor fields
        id=vendor.id,
        vendor_code=vendor.vendor_code,
        subdomain=vendor.subdomain,
        name=vendor.name,
        description=vendor.description,
        company_id=vendor.company_id,
        letzshop_csv_url_fr=vendor.letzshop_csv_url_fr,
        letzshop_csv_url_en=vendor.letzshop_csv_url_en,
        letzshop_csv_url_de=vendor.letzshop_csv_url_de,
        is_active=vendor.is_active,
        is_verified=vendor.is_verified,
        created_at=vendor.created_at,
        updated_at=vendor.updated_at,
        # Company info
        company_name=vendor.company.name,
        company_contact_email=vendor.company.contact_email,
        company_contact_phone=vendor.company.contact_phone,
        company_website=vendor.company.website,
        # Owner info (from company)
        owner_email=vendor.company.owner.email,
        owner_username=vendor.company.owner.username,
        login_url=f"http://localhost:8000/vendor/{vendor.subdomain}/login",
    )


@router.get("", response_model=VendorListResponse)
def get_all_vendors_admin(
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=1000),
    search: str | None = Query(None, description="Search by name or vendor code"),
    is_active: bool | None = Query(None),
    is_verified: bool | None = Query(None),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Get all vendors with filtering (Admin only)."""
    vendors, total = admin_service.get_all_vendors(
        db=db,
        skip=skip,
        limit=limit,
        search=search,
        is_active=is_active,
        is_verified=is_verified,
    )
    return VendorListResponse(vendors=vendors, total=total, skip=skip, limit=limit)


@router.get("/stats", response_model=VendorStatsResponse)
def get_vendor_statistics_endpoint(
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Get vendor statistics for admin dashboard (Admin only)."""
    stats = stats_service.get_vendor_statistics(db)

    # Use schema-compatible keys (with fallback to legacy keys)
    return VendorStatsResponse(
        total=stats.get("total", stats.get("total_vendors", 0)),
        verified=stats.get("verified", stats.get("verified_vendors", 0)),
        pending=stats.get("pending", stats.get("pending_vendors", 0)),
        inactive=stats.get("inactive", stats.get("inactive_vendors", 0)),
    )


def _build_vendor_detail_response(vendor) -> VendorDetailResponse:
    """
    Helper to build VendorDetailResponse with resolved contact info.

    Contact fields are resolved using vendor override or company fallback.
    Inheritance flags indicate if value comes from company.
    """
    contact_info = vendor.get_contact_info_with_inheritance()

    return VendorDetailResponse(
        # Vendor fields
        id=vendor.id,
        vendor_code=vendor.vendor_code,
        subdomain=vendor.subdomain,
        name=vendor.name,
        description=vendor.description,
        company_id=vendor.company_id,
        letzshop_csv_url_fr=vendor.letzshop_csv_url_fr,
        letzshop_csv_url_en=vendor.letzshop_csv_url_en,
        letzshop_csv_url_de=vendor.letzshop_csv_url_de,
        is_active=vendor.is_active,
        is_verified=vendor.is_verified,
        created_at=vendor.created_at,
        updated_at=vendor.updated_at,
        # Company info
        company_name=vendor.company.name,
        # Owner details (from company)
        owner_email=vendor.company.owner.email,
        owner_username=vendor.company.owner.username,
        # Resolved contact info with inheritance flags
        **contact_info,
        # Original company values for UI reference
        company_contact_email=vendor.company.contact_email,
        company_contact_phone=vendor.company.contact_phone,
        company_website=vendor.company.website,
        company_business_address=vendor.company.business_address,
        company_tax_number=vendor.company.tax_number,
    )


@router.get("/{vendor_identifier}", response_model=VendorDetailResponse)
def get_vendor_details(
    vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Get detailed vendor information including company and owner details (Admin only).

    Accepts either vendor ID (integer) or vendor_code (string).

    Returns vendor info with company contact details, owner info, and
    resolved contact fields (vendor override or company default).

    Raises:
        VendorNotFoundException: If vendor not found (404)
    """
    vendor = vendor_service.get_vendor_by_identifier(db, vendor_identifier)
    return _build_vendor_detail_response(vendor)


@router.put("/{vendor_identifier}", response_model=VendorDetailResponse)
def update_vendor(
    vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"),
    vendor_update: VendorUpdate = Body(...),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Update vendor information (Admin only).

    Accepts either vendor ID (integer) or vendor_code (string).

    **Can update:**
    - Basic info: name, description, subdomain
    - Marketplace URLs
    - Status: is_active, is_verified
    - Contact info: contact_email, contact_phone, website, business_address, tax_number
      (these override company defaults; set to empty to reset to inherit)

    **Cannot update:**
    - `vendor_code` (immutable)

    Raises:
        VendorNotFoundException: If vendor not found (404)
    """
    vendor = vendor_service.get_vendor_by_identifier(db, vendor_identifier)
    vendor = admin_service.update_vendor(db, vendor.id, vendor_update)
    db.commit()
    return _build_vendor_detail_response(vendor)


# NOTE: Ownership transfer is now at the Company level.
# Use PUT /api/v1/admin/companies/{id}/transfer-ownership instead.
# This endpoint is kept for backwards compatibility but may be removed in future versions.


@router.put("/{vendor_identifier}/verification", response_model=VendorDetailResponse)
def toggle_vendor_verification(
    vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"),
    verification_data: dict = Body(..., example={"is_verified": True}),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Set vendor verification status (Admin only).

    Accepts either vendor ID (integer) or vendor_code (string).

    Request body: { "is_verified": true/false }

    Raises:
        VendorNotFoundException: If vendor not found (404)
    """
    vendor = vendor_service.get_vendor_by_identifier(db, vendor_identifier)

    if "is_verified" in verification_data:
        vendor, message = vendor_service.set_verification(
            db, vendor.id, verification_data["is_verified"]
        )
        db.commit()  # ✅ ARCH: Commit at API level for transaction control
        logger.info(f"Vendor verification updated: {message}")

    return _build_vendor_detail_response(vendor)


@router.put("/{vendor_identifier}/status", response_model=VendorDetailResponse)
def toggle_vendor_status(
    vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"),
    status_data: dict = Body(..., example={"is_active": True}),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Set vendor active status (Admin only).

    Accepts either vendor ID (integer) or vendor_code (string).

    Request body: { "is_active": true/false }

    Raises:
        VendorNotFoundException: If vendor not found (404)
    """
    vendor = vendor_service.get_vendor_by_identifier(db, vendor_identifier)

    if "is_active" in status_data:
        vendor, message = vendor_service.set_status(
            db, vendor.id, status_data["is_active"]
        )
        db.commit()  # ✅ ARCH: Commit at API level for transaction control
        logger.info(f"Vendor status updated: {message}")

    return _build_vendor_detail_response(vendor)


@router.delete("/{vendor_identifier}")
def delete_vendor(
    vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"),
    confirm: bool = Query(False, description="Must be true to confirm deletion"),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Delete vendor and all associated data (Admin only).

    Accepts either vendor ID (integer) or vendor_code (string).

    ⚠️ **WARNING: This is destructive and will delete:**
    - Vendor account
    - All products
    - All orders
    - All customers
    - All team members

    Requires confirmation parameter: `confirm=true`

    Raises:
        ConfirmationRequiredException: If confirm=true not provided (400)
        VendorNotFoundException: If vendor not found (404)
    """
    if not confirm:
        raise ConfirmationRequiredException(
            operation="delete_vendor",
            message="Deletion requires confirmation parameter: confirm=true",
        )

    vendor = vendor_service.get_vendor_by_identifier(db, vendor_identifier)
    message = admin_service.delete_vendor(db, vendor.id)
    db.commit()
    return {"message": message}


# ============================================================================
# LETZSHOP EXPORT
# ============================================================================


@router.get("/{vendor_identifier}/export/letzshop")
def export_vendor_products_letzshop(
    vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"),
    language: str = Query(
        "en", description="Language for title/description (en, fr, de)"
    ),
    include_inactive: bool = Query(False, description="Include inactive products"),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Export vendor products in Letzshop CSV format (Admin only).

    Generates a Google Shopping compatible CSV file for Letzshop marketplace.
    The file uses tab-separated values and includes all required Letzshop fields.

    **Supported languages:** en, fr, de

    **CSV Format:**
    - Delimiter: Tab (\\t)
    - Encoding: UTF-8
    - Fields: id, title, description, price, availability, image_link, etc.

    Returns:
        CSV file as attachment (vendor_code_letzshop_export.csv)
    """
    from fastapi.responses import Response

    from app.services.letzshop_export_service import letzshop_export_service

    vendor = vendor_service.get_vendor_by_identifier(db, vendor_identifier)

    csv_content = letzshop_export_service.export_vendor_products(
        db=db,
        vendor_id=vendor.id,
        language=language,
        include_inactive=include_inactive,
    )

    filename = f"{vendor.vendor_code.lower()}_letzshop_export.csv"

    return Response(
        content=csv_content,
        media_type="text/csv; charset=utf-8",
        headers={
            "Content-Disposition": f'attachment; filename="{filename}"',
        },
    )


@router.post("/{vendor_identifier}/export/letzshop", response_model=LetzshopExportResponse)
def export_vendor_products_letzshop_to_folder(
    vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"),
    request: LetzshopExportRequest = None,
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Export vendor products to Letzshop pickup folder (Admin only).

    Generates CSV files for all languages (FR, DE, EN) and places them in a folder
    that Letzshop scheduler can fetch from. This is the preferred method for
    automated product sync.

    **Behavior:**
    - Creates CSV files for each language (fr, de, en)
    - Places files in: exports/letzshop/{vendor_code}/
    - Filename format: {vendor_code}_products_{language}.csv

    Returns:
        JSON with export status and file paths
    """
    import os
    from datetime import UTC, datetime
    from pathlib import Path as FilePath

    from app.services.letzshop_export_service import letzshop_export_service

    vendor = vendor_service.get_vendor_by_identifier(db, vendor_identifier)

    include_inactive = request.include_inactive if request else False

    # Track export start time
    started_at = datetime.now(UTC)

    # Create export directory
    export_dir = FilePath(f"exports/letzshop/{vendor.vendor_code.lower()}")
    export_dir.mkdir(parents=True, exist_ok=True)

    exported_files = []
    languages = ["fr", "de", "en"]
    total_records = 0
    failed_count = 0

    for lang in languages:
        try:
            csv_content = letzshop_export_service.export_vendor_products(
                db=db,
                vendor_id=vendor.id,
                language=lang,
                include_inactive=include_inactive,
            )

            filename = f"{vendor.vendor_code.lower()}_products_{lang}.csv"
            filepath = export_dir / filename

            with open(filepath, "w", encoding="utf-8") as f:
                f.write(csv_content)

            # Count lines (minus header)
            line_count = csv_content.count("\n")
            if line_count > 0:
                total_records = max(total_records, line_count - 1)

            exported_files.append({
                "language": lang,
                "filename": filename,
                "path": str(filepath),
                "size_bytes": os.path.getsize(filepath),
            })
        except Exception as e:
            failed_count += 1
            exported_files.append({
                "language": lang,
                "error": str(e),
            })

    # Log the export operation via service
    # For exports, track files (languages) as the unit of work
    completed_at = datetime.now(UTC)
    letzshop_export_service.log_export(
        db=db,
        vendor_id=vendor.id,
        started_at=started_at,
        completed_at=completed_at,
        files_processed=len(languages),
        files_succeeded=len(languages) - failed_count,
        files_failed=failed_count,
        products_exported=total_records,
        triggered_by=f"admin:{current_admin.id}",
        error_details={"files": exported_files} if failed_count > 0 else None,
    )
    db.commit()

    return {
        "success": True,
        "message": f"Exported {len([f for f in exported_files if 'error' not in f])} language(s) to {export_dir}",
        "vendor_code": vendor.vendor_code,
        "export_directory": str(export_dir),
        "files": exported_files,
    }
