# app/modules/tenancy/routes/api/merchant.py
"""
Tenancy module merchant API routes.

Aggregates all merchant tenancy routes:
- /auth/* - Merchant authentication (login, logout, /me)
- /account/* - Merchant account management (stores, profile)

Auto-discovered by the route system (merchant.py in routes/api/).
"""

import logging

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

from app.api.deps import get_current_merchant_api, get_merchant_for_current_user
from app.core.database import get_db
from app.modules.tenancy.schemas import (
    MerchantPortalProfileResponse,
    MerchantPortalProfileUpdate,
    MerchantPortalStoreListResponse,
    MerchantStoreCreate,
    MerchantStoreDetailResponse,
    MerchantStoreUpdate,
)
from app.modules.tenancy.schemas.auth import UserContext
from app.modules.tenancy.schemas.team import (
    MerchantTeamInvite,
    MerchantTeamProfileUpdate,
)
from app.modules.tenancy.services.merchant_service import merchant_service
from app.modules.tenancy.services.merchant_store_service import merchant_store_service

from .email_verification import email_verification_api_router
from .merchant_auth import merchant_auth_router
from .user_account import merchant_account_router

logger = logging.getLogger(__name__)

router = APIRouter()

# Include auth routes (/auth/login, /auth/logout, /auth/me, /auth/forgot-password, /auth/reset-password)
router.include_router(merchant_auth_router, tags=["merchant-auth"])

# Include email verification routes (/resend-verification)
router.include_router(email_verification_api_router, tags=["email-verification"])

# Account routes are defined below with /account prefix
_account_router = APIRouter(prefix="/account")


# ============================================================================
# ACCOUNT ENDPOINTS
# ============================================================================


@_account_router.get("/stores", response_model=MerchantPortalStoreListResponse)
async def merchant_stores(
    request: Request,
    skip: int = Query(0, ge=0, description="Number of records to skip"),
    limit: int = Query(100, ge=1, le=200, description="Max records to return"),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """
    List all stores belonging to the merchant.

    Returns a paginated list of store summaries for the authenticated merchant.
    """
    stores, total = merchant_service.get_merchant_stores(
        db, merchant.id, skip=skip, limit=limit
    )

    can_create, _ = merchant_store_service.can_create_store(db, merchant.id)

    return MerchantPortalStoreListResponse(
        stores=stores,
        total=total,
        skip=skip,
        limit=limit,
        can_create_store=can_create,
    )


@_account_router.post("/stores", response_model=MerchantStoreDetailResponse)
async def create_merchant_store(
    store_data: MerchantStoreCreate,
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """
    Create a new store under the merchant.

    Checks subscription tier store limits before creation.
    New stores are created with is_active=True, is_verified=False.
    """
    # Service raises MaxStoresReachedException, StoreAlreadyExistsException,
    # or StoreValidationException — all handled by global exception handler.
    result = merchant_store_service.create_store(
        db,
        merchant.id,
        store_data.model_dump(),
    )
    db.commit()
    logger.info(
        f"Merchant {merchant.id} ({current_user.username}) created store "
        f"'{store_data.store_code}'"
    )
    return result


@_account_router.get("/stores/{store_id}", response_model=MerchantStoreDetailResponse)
async def get_merchant_store_detail(
    store_id: int,
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """
    Get detailed store information with ownership validation.

    Returns store details including platform assignments.
    """
    # StoreNotFoundException handled by global exception handler
    return merchant_store_service.get_store_detail(db, merchant.id, store_id)


@_account_router.put("/stores/{store_id}", response_model=MerchantStoreDetailResponse)
async def update_merchant_store(
    store_id: int,
    update_data: MerchantStoreUpdate,
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """
    Update store details (merchant-allowed fields only).

    Only name, description, and contact info fields can be updated.
    """
    # StoreNotFoundException handled by global exception handler
    result = merchant_store_service.update_store(
        db,
        merchant.id,
        store_id,
        update_data.model_dump(exclude_unset=True),
    )
    db.commit()
    logger.info(
        f"Merchant {merchant.id} ({current_user.username}) updated store {store_id}"
    )
    return result


@_account_router.get("/platforms")
async def get_merchant_platforms(
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """
    Get platforms available for the merchant (from active subscriptions).

    Used by the store creation/edit UI to show platform selection options.
    """
    return merchant_store_service.get_subscribed_platform_ids(db, merchant.id)


@_account_router.get("/team")
async def merchant_team_overview(
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """
    Get team members across all merchant stores (member-centric view).

    Returns deduplicated members with per-store role info.
    """
    return merchant_store_service.get_merchant_team_members(db, merchant.id)


@_account_router.get("/team/members")
async def merchant_team_members_list(
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """Flat ``{members: [...]}`` view of merchant team members.

    Same data as ``GET /team`` but with the wrapper fields stripped, so it
    matches the shape store-side autocomplete factories already expect at
    ``${prefix}/team/members``.
    """
    full = merchant_store_service.get_merchant_team_members(db, merchant.id)
    return {"members": full["members"]}


@_account_router.get("/team/stores/{store_id}/roles")
async def merchant_team_store_roles(
    store_id: int,
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """Get available roles for a specific store."""
    from app.modules.tenancy.services.store_team_service import store_team_service

    merchant_store_service.validate_store_ownership(db, merchant.id, store_id)
    roles = store_team_service.get_store_roles(db, store_id)
    return {"roles": roles, "total": len(roles)}


@_account_router.post("/team/invite")
async def merchant_team_invite(
    data: MerchantTeamInvite,
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """Invite a member to one or more merchant stores."""
    from app.modules.tenancy.schemas.team import (
        MerchantTeamInviteResponse,
        MerchantTeamInviteResult,
    )
    from app.modules.tenancy.services.store_team_service import store_team_service

    # Get the User ORM object (service needs it as inviter)
    inviter = merchant_store_service.get_user(db, current_user.id)

    results = []
    for store_id in data.store_ids:
        try:
            store = merchant_store_service.validate_store_ownership(
                db, merchant.id, store_id
            )
            store_team_service.invite_team_member(
                db,
                store=store,
                inviter=inviter,
                email=data.email,
                role_name=data.role_name,
                first_name=data.first_name,
                last_name=data.last_name,
            )
            results.append(MerchantTeamInviteResult(
                store_id=store.id,
                store_name=store.name,
                success=True,
            ))
        except Exception as e:
            results.append(MerchantTeamInviteResult(
                store_id=store_id,
                store_name=getattr(e, "store_name", str(store_id)),
                success=False,
                error=str(e),
            ))

    db.commit()
    success_count = sum(1 for r in results if r.success)
    if success_count == len(results):
        message = f"Invitation sent to {data.email} for {success_count} store(s)"
    elif success_count > 0:
        message = f"Invitation partially sent ({success_count}/{len(results)} stores)"
    else:
        message = "Invitation failed for all stores"

    return MerchantTeamInviteResponse(
        message=message,
        email=data.email,
        results=results,
    )


@_account_router.put("/team/members/{user_id}/profile")
async def merchant_team_update_profile(
    user_id: int,
    data: MerchantTeamProfileUpdate,
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """Update a team member's profile (first name, last name, email)."""
    merchant_store_service.update_team_member_profile(
        db, merchant.id, user_id, data.model_dump(exclude_unset=True)
    )
    db.commit()
    logger.info(
        f"Merchant {merchant.id} updated profile for user {user_id} "
        f"by {current_user.username}"
    )
    return {"message": "Profile updated successfully"}


@_account_router.put("/team/stores/{store_id}/members/{user_id}")
async def merchant_team_update_role(
    store_id: int,
    user_id: int,
    role_name: str = Query(..., description="New role name"),
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """Update a member's role in a specific store."""
    from app.modules.tenancy.services.store_team_service import store_team_service

    store = merchant_store_service.validate_store_ownership(db, merchant.id, store_id)
    store_team_service.update_member_role(
        db,
        store=store,
        user_id=user_id,
        new_role_name=role_name,
        actor_user_id=current_user.id,
    )
    db.commit()
    return {"message": "Role updated successfully"}


@_account_router.post("/team/stores/{store_id}/members/{user_id}/resend")
async def merchant_team_resend_invitation(
    store_id: int,
    user_id: int,
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """Resend invitation to a pending team member."""
    from app.modules.tenancy.services.store_team_service import store_team_service

    store = merchant_store_service.validate_store_ownership(db, merchant.id, store_id)
    inviter = merchant_store_service.get_user(db, current_user.id)
    result = store_team_service.resend_invitation(
        db, store=store, user_id=user_id, inviter=inviter,
    )
    db.commit()
    return result


@_account_router.delete("/team/stores/{store_id}/members/{user_id}", status_code=204)
async def merchant_team_remove_member(
    store_id: int,
    user_id: int,
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """Remove a member from a specific store."""
    from app.modules.tenancy.services.store_team_service import store_team_service

    store = merchant_store_service.validate_store_ownership(db, merchant.id, store_id)
    store_team_service.remove_team_member(
        db,
        store=store,
        user_id=user_id,
        actor_user_id=current_user.id,
    )
    db.commit()


@_account_router.get("/profile", response_model=MerchantPortalProfileResponse)
async def merchant_profile(
    request: Request,
    merchant=Depends(get_merchant_for_current_user),
):
    """
    Get the authenticated merchant's profile information.

    Returns merchant details including contact info, business details,
    and verification status.
    """
    return merchant


@_account_router.put("/profile", response_model=MerchantPortalProfileResponse)
async def update_merchant_profile(
    request: Request,
    profile_data: MerchantPortalProfileUpdate,
    current_user: UserContext = Depends(get_current_merchant_api),
    merchant=Depends(get_merchant_for_current_user),
    db: Session = Depends(get_db),
):
    """
    Update the authenticated merchant's profile information.

    Accepts partial updates - only provided fields are changed.
    """
    # Apply only the fields that were explicitly provided
    update_data = profile_data.model_dump(exclude_unset=True)
    for field_name, value in update_data.items():
        setattr(merchant, field_name, value)

    db.commit()
    db.refresh(merchant)

    logger.info(
        f"Merchant profile updated: merchant_id={merchant.id}, "
        f"user={current_user.username}, fields={list(update_data.keys())}"
    )

    return merchant


# Include account routes in main router
router.include_router(_account_router, tags=["merchant-account"])

# Include self-service user account routes
router.include_router(merchant_account_router, tags=["merchant-user-account"])
