# app/modules/tenancy/routes/api/admin_merchants.py
"""
Merchant management endpoints for admin.
"""

import logging
from datetime import UTC, datetime

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

from app.api.deps import get_current_admin_api
from app.core.database import get_db
from app.core.environment import should_use_secure_cookies
from app.modules.tenancy.exceptions import (
    ConfirmationRequiredException,
    MerchantHasStoresException,
)
from app.modules.tenancy.schemas.auth import UserContext
from app.modules.tenancy.schemas.merchant import (
    MerchantCreate,
    MerchantCreateResponse,
    MerchantDetailResponse,
    MerchantListResponse,
    MerchantResponse,
    MerchantTransferOwnership,
    MerchantTransferOwnershipResponse,
    MerchantUpdate,
)
from app.modules.tenancy.services.merchant_service import merchant_service

admin_merchants_router = APIRouter(prefix="/merchants")
logger = logging.getLogger(__name__)


@admin_merchants_router.post("", response_model=MerchantCreateResponse)
def create_merchant_with_owner(
    request: Request,
    merchant_data: MerchantCreate,
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Create a new merchant with owner user account (Admin only).

    This endpoint:
    1. Creates a new merchant record
    2. Creates an owner user account with owner_email (if not exists)
    3. Sends email verification + welcome email to owner
    4. Returns credentials (temporary password shown ONCE if new user created)

    **Email Fields:**
    - `owner_email`: Used for owner's login/authentication (stored in users.email)
    - `contact_email`: Public business contact (stored in merchants.contact_email)

    Returns merchant details with owner credentials.
    """
    merchant, owner_user, temp_password = merchant_service.create_merchant_with_owner(
        db, merchant_data
    )

    db.commit()  # ✅ ARCH: Commit at API level for transaction control

    # Send verification email to new owner (only for newly created users)
    if temp_password:
        try:
            from app.modules.messaging.services.email_service import EmailService
            from app.modules.tenancy.models import EmailVerificationToken

            plaintext_token = EmailVerificationToken.create_for_user(db, owner_user.id)

            scheme = "https" if should_use_secure_cookies() else "http"
            host = request.headers.get("host", "localhost:8000")
            verification_link = f"{scheme}://{host}/verify-email?token={plaintext_token}"

            email_service = EmailService(db)
            email_service.send_template(
                template_code="email_verification",
                to_email=owner_user.email,
                to_name=owner_user.username,
                language="en",
                variables={
                    "first_name": owner_user.username,
                    "verification_link": verification_link,
                    "expiry_hours": str(EmailVerificationToken.TOKEN_EXPIRY_HOURS),
                    "platform_name": "Orion",
                },
            )

            db.commit()
            logger.info(f"Verification email sent to {owner_user.email}")
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to send verification email: {e}")  # noqa: SEC021

    return MerchantCreateResponse(
        merchant=MerchantResponse(
            id=merchant.id,
            name=merchant.name,
            description=merchant.description,
            owner_user_id=merchant.owner_user_id,
            contact_email=merchant.contact_email,
            contact_phone=merchant.contact_phone,
            website=merchant.website,
            business_address=merchant.business_address,
            tax_number=merchant.tax_number,
            is_active=merchant.is_active,
            is_verified=merchant.is_verified,
            created_at=merchant.created_at.isoformat(),
            updated_at=merchant.updated_at.isoformat(),
        ),
        owner_user_id=owner_user.id,
        owner_username=owner_user.username,
        owner_email=owner_user.email,
        temporary_password=temp_password or "N/A (Existing user)",
        login_url="http://localhost:8000/admin/login",
    )


@admin_merchants_router.get("", response_model=MerchantListResponse)
def get_all_merchants(
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=1000),
    search: str | None = Query(None, description="Search by merchant name"),
    is_active: bool | None = Query(None),
    is_verified: bool | None = Query(None),
    include_deleted: bool = Query(False, description="Include soft-deleted merchants"),
    only_deleted: bool = Query(False, description="Show only soft-deleted merchants (trash view)"),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get all merchants with filtering (Admin only)."""
    merchants, total = merchant_service.get_merchants(
        db,
        skip=skip,
        limit=limit,
        search=search,
        is_active=is_active,
        is_verified=is_verified,
        include_deleted=include_deleted,
        only_deleted=only_deleted,
    )

    return MerchantListResponse(
        merchants=[
            MerchantResponse(
                id=c.id,
                name=c.name,
                description=c.description,
                owner_user_id=c.owner_user_id,
                owner_email=c.owner.email if c.owner else None,
                contact_email=c.contact_email,
                contact_phone=c.contact_phone,
                website=c.website,
                business_address=c.business_address,
                tax_number=c.tax_number,
                is_active=c.is_active,
                is_verified=c.is_verified,
                created_at=c.created_at.isoformat(),
                updated_at=c.updated_at.isoformat(),
                store_count=c.store_count,
            )
            for c in merchants
        ],
        total=total,
        skip=skip,
        limit=limit,
    )


@admin_merchants_router.get("/{merchant_id}", response_model=MerchantDetailResponse)
def get_merchant_details(
    merchant_id: int = Path(..., description="Merchant ID"),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Get detailed merchant information including store counts (Admin only).
    """
    merchant = merchant_service.get_merchant_by_id(db, merchant_id)

    # Count stores
    store_count = len(merchant.stores)
    active_store_count = sum(1 for v in merchant.stores if v.is_active)

    # Build stores list for detail view
    stores_list = [
        {
            "id": v.id,
            "store_code": v.store_code,
            "name": v.name,
            "subdomain": v.subdomain,
            "is_active": v.is_active,
            "is_verified": v.is_verified,
        }
        for v in merchant.stores
    ]

    return MerchantDetailResponse(
        id=merchant.id,
        name=merchant.name,
        description=merchant.description,
        owner_user_id=merchant.owner_user_id,
        owner_email=merchant.owner.email if merchant.owner else None,
        owner_username=merchant.owner.username if merchant.owner else None,
        contact_email=merchant.contact_email,
        contact_phone=merchant.contact_phone,
        website=merchant.website,
        business_address=merchant.business_address,
        tax_number=merchant.tax_number,
        is_active=merchant.is_active,
        is_verified=merchant.is_verified,
        created_at=merchant.created_at.isoformat(),
        updated_at=merchant.updated_at.isoformat(),
        store_count=store_count,
        active_store_count=active_store_count,
        stores=stores_list,
    )


@admin_merchants_router.put("/{merchant_id}", response_model=MerchantResponse)
def update_merchant(
    merchant_id: int = Path(..., description="Merchant ID"),
    merchant_update: MerchantUpdate = Body(...),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Update merchant information (Admin only).

    **Can update:**
    - Basic info: name, description
    - Business contact: contact_email, contact_phone, website
    - Business details: business_address, tax_number
    - Status: is_active, is_verified

    **Cannot update:**
    - `owner_user_id` (would require ownership transfer feature)
    """
    merchant = merchant_service.update_merchant(db, merchant_id, merchant_update)
    db.commit()  # ✅ ARCH: Commit at API level for transaction control

    return MerchantResponse(
        id=merchant.id,
        name=merchant.name,
        description=merchant.description,
        owner_user_id=merchant.owner_user_id,
        contact_email=merchant.contact_email,
        contact_phone=merchant.contact_phone,
        website=merchant.website,
        business_address=merchant.business_address,
        tax_number=merchant.tax_number,
        is_active=merchant.is_active,
        is_verified=merchant.is_verified,
        created_at=merchant.created_at.isoformat(),
        updated_at=merchant.updated_at.isoformat(),
    )


@admin_merchants_router.put("/{merchant_id}/verification", response_model=MerchantResponse)
def toggle_merchant_verification(
    merchant_id: int = Path(..., description="Merchant ID"),
    verification_data: dict = Body(..., example={"is_verified": True}),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Toggle merchant verification status (Admin only).

    Request body: { "is_verified": true/false }
    """
    is_verified = verification_data.get("is_verified", False)
    merchant = merchant_service.toggle_verification(db, merchant_id, is_verified)
    db.commit()  # ✅ ARCH: Commit at API level for transaction control

    return MerchantResponse(
        id=merchant.id,
        name=merchant.name,
        description=merchant.description,
        owner_user_id=merchant.owner_user_id,
        contact_email=merchant.contact_email,
        contact_phone=merchant.contact_phone,
        website=merchant.website,
        business_address=merchant.business_address,
        tax_number=merchant.tax_number,
        is_active=merchant.is_active,
        is_verified=merchant.is_verified,
        created_at=merchant.created_at.isoformat(),
        updated_at=merchant.updated_at.isoformat(),
    )


@admin_merchants_router.put("/{merchant_id}/status", response_model=MerchantResponse)
def toggle_merchant_status(
    merchant_id: int = Path(..., description="Merchant ID"),
    status_data: dict = Body(..., example={"is_active": True}),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Toggle merchant active status (Admin only).

    Request body: { "is_active": true/false }
    """
    is_active = status_data.get("is_active", True)
    merchant = merchant_service.toggle_active(db, merchant_id, is_active)
    db.commit()  # ✅ ARCH: Commit at API level for transaction control

    return MerchantResponse(
        id=merchant.id,
        name=merchant.name,
        description=merchant.description,
        owner_user_id=merchant.owner_user_id,
        contact_email=merchant.contact_email,
        contact_phone=merchant.contact_phone,
        website=merchant.website,
        business_address=merchant.business_address,
        tax_number=merchant.tax_number,
        is_active=merchant.is_active,
        is_verified=merchant.is_verified,
        created_at=merchant.created_at.isoformat(),
        updated_at=merchant.updated_at.isoformat(),
    )


@admin_merchants_router.post(
    "/{merchant_id}/transfer-ownership",
    response_model=MerchantTransferOwnershipResponse,
)
def transfer_merchant_ownership(
    merchant_id: int = Path(..., description="Merchant ID"),
    transfer_data: MerchantTransferOwnership = Body(...),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Transfer merchant ownership to another user (Admin only).

    **This is a critical operation that:**
    - Changes the merchant's owner_user_id
    - Updates all associated stores' owner_user_id
    - Creates audit trail

    ⚠️ **This action is logged and should be used carefully.**

    **Requires:**
    - `new_owner_user_id`: ID of user who will become owner
    - `confirm_transfer`: Must be true
    - `transfer_reason`: Optional reason for audit trail
    """
    merchant, old_owner, new_owner = merchant_service.transfer_ownership(
        db, merchant_id, transfer_data
    )
    db.commit()  # ✅ ARCH: Commit at API level for transaction control

    return MerchantTransferOwnershipResponse(
        message="Ownership transferred successfully",
        merchant_id=merchant.id,
        merchant_name=merchant.name,
        old_owner={
            "id": old_owner.id,
            "username": old_owner.username,
            "email": old_owner.email,
        },
        new_owner={
            "id": new_owner.id,
            "username": new_owner.username,
            "email": new_owner.email,
        },
        transferred_at=datetime.now(UTC),
        transfer_reason=transfer_data.transfer_reason,
    )


@admin_merchants_router.delete("/{merchant_id}")
def delete_merchant(
    merchant_id: int = Path(..., description="Merchant ID"),
    confirm: bool = Query(False, description="Must be true to confirm deletion"),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Delete merchant and all associated stores (Admin only).

    ⚠️ **WARNING: This is destructive and will delete:**
    - Merchant account
    - All stores under this merchant
    - All products under those stores
    - All orders, customers, team members

    Requires confirmation parameter: `confirm=true`
    """
    if not confirm:
        raise ConfirmationRequiredException(
            operation="delete_merchant",
            message="Deletion requires confirmation parameter: confirm=true",
        )

    # Get merchant to check store count
    merchant = merchant_service.get_merchant_by_id(db, merchant_id)
    store_count = len(merchant.stores)

    if store_count > 0:
        raise MerchantHasStoresException(merchant_id, store_count)

    merchant_service.delete_merchant(db, merchant_id)
    db.commit()  # ✅ ARCH: Commit at API level for transaction control

    return {"message": f"Merchant {merchant_id} deleted successfully"}


@admin_merchants_router.put("/{merchant_id}/restore")
def restore_merchant(
    merchant_id: int = Path(..., description="Merchant ID"),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Restore a soft-deleted merchant (Admin only).

    This only restores the merchant record itself.
    Stores and their children must be restored separately.
    """
    from app.core.soft_delete import restore
    from app.modules.tenancy.models import Merchant

    restored = restore(db, Merchant, merchant_id, restored_by_id=current_admin.id)
    db.commit()
    logger.info(f"Merchant {merchant_id} restored by admin {current_admin.username}")
    return {"message": f"Merchant '{restored.name}' restored successfully", "merchant_id": merchant_id}
