# members.py
from typing import Dict, Any, Optional
from mcp.server.fastmcp import Context
from ..mcp_app import mcp
from ..core.validators import ParameterValidator
from ..core.api_wrapper import DefensiveAPIWrapper, safe_congressional_request
from ..core.exceptions import CommonErrors, format_error_response
from ..core.response_utils import ResponseProcessor
import logging

logger = logging.getLogger(__name__)

# Initialize framework components
validator = ParameterValidator()
api_wrapper = DefensiveAPIWrapper()
response_processor = ResponseProcessor()

# Resources (Static data only - no user parameters)
@mcp.resource("congress://members/current")
async def get_current_members(ctx: Context) -> str:
    """
    Get a list of current members of Congress.
    
    Returns a sample of 20 current members from both chambers of Congress,
    including their biographical information and contact details.
    """
    data = await safe_congressional_request("/member", ctx, {"limit": 20, "currentMember": "true"}, endpoint_type='members')
    
    if "error" in data:
        return f"Error retrieving members: {data['error']}"
    
    members = data.get("members", [])
    if not members:
        return "No current members found."
    
    result = ["# Current Members of Congress (Sample)"]
    for member in members:
        result.append("\n" + format_member_summary(member))
    
    return "\n".join(result)

@mcp.resource("congress://members/all")
async def get_all_members(ctx: Context) -> str:
    """
    Get a list of congressional members.
    
    Returns a list of congressional members with basic information about each,
    including their biographical information and contact details.
    """
    data = await safe_congressional_request("/member", ctx, {"limit": 20}, endpoint_type='members')
    
    if "error" in data:
        return f"Error retrieving members: {data['error']}"
    
    members = data.get("members", [])
    if not members:
        return "No members found."
    
    result = ["# Congressional Members (Sample)"]
    for member in members:
        result.append("\n" + format_member_summary(member))
    
    return "\n".join(result)

# Tools (Interactive functions with parameters)
async def get_member_details(ctx: Context, bioguide_id: str) -> str:
    """
    Get detailed information about a specific member of Congress.
    
    Args:
        bioguide_id: The Bioguide ID for the member (e.g., "A000055")
        
    Returns comprehensive information about the specified member,
    including biographical data, terms of service, and committee assignments.
    """
    try:
        # Validate bioguide_id parameter
        if not bioguide_id or not isinstance(bioguide_id, str):
            return format_error_response(CommonErrors.invalid_parameter(
                "bioguide_id", bioguide_id, "Bioguide ID must be a non-empty string (e.g., 'A000055')"
            ))
        
        bioguide_id = bioguide_id.strip().upper()
        if not bioguide_id:
            return format_error_response(CommonErrors.invalid_parameter(
                "bioguide_id", bioguide_id, "Bioguide ID cannot be empty"
            ))
        
        data = await safe_congressional_request(f"/member/{bioguide_id}", ctx, {}, endpoint_type='members')
        
        if "error" in data:
            if "404" in str(data["error"]):
                return format_error_response(CommonErrors.data_not_found(
                    resource_type="Member", identifier=bioguide_id
                ))
            return format_error_response(CommonErrors.api_server_error(f"/member/{bioguide_id}", message=str(data["error"])))
        
        member = data.get("member", {})
        if not member:
            return format_error_response(CommonErrors.data_not_found(
                resource_type="Member", identifier=bioguide_id
            ))
        
        # Format detailed member information
        result = [format_member_summary(member)]
        
        # Add detailed biographical information
        result.append("\n## Detailed Information")
        
        # Terms of service
        if "terms" in member:
            terms = member["terms"]
            if isinstance(terms, dict) and "item" in terms:
                terms = terms["item"]
            
            if terms and isinstance(terms, list):
                result.append("\n### Terms of Service")
                for i, term in enumerate(terms[:5]):  # Show up to 5 most recent terms
                    if isinstance(term, dict):
                        congress = term.get("congress", "Unknown")
                        chamber = term.get("chamber", "Unknown")
                        start_year = term.get("startYear", "Unknown")
                        end_year = term.get("endYear", "Unknown")
                        result.append(f"{i+1}. Congress {congress} ({chamber}): {start_year}-{end_year}")
        
        # Committee assignments
        if "committeeAssignments" in member and member["committeeAssignments"]:
            committees = member["committeeAssignments"]
            
            if isinstance(committees, dict) and "item" in committees:
                committees = committees["item"]
            
            if committees and isinstance(committees, list):
                result.append("\n### Committee Assignments")
                for committee in committees:
                    name = committee.get("name", "Unknown committee")
                    code = committee.get("systemCode", "")
                    chamber = committee.get("chamber", "")
                    result.append(f"- {name} ({chamber}, {code})")
        
        # Sponsored legislation count
        if "sponsoredLegislation" in member and "count" in member["sponsoredLegislation"]:
            count = member["sponsoredLegislation"]["count"]
            result.append(f"\n### Legislative Activity")
            result.append(f"Total bills sponsored: {count}")
            result.append("Use get_member_sponsored_legislation to see specific bills.")
        
        # Contact and social media information
        result.append("\n### Contact Information")
        if "officialWebsiteUrl" in member:
            result.append(f"Official Website: {member['officialWebsiteUrl']}")
        if "twitterAccount" in member:
            result.append(f"Twitter: @{member['twitterAccount']}")
        if "youtubeAccount" in member:
            result.append(f"YouTube: {member['youtubeAccount']}")
        if "facebookAccount" in member:
            result.append(f"Facebook: {member['facebookAccount']}")
        
        # Additional biographical details
        if "birthDate" in member:
            result.append(f"Birth Date: {member['birthDate']}")
        if "deathDate" in member:
            result.append(f"Death Date: {member['deathDate']}")
        
        return "\n".join(result)
        
    except Exception as e:
        logger.error(f"Error in get_member_details: {str(e)}")
        return format_error_response(CommonErrors.api_server_error(f"Unexpected error: {str(e)}"))

async def get_member_sponsored_legislation(ctx: Context, bioguide_id: str) -> str:
    """
    Get legislation sponsored by a specific member of Congress.
    
    Args:
        bioguide_id: The Bioguide ID for the member (e.g., "L000174")
        
    Returns a list of legislation sponsored by the specified member.
    """
    try:
        # Validate bioguide_id parameter
        if not bioguide_id or not isinstance(bioguide_id, str):
            return format_error_response(CommonErrors.invalid_parameter(
                "bioguide_id", bioguide_id, "Bioguide ID must be a non-empty string"
            ))
        
        bioguide_id = bioguide_id.strip().upper()
        if not bioguide_id:
            return format_error_response(CommonErrors.invalid_parameter(
                "bioguide_id", bioguide_id, "Bioguide ID cannot be empty"
            ))
        
        data = await safe_congressional_request(f"/member/{bioguide_id}/sponsored-legislation", ctx, {"limit": 20}, endpoint_type='members')
        
        if "error" in data:
            if "404" in str(data["error"]):
                return format_error_response(CommonErrors.data_not_found(
                    resource_type="Member", identifier=bioguide_id
                ))
            return format_error_response(CommonErrors.api_server_error(f"/member/{bioguide_id}/sponsored-legislation", message=str(data["error"])))
        
        legislation = data.get("sponsoredLegislation", [])
        if not legislation:
            return f"No sponsored legislation found for member {bioguide_id}."
        
        # Process and deduplicate results
        if isinstance(legislation, list):
            legislation = response_processor.deduplicate_results(
                legislation, 
                key_fields=["congress", "type", "number"]
            )
        
        result = [f"# Sponsored Legislation for Member {bioguide_id}"]
        result.append(f"Found {len(legislation)} bills:")
        
        for bill in legislation:
            congress = bill.get("congress", "Unknown")
            bill_type = bill.get("type", "Unknown") or "Unknown"
            number = bill.get("number", "Unknown")
            title = bill.get("title", "No title available")
            
            # Ensure bill_type is not None before calling upper()
            bill_type_display = bill_type.upper() if bill_type and bill_type != "Unknown" else "UNKNOWN"
            
            result.append(f"\n## {bill_type_display} {number} (Congress {congress})")
            result.append(f"{title}")
            
            if "url" in bill:
                result.append(f"[View Details]({bill['url']})")
        
        return "\n".join(result)
        
    except Exception as e:
        logger.error(f"Error in get_member_sponsored_legislation: {str(e)}")
        return format_error_response(CommonErrors.api_server_error(f"Unexpected error: {str(e)}"))

async def get_member_cosponsored_legislation(ctx: Context, bioguide_id: str) -> str:
    """
    Get legislation cosponsored by a specific member of Congress.
    
    Args:
        bioguide_id: The Bioguide ID for the member (e.g., "L000174")
        
    Returns a list of legislation cosponsored by the specified member.
    """
    try:
        # Validate bioguide_id parameter
        if not bioguide_id or not isinstance(bioguide_id, str):
            return format_error_response(CommonErrors.invalid_parameter(
                "bioguide_id", bioguide_id, "Bioguide ID must be a non-empty string"
            ))
        
        bioguide_id = bioguide_id.strip().upper()
        if not bioguide_id:
            return format_error_response(CommonErrors.invalid_parameter(
                "bioguide_id", bioguide_id, "Bioguide ID cannot be empty"
            ))
        
        data = await safe_congressional_request(f"/member/{bioguide_id}/cosponsored-legislation", ctx, {"limit": 20}, endpoint_type='members')
        
        if "error" in data:
            if "404" in str(data["error"]):
                return format_error_response(CommonErrors.data_not_found(
                    resource_type="Member", identifier=bioguide_id
                ))
            return format_error_response(CommonErrors.api_server_error(f"/member/{bioguide_id}/cosponsored-legislation", message=str(data["error"])))
        
        legislation = data.get("cosponsoredLegislation", [])
        if not legislation:
            return f"No cosponsored legislation found for member {bioguide_id}."
        
        # Process and deduplicate results
        if isinstance(legislation, list):
            legislation = response_processor.deduplicate_results(
                legislation, 
                key_fields=["congress", "type", "number"]
            )
        
        result = [f"# Cosponsored Legislation for Member {bioguide_id}"]
        result.append(f"Found {len(legislation)} bills:")
        
        for bill in legislation:
            congress = bill.get("congress", "Unknown")
            bill_type = bill.get("type", "Unknown") or "Unknown"
            number = bill.get("number", "Unknown")
            title = bill.get("title", "No title available")
            
            # Ensure bill_type is not None before calling upper()
            bill_type_display = bill_type.upper() if bill_type and bill_type != "Unknown" else "UNKNOWN"
            
            result.append(f"\n## {bill_type_display} {number} (Congress {congress})")
            result.append(f"{title}")
            
            if "url" in bill:
                result.append(f"[View Details]({bill['url']})")
        
        return "\n".join(result)
        
    except Exception as e:
        logger.error(f"Error in get_member_cosponsored_legislation: {str(e)}")
        return format_error_response(CommonErrors.api_server_error(f"Unexpected error: {str(e)}"))

async def get_members_by_congress(ctx: Context, congress: int) -> str:
    """
    Get members of a specific Congress.
    
    Args:
        congress: The Congress number (e.g., 118)
        
    Returns a list of members who served in the specified Congress.
    """
    try:
        # Validate congress parameter
        congress_validation = validator.validate_congress_number(congress)
        if not congress_validation.is_valid:
            return format_error_response(CommonErrors.invalid_parameter(
                "congress", congress, congress_validation.error_message
            ))
        
        # Use pagination to get all members of the congress
        data = await get_all_members_paginated(ctx, f"/member/congress/{congress}", {})
        
        if "error" in data:
            return format_error_response(CommonErrors.api_server_error(f"Error retrieving members for Congress {congress}: {data['error']}"))
        
        members = data.get("members", [])
        if not members:
            return f"No members found for Congress {congress}."
        
        # Process and deduplicate results
        members = response_processor.deduplicate_results(
            members, 
            key_fields=["bioguideId"]
        )
        
        result = [f"# Members of the {congress}th Congress"]
        result.append(f"Found {len(members)} members:")
        
        for member in members:
            result.append("\n" + format_member_summary(member))
        
        return "\n".join(result)
        
    except Exception as e:
        logger.error(f"Error in get_members_by_congress: {str(e)}")
        return format_error_response(CommonErrors.api_server_error(f"Unexpected error: {str(e)}"))

async def get_members_by_state(ctx: Context, state_code: str) -> str:
    """
    Get members from a specific state.
    
    Args:
        state_code: The two-letter state code (e.g., "MI" for Michigan)
        
    Returns a list of members who represent the specified state.
    """
    try:
        # Validate state_code parameter
        state_validation = validator.validate_state_code(state_code)
        if not state_validation.is_valid:
            return format_error_response(CommonErrors.invalid_parameter(
                "state_code", state_code, state_validation.error_message
            ))
        
        state_code = state_validation.sanitized_value
        
        data = await safe_congressional_request(f"/member/{state_code}", ctx, {"currentMember": "true"}, endpoint_type='members')
        
        if "error" in data:
            return format_error_response(CommonErrors.api_server_error(f"Error retrieving members for state {state_code}: {data['error']}"))
        
        members = data.get("members", [])
        if not members:
            return f"No members found for state {state_code}."
        
        # Process and deduplicate results
        members = response_processor.deduplicate_results(
            members, 
            key_fields=["bioguideId"]
        )
        
        result = [f"# Members from {state_code}"]
        result.append(f"Found {len(members)} current members:")
        
        for member in members:
            result.append("\n" + format_member_summary(member))
        
        return "\n".join(result)
        
    except Exception as e:
        logger.error(f"Error in get_members_by_state: {str(e)}")
        return format_error_response(CommonErrors.api_server_error(f"Unexpected error: {str(e)}"))

async def get_members_by_district(ctx: Context, state_code: str, district: int) -> str:
    """
    Get members from a specific congressional district.
    
    Args:
        state_code: The two-letter state code (e.g., "MI" for Michigan)
        district: The district number (e.g., 10)
        
    Returns a list of members who represent the specified district.
    """
    try:
        # Validate state_code parameter
        state_validation = validator.validate_state_code(state_code)
        if not state_validation.is_valid:
            return format_error_response(CommonErrors.invalid_parameter(
                "state_code", state_code, state_validation.error_message
            ))
        
        state_code = state_validation.sanitized_value
        
        # Validate district parameter
        if not isinstance(district, int) or district < 1:
            return format_error_response(CommonErrors.invalid_parameter(
                "district", district, "District must be a positive integer (e.g., 1, 2, 10)"
            ))
        
        data = await safe_congressional_request(f"/member/{state_code}/{district}", ctx, {"currentMember": "true"}, endpoint_type='members')
        
        if "error" in data:
            return format_error_response(CommonErrors.api_server_error(f"Error retrieving members for {state_code}-{district}: {data['error']}"))
        
        members = data.get("members", [])
        if not members:
            return f"No members found for {state_code} district {district}."
        
        # Process and deduplicate results
        members = response_processor.deduplicate_results(
            members, 
            key_fields=["bioguideId"]
        )
        
        result = [f"# Members from {state_code} District {district}"]
        result.append(f"Found {len(members)} current members:")
        
        for member in members:
            result.append("\n" + format_member_summary(member))
        
        return "\n".join(result)
        
    except Exception as e:
        logger.error(f"Error in get_members_by_district: {str(e)}")
        return format_error_response(CommonErrors.api_server_error(f"Unexpected error: {str(e)}"))

async def search_members(
    ctx: Context,
    name: Optional[str] = None,
    state: Optional[str] = None,
    party: Optional[str] = None,
    chamber: Optional[str] = None,
    congress: Optional[int] = None,
    current_member: bool = True,
    limit: int = 10,
    district: Optional[int] = None
) -> str:
    """
    Search for members of Congress based on various criteria.
    
    Args:
        name: Optional name to search for
        state: Optional state abbreviation (e.g., 'CA', 'TX')
        party: Optional party affiliation ('D', 'R', 'I')
        chamber: Optional chamber ('house' or 'senate')
        congress: Optional Congress number (e.g., 117)
        current_member: Whether to only include current members (default: True)
        limit: Maximum number of results to return (default: 10)
        district: Optional district number for the district (e.g., 10)
    
    Returns:
        A formatted list of members matching the search criteria.
    """
    try:
        # Validate limit parameter
        limit_validation = validator.validate_limit_range(limit, 250)
        if not limit_validation.is_valid:
            return format_error_response(CommonErrors.invalid_parameter(
                "limit", limit, limit_validation.error_message
            ))
        
        # Validate congress parameter if provided
        if congress is not None:
            congress_validation = validator.validate_congress_number(congress)
            if not congress_validation.is_valid:
                return format_error_response(CommonErrors.invalid_parameter(
                    "congress", congress, congress_validation.error_message
                ))
        
        # Validate state parameter if provided
        if state is not None:
            state_validation = validator.validate_state_code(state)
            if not state_validation.is_valid:
                return format_error_response(CommonErrors.invalid_parameter(
                    "state", state, state_validation.error_message
                ))
            state = state_validation.sanitized_value
        
        # Validate chamber parameter if provided
        if chamber is not None:
            chamber = chamber.lower().strip()
            if chamber not in ["house", "senate"]:
                return format_error_response(CommonErrors.invalid_parameter(
                    "chamber", chamber, "Chamber must be 'house' or 'senate'"
                ))
        
        # Validate party parameter if provided
        if party is not None:
            party = party.upper().strip()
            if party not in ["D", "R", "I", "DEMOCRATIC", "REPUBLICAN", "INDEPENDENT"]:
                return format_error_response(CommonErrors.invalid_parameter(
                    "party", party, "Party must be 'D', 'R', 'I', 'Democratic', 'Republican', or 'Independent'"
                ))
            # Normalize party names
            if party in ["DEMOCRATIC"]:
                party = "D"
            elif party in ["REPUBLICAN"]:
                party = "R"
            elif party in ["INDEPENDENT"]:
                party = "I"
        
        # Validate district parameter if provided
        if district is not None:
            if not isinstance(district, int) or district < 1:
                return format_error_response(CommonErrors.invalid_parameter(
                    "district", district, "District must be a positive integer (e.g., 1, 2, 10)"
                ))
        
        # Build search parameters
        params = {"limit": limit}
        if current_member:
            params["currentMember"] = "true"
        
        # Determine the best API endpoint based on provided parameters
        endpoint = "/member"
        
        # If we have specific state and district, use the district endpoint
        if state and district:
            endpoint = f"/member/{state}/{district}"
        # If we have state but no district, use the state endpoint
        elif state and not district:
            endpoint = f"/member/{state}"
        # If we have congress, use the congress endpoint
        elif congress:
            endpoint = f"/member/congress/{congress}"
        
        # For name-only searches, we need comprehensive data across congresses
        # Use pagination to get all members
        if name and not any([state, congress, district, chamber, party]):
            # Progressive search strategy: current congress first, then previous
            congress_search_order = [118, 117, 116]  # Current and recent congresses
            
            all_members = []
            for search_congress in congress_search_order:
                congress_members = await get_all_members_paginated(
                    ctx, f"/member/congress/{search_congress}", params
                )
                if "error" in congress_members:
                    continue  # Skip this congress if error, try next
                
                members_list = congress_members.get("members", [])
                if members_list:
                    all_members.extend(members_list)
                
                # Early termination if we find matches
                if name:
                    # Quick check if any member might match the name
                    potential_matches = []
                    search_name = name.lower().strip()
                    for member in members_list:
                        member_names = []
                        if "directOrderName" in member and member["directOrderName"]:
                            member_names.append(member["directOrderName"].lower())
                        if "invertedOrderName" in member and member["invertedOrderName"]:
                            member_names.append(member["invertedOrderName"].lower())
                        if isinstance(member.get("name"), str):
                            member_names.append(member["name"].lower())
                        
                        if any(search_name in member_name for member_name in member_names):
                            potential_matches.append(member)
                    
                    if potential_matches:
                        # Found matches in this congress, no need to search further back
                        break
            
            # Use the aggregated data
            data = {"members": all_members}
        else:
            # Use single endpoint request for other cases
            data = await safe_congressional_request(endpoint, ctx, params, endpoint_type='members')
        
        if "error" in data:
            return format_error_response(CommonErrors.api_server_error(f"Error searching members: {data['error']}"))
        
        members = data.get("members", [])
        if not members:
            return "No members found matching the specified criteria."
        
        # Debug: Log the first few members and their name fields
        if name and len(members) > 0:
            logger.info(f"DEBUG: Searching for name '{name}' in {len(members)} members")
            for i, member in enumerate(members[:3]):  # Log first 3 members
                name_fields = {
                    "directOrderName": member.get("directOrderName"),
                    "invertedOrderName": member.get("invertedOrderName"),
                    "name": member.get("name"),
                    "bioguideId": member.get("bioguideId")
                }
                logger.info(f"DEBUG: Member {i+1} name fields: {name_fields}")
        
        # Apply client-side filtering for parameters not supported by the API endpoint
        filtered_members = []
        
        for member in members:
            # Filter by name if provided
            if name:
                member_names = []
                
                # Collect all possible name representations
                if "directOrderName" in member and member["directOrderName"]:
                    member_names.append(member["directOrderName"].lower())
                if "invertedOrderName" in member and member["invertedOrderName"]:
                    member_names.append(member["invertedOrderName"].lower())
                if isinstance(member.get("name"), str):
                    member_names.append(member["name"].lower())
                elif isinstance(member.get("name"), dict):
                    name_dict = member["name"]
                    first = name_dict.get("firstName", "")
                    last = name_dict.get("lastName", "")
                    if first and last:
                        member_names.append(f"{first} {last}".lower())
                        member_names.append(f"{last}, {first}".lower())
                    if first:
                        member_names.append(first.lower())
                    if last:
                        member_names.append(last.lower())
                
                # Check if the search name matches any of the member name representations
                search_name = name.lower().strip()
                name_match = any(search_name in member_name for member_name in member_names)
                
                # Debug: Log the name matching attempt
                bioguide_id = member.get("bioguideId", "unknown")
                logger.info(f"DEBUG: Matching '{search_name}' against {member_names} (bioguideId: {bioguide_id}): {name_match}")
                
                if not name_match:
                    continue
            
            # Filter by party if provided
            if party:
                member_party = ""
                if "partyHistory" in member and isinstance(member["partyHistory"], list) and member["partyHistory"]:
                    party_history = member["partyHistory"][0]
                    if isinstance(party_history, dict):
                        member_party = party_history.get("partyAbbreviation", "")
                elif "partyName" in member:
                    member_party = member["partyName"]
                elif "party" in member:
                    member_party = member["party"]
                
                # Normalize member party for comparison
                if member_party.lower() in ["democratic", "d"]:
                    member_party = "D"
                elif member_party.lower() in ["republican", "r"]:
                    member_party = "R"
                elif member_party.lower() in ["independent", "i"]:
                    member_party = "I"
                
                if party != member_party:
                    continue
            
            # Filter by chamber if provided
            if chamber:
                member_chamber = ""
                if "terms" in member:
                    terms = member["terms"]
                    if isinstance(terms, dict) and "item" in terms:
                        terms = terms["item"]
                    if terms and isinstance(terms, list) and terms:
                        # Get the most recent term
                        latest_term = terms[-1]
                        member_chamber = latest_term.get("chamber", "").lower()
                
                if chamber != member_chamber:
                    continue
            
            filtered_members.append(member)
        
        # Process and deduplicate results
        filtered_members = response_processor.deduplicate_results(
            filtered_members, 
            key_fields=["bioguideId"]
        )
        
        # Apply limit to filtered results
        if len(filtered_members) > limit:
            filtered_members = filtered_members[:limit]
        
        if not filtered_members:
            return "No members found matching the specified criteria after filtering."
        
        # Format results
        result = ["# Member Search Results"]
        result.append(f"Found {len(filtered_members)} members:")
        
        for member in filtered_members:
            result.append("\n" + format_member_summary(member))
        
        return "\n".join(result)
        
    except Exception as e:
        logger.error(f"Error in search_members: {str(e)}")
        return format_error_response(CommonErrors.api_server_error(f"Unexpected error: {str(e)}"))

async def get_members_by_congress_state_district(
    ctx: Context,
    congress: int,
    state_code: str,
    district: Optional[int] = None,
    current_member: bool = True
) -> str:
    """
    Get members filtered by congress, state and optionally district.

    Args:
        congress: The Congress number (e.g., 118)
        state_code: The two letter identifier for the state (e.g., 'MI' for Michigan)
        district: Optional district number for the district (e.g., 10)
        current_member: Whether to only include current members (default: True)
    
    Returns:
        A formatted list of members matching the specified criteria.
    """
    try:
        # Validate congress parameter
        congress_validation = validator.validate_congress_number(congress)
        if not congress_validation.is_valid:
            return format_error_response(CommonErrors.invalid_parameter(
                "congress", congress, congress_validation.error_message
            ))
        
        # Validate state_code parameter
        state_validation = validator.validate_state_code(state_code)
        if not state_validation.is_valid:
            return format_error_response(CommonErrors.invalid_parameter(
                "state_code", state_code, state_validation.error_message
            ))
        
        state_code = state_validation.sanitized_value
        
        # Validate district parameter if provided
        if district is not None:
            if not isinstance(district, int) or district < 1:
                return format_error_response(CommonErrors.invalid_parameter(
                    "district", district, "District must be a positive integer (e.g., 1, 2, 10)"
                ))
        
        # Build parameters
        params = {}
        if current_member:
            params["currentMember"] = "true"
        
        # Determine endpoint based on whether district is provided
        if district is not None:
            endpoint = f"/member/{state_code}/{district}"
        else:
            endpoint = f"/member/{state_code}"
        
        # Make the API request
        data = await safe_congressional_request(endpoint, ctx, params, endpoint_type='members')
        
        if "error" in data:
            return format_error_response(CommonErrors.api_server_error(f"Error retrieving members: {data['error']}"))
        
        members = data.get("members", [])
        if not members:
            district_str = f" district {district}" if district else ""
            return f"No members found for {state_code}{district_str} in Congress {congress}."
        
        # Filter by congress if the API doesn't handle it directly
        filtered_members = []
        for member in members:
            # Check if member served in the specified congress
            if "terms" in member:
                terms = member["terms"]
                # Handle case where terms might be wrapped in an object with 'item' key
                if isinstance(terms, dict) and "item" in terms:
                    terms = terms["item"]
                
                if terms and isinstance(terms, list):
                    # Check if any term matches the specified congress
                    for term in terms:
                        if isinstance(term, dict) and term.get("congress") == congress:
                            filtered_members.append(member)
                            break
        
        # Process and deduplicate results
        filtered_members = response_processor.deduplicate_results(
            filtered_members, 
            key_fields=["bioguideId"]
        )
        
        if not filtered_members:
            district_str = f" district {district}" if district else ""
            return f"No members found for {state_code}{district_str} in the {congress}th Congress."
        
        # Format results
        district_str = f" District {district}" if district else ""
        result = [f"# Members from {state_code}{district_str} - {congress}th Congress"]
        result.append(f"Found {len(filtered_members)} members:")
        
        for member in filtered_members:
            result.append("\n" + format_member_summary(member))
        
        return "\n".join(result)
        
    except Exception as e:
        logger.error(f"Error in get_members_by_congress_state_district: {str(e)}")
        return format_error_response(CommonErrors.api_server_error(f"Unexpected error: {str(e)}"))

async def get_all_members_paginated(ctx: Context, endpoint: str, base_params: Dict[str, Any]) -> Dict[str, Any]:
    """
    Get all members from an endpoint using pagination.
    
    Args:
        ctx: The context object
        endpoint: The API endpoint to call
        base_params: Base parameters for the request
        
    Returns:
        Dictionary containing all members or error information
    """
    try:
        all_members = []
        offset = 0
        limit = 250  # Maximum per request
        
        while True:
            # Create params for this request
            params = base_params.copy()
            params.update({"limit": limit, "offset": offset})
            
            # Make the API request
            logger.info(f"Fetching members from {endpoint} with offset={offset}, limit={limit}")
            data = await safe_congressional_request(endpoint, ctx, params, endpoint_type='members')
            
            if "error" in data:
                if offset == 0:
                    # If first request fails, return the error
                    return data
                else:
                    # If later request fails, break and return what we have
                    logger.warning(f"Pagination request failed at offset {offset}: {data['error']}")
                    break
            
            members = data.get("members", [])
            if not members:
                # No more members to fetch
                break
            
            all_members.extend(members)
            logger.info(f"Fetched {len(members)} members (total so far: {len(all_members)})")
            
            # If we got fewer members than the limit, we've reached the end
            if len(members) < limit:
                break
            
            # Move to next page
            offset += limit
            
            # Safety check to prevent infinite loops
            if offset > 2000:  # More than reasonable for any congress
                logger.warning(f"Pagination safety limit reached at offset {offset}")
                break
        
        logger.info(f"Pagination complete. Total members fetched: {len(all_members)}")
        return {"members": all_members}
        
    except Exception as e:
        logger.error(f"Error in get_all_members_paginated: {str(e)}")
        return {"error": f"Pagination error: {str(e)}"}

# Formatting helpers
def format_member_summary(member: Dict[str, Any]) -> str:
    """Format a member into a readable summary."""
    # Handle name field - can be string or nested object
    name_str = "Unknown"
    if "name" in member:
        if isinstance(member["name"], str):
            name_str = member["name"]
        elif isinstance(member["name"], dict):
            first = member["name"].get("firstName", "")
            middle = member["name"].get("middleName", "")
            last = member["name"].get("lastName", "")
            name_str = f"{first} {middle} {last}".strip()
            # Clean up extra spaces
            name_str = " ".join(name_str.split())
    
    result = []
    result.append(f"## {name_str}")
    result.append(f"Bioguide ID: {member.get('bioguideId', 'Unknown')}")
    
    # Handle party information - try multiple possible fields
    party = "Unknown"
    if "partyHistory" in member and isinstance(member["partyHistory"], list) and member["partyHistory"]:
        party_history = member["partyHistory"][0]
        if isinstance(party_history, dict):
            party = party_history.get("partyAbbreviation", "")
    elif "partyName" in member and member["partyName"]:
        party = member["partyName"]
    elif "party" in member and member["party"]:
        party = member["party"]
    # Map party codes to full names if needed
    if party == "D" or party.lower() == "d":
        party = "Democratic"
    elif party == "R" or party.lower() == "r":
        party = "Republican"
    elif party == "I" or party.lower() == "i":
        party = "Independent"
    result.append(f"Party: {party}")
    
    result.append(f"State: {member.get('state', 'Unknown')}")
    
    # District (only for House members)
    if "district" in member and member["district"]:
        result.append(f"District: {member['district']}")
    
    # Handle terms information
    if "terms" in member:
        terms = member["terms"]
        # Handle case where terms might be wrapped in an object with 'item' key
        if isinstance(terms, dict) and "item" in terms:
            terms = terms["item"]
        
        if terms and isinstance(terms, list) and len(terms) > 0:
            latest_term = terms[0]
            if isinstance(latest_term, dict):
                chamber = latest_term.get('chamber', 'Unknown')
                result.append(f"Chamber: {chamber}")
                
                # Add term years if available
                start_year = latest_term.get('startYear', 'Unknown')
                end_year = latest_term.get('endYear', 'Present')
                if start_year != 'Unknown':
                    result.append(f"Term: {start_year} - {end_year}")
    
    # URL
    url = member.get("url", "No URL available")
    result.append(f"URL: {url}")
    
    return "\n".join(result)
