# app/modules/tenancy/routes/api/vendor_team.py
"""
Vendor team member management endpoints.

Implements complete team management with:
- Team member listing
- Invitation system
- Role management
- Permission checking
- RBAC integration
"""

import logging

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

from app.api.deps import (
    get_current_vendor_api,
    get_user_permissions,
    require_vendor_owner,
    require_vendor_permission,
)
from app.core.database import get_db
# Permission IDs are now defined in module definition.py files
# and discovered by PermissionDiscoveryService
from app.modules.tenancy.services.vendor_team_service import vendor_team_service
from models.schema.auth import UserContext
from app.modules.tenancy.schemas.team import (
    BulkRemoveRequest,
    BulkRemoveResponse,
    InvitationAccept,
    InvitationAcceptResponse,
    InvitationResponse,
    RoleListResponse,
    TeamMemberInvite,
    TeamMemberListResponse,
    TeamMemberResponse,
    TeamMemberUpdate,
    TeamStatistics,
    UserPermissionsResponse,
)

vendor_team_router = APIRouter(prefix="/team")
logger = logging.getLogger(__name__)


# ============================================================================
# Team Member Routes
# ============================================================================


@vendor_team_router.get("/members", response_model=TeamMemberListResponse)
def list_team_members(
    request: Request,
    include_inactive: bool = False,
    db: Session = Depends(get_db),
    current_user: UserContext = Depends(
        require_vendor_permission("team.view")
    ),
):
    """
    Get all team members for current vendor.

    **Required Permission:** `team.view`

    **Query Parameters:**
    - `include_inactive`: Include inactive team members (default: False)

    **Returns:**
    - List of team members with their roles and permissions
    - Statistics (total, active, pending)
    """
    vendor = request.state.vendor

    members = vendor_team_service.get_team_members(
        db=db, vendor=vendor, include_inactive=include_inactive
    )

    # Calculate statistics
    total = len(members)
    active = sum(1 for m in members if m["is_active"])
    pending = sum(1 for m in members if m["invitation_pending"])

    logger.info(
        f"Listed {total} team members for vendor {vendor.vendor_code} "
        f"(active: {active}, pending: {pending})"
    )

    return TeamMemberListResponse(
        members=members, total=total, active_count=active, pending_invitations=pending
    )


@vendor_team_router.post("/invite", response_model=InvitationResponse)
def invite_team_member(
    invitation: TeamMemberInvite,
    request: Request,
    db: Session = Depends(get_db),
    current_user: UserContext = Depends(require_vendor_owner),  # Owner only
):
    """
    Invite a new team member to the vendor.

    **Required:** Vendor owner role

    **Process:**
    1. Create user account (if doesn't exist)
    2. Create VendorUser with invitation token
    3. Send invitation email

    **Request Body:**
    - `email`: Email address of invitee
    - `first_name`, `last_name`: Optional names
    - `role_name`: Preset role (manager, staff, support, viewer, marketing)
    - `role_id`: Use existing role (alternative to role_name)
    - `custom_permissions`: Override role permissions (requires role_name)

    **Returns:**
    - Invitation details
    - Confirmation of email sent
    """
    vendor = request.state.vendor

    # Determine role approach
    if invitation.role_id:
        # Use existing role by ID
        result = vendor_team_service.invite_team_member(
            db=db,
            vendor=vendor,
            inviter=current_user,
            email=invitation.email,
            role_id=invitation.role_id,
        )
    elif invitation.role_name:
        # Use role name with optional custom permissions
        result = vendor_team_service.invite_team_member(
            db=db,
            vendor=vendor,
            inviter=current_user,
            email=invitation.email,
            role_name=invitation.role_name,
            custom_permissions=invitation.custom_permissions,
        )
    else:
        # Default to Staff role
        result = vendor_team_service.invite_team_member(
            db=db,
            vendor=vendor,
            inviter=current_user,
            email=invitation.email,
            role_name="staff",
        )
    db.commit()

    logger.info(
        f"Invitation sent: {invitation.email} to {vendor.vendor_code} "
        f"by {current_user.username}"
    )

    return InvitationResponse(
        message="Invitation sent successfully",
        email=result["email"],
        role=result["role"],
        invitation_sent=True,
    )


@vendor_team_router.post("/accept-invitation", response_model=InvitationAcceptResponse)  # public
def accept_invitation(acceptance: InvitationAccept, db: Session = Depends(get_db)):
    """
    Accept a team invitation and activate account.

    **No authentication required** - uses invitation token.

    **Request Body:**
    - `invitation_token`: Token from invitation email
    - `password`: New password (min 8 chars, must have upper, lower, digit)
    - `first_name`, `last_name`: User's name

    **Returns:**
    - Confirmation message
    - Vendor information
    - User information
    - Assigned role
    """
    result = vendor_team_service.accept_invitation(
        db=db,
        invitation_token=acceptance.invitation_token,
        password=acceptance.password,
        first_name=acceptance.first_name,
        last_name=acceptance.last_name,
    )
    db.commit()

    logger.info(
        f"Invitation accepted: {result['user'].email} "
        f"for vendor {result['vendor'].vendor_code}"
    )

    return InvitationAcceptResponse(
        message="Invitation accepted successfully. You can now login.",
        vendor={
            "id": result["vendor"].id,
            "vendor_code": result["vendor"].vendor_code,
            "name": result["vendor"].name,
            "subdomain": result["vendor"].subdomain,
        },
        user={
            "id": result["user"].id,
            "email": result["user"].email,
            "username": result["user"].username,
            "full_name": result["user"].full_name,
        },
        role=result["role"],
    )


@vendor_team_router.get("/members/{user_id}", response_model=TeamMemberResponse)
def get_team_member(
    user_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: UserContext = Depends(
        require_vendor_permission("team.view")
    ),
):
    """
    Get details of a specific team member.

    **Required Permission:** `team.view`
    """
    vendor = request.state.vendor

    members = vendor_team_service.get_team_members(
        db=db, vendor=vendor, include_inactive=True
    )

    member = next((m for m in members if m["id"] == user_id), None)
    if not member:
        from app.modules.tenancy.exceptions import UserNotFoundException

        raise UserNotFoundException(str(user_id))

    return TeamMemberResponse(**member)


@vendor_team_router.put("/members/{user_id}", response_model=TeamMemberResponse)
def update_team_member(
    user_id: int,
    update_data: TeamMemberUpdate,
    request: Request,
    db: Session = Depends(get_db),
    current_user: UserContext = Depends(require_vendor_owner),  # Owner only
):
    """
    Update a team member's role or status.

    **Required:** Vendor owner role

    **Cannot:**
    - Change owner's role
    - Remove owner

    **Request Body:**
    - `role_id`: New role ID (optional)
    - `is_active`: Active status (optional)
    """
    vendor = request.state.vendor

    vendor_user = vendor_team_service.update_member_role(
        db=db,
        vendor=vendor,
        user_id=user_id,
        new_role_id=update_data.role_id,
        is_active=update_data.is_active,
    )
    db.commit()

    logger.info(
        f"Team member updated: {user_id} in {vendor.vendor_code} "
        f"by {current_user.username}"
    )

    # Return updated member details
    members = vendor_team_service.get_team_members(db, vendor, include_inactive=True)
    member = next((m for m in members if m["id"] == user_id), None)

    return TeamMemberResponse(**member)


@vendor_team_router.delete("/members/{user_id}")
def remove_team_member(
    user_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: UserContext = Depends(require_vendor_owner),  # Owner only
):
    """
    Remove a team member from the vendor.

    **Required:** Vendor owner role

    **Cannot remove:**
    - Vendor owner

    **Action:**
    - Soft delete (sets is_active = False)
    - Member can be re-invited later
    """
    vendor = request.state.vendor

    vendor_team_service.remove_team_member(db=db, vendor=vendor, user_id=user_id)
    db.commit()

    logger.info(
        f"Team member removed: {user_id} from {vendor.vendor_code} "
        f"by {current_user.username}"
    )

    return {"message": "Team member removed successfully", "user_id": user_id}


@vendor_team_router.post("/members/bulk-remove", response_model=BulkRemoveResponse)
def bulk_remove_team_members(
    bulk_remove: BulkRemoveRequest,
    request: Request,
    db: Session = Depends(get_db),
    current_user: UserContext = Depends(require_vendor_owner),
):
    """
    Remove multiple team members at once.

    **Required:** Vendor owner role
    """
    vendor = request.state.vendor

    success_count = 0
    failed_count = 0
    errors = []

    for user_id in bulk_remove.user_ids:
        try:
            vendor_team_service.remove_team_member(
                db=db, vendor=vendor, user_id=user_id
            )
            success_count += 1
        except Exception as e:
            failed_count += 1
            errors.append({"user_id": user_id, "error": str(e)})

    db.commit()

    logger.info(
        f"Bulk remove completed: {success_count} removed, {failed_count} failed "
        f"in {vendor.vendor_code}"
    )

    return BulkRemoveResponse(
        success_count=success_count, failed_count=failed_count, errors=errors
    )


# ============================================================================
# Role Management Routes
# ============================================================================


@vendor_team_router.get("/roles", response_model=RoleListResponse)
def list_roles(
    request: Request,
    db: Session = Depends(get_db),
    current_user: UserContext = Depends(
        require_vendor_permission("team.view")
    ),
):
    """
    Get all available roles for the vendor.

    **Required Permission:** `team.view`

    **Returns:**
    - List of roles with permissions
    - Includes both preset and custom roles
    """
    vendor = request.state.vendor

    roles = vendor_team_service.get_vendor_roles(db=db, vendor_id=vendor.id)
    db.commit()  # Commit in case default roles were created

    return RoleListResponse(roles=roles, total=len(roles))


# ============================================================================
# Permission Routes
# ============================================================================


@vendor_team_router.get("/me/permissions", response_model=UserPermissionsResponse)
def get_my_permissions(
    request: Request,
    permissions: list[str] = Depends(get_user_permissions),
    current_user: UserContext = Depends(get_current_vendor_api),
):
    """
    Get current user's permissions in this vendor.

    **Use this endpoint to:**
    - Determine what UI elements to show/hide
    - Check permissions before making API calls
    - Display user's role and capabilities

    **Returns:**
    - Complete list of permissions
    - Whether user is owner
    - Role name (if team member)

    Requires Authorization header (API endpoint).
    """
    vendor = request.state.vendor

    is_owner = current_user.is_owner_of(vendor.id)
    role_name = current_user.get_vendor_role(vendor.id)

    return UserPermissionsResponse(
        permissions=permissions,
        permission_count=len(permissions),
        is_owner=is_owner,
        role_name=role_name,
    )


# ============================================================================
# Statistics Routes
# ============================================================================


@vendor_team_router.get("/statistics", response_model=TeamStatistics)
def get_team_statistics(
    request: Request,
    db: Session = Depends(get_db),
    current_user: UserContext = Depends(
        require_vendor_permission("team.view")
    ),
):
    """
    Get team statistics for the vendor.

    **Required Permission:** `team.view`

    **Returns:**
    - Total members
    - Active/inactive breakdown
    - Pending invitations
    - Owner count
    - Role distribution
    """
    vendor = request.state.vendor

    members = vendor_team_service.get_team_members(
        db=db, vendor=vendor, include_inactive=True
    )

    # Calculate statistics
    total = len(members)
    active = sum(1 for m in members if m["is_active"])
    inactive = total - active
    pending = sum(1 for m in members if m["invitation_pending"])
    owners = sum(1 for m in members if m["is_owner"])
    team_members = total - owners

    # Role breakdown
    roles_breakdown = {}
    for member in members:
        role = member["role_name"]
        roles_breakdown[role] = roles_breakdown.get(role, 0) + 1

    return TeamStatistics(
        total_members=total,
        active_members=active,
        inactive_members=inactive,
        pending_invitations=pending,
        owners=owners,
        team_members=team_members,
        roles_breakdown=roles_breakdown,
    )
