import os
import re
from datetime import datetime

def create_dependency_file():
    """
    Reads the 'tokens_repo.py' file to identify roles, then generates a
    'dependencies.py' file with corresponding FastAPI dependency functions
    for token verification.
    """
    repo_path = os.path.join("repositories", "tokens_repo.py")
    if not os.path.exists(repo_path):
        print(f"❌ Error: Repository file not found at '{repo_path}'.")
        print("Please run the token repository generator first.")
        return

    # --- 1. Read the repository file and extract roles ---
    try:
        with open(repo_path, "r", encoding="utf-8") as f:
            repo_content = f.read()
            
        # Use regex to find all role names from the activate functions
        # This is a reliable way to get the roles the repo was built for
        # e.g., finds "admin" in "activate_admin_access_token"
        pattern = r"async def activate_(\w+)_access_token"
        roles = sorted(list(set(re.findall(pattern, repo_content))))

        if not roles:
            print("❌ Error: No roles found in 'tokens_repo.py'. The file might be empty or invalid.")
            return
            
    except IOError as e:
        print(f"❌ Error reading repository file: {e}")
        return

    # --- 2. Create the 'security' directory ---
    directory = "security"
    if not os.path.exists(directory):
        os.makedirs(directory)
        print(f"Created directory: '{directory}/'")

    # --- 3. Start building the dependency file content ---
    file_content = f"""
# ============================================================================
# AUTHENTICATION DEPENDENCIES
# ============================================================================
# This file was auto-generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S WAT')}
# It contains FastAPI dependencies for verifying JWT tokens.
#
# DO NOT EDIT THIS FILE MANUALLY - RE-RUN THE GENERATOR INSTEAD.
# ============================================================================

from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer

# Import functions from your other security and repository files
# Note: Ensure these files and functions exist in your project structure.
from security.encrypting_jwt import decode_jwt_token
from repositories.tokens_repo import get_valid_access_token, get_token_details_for_refresh, delete_access_token, add_refresh_token
from schemas.tokens_schema import refreshedToken

# This is the security scheme for requiring a bearer token (e.g., "Authorization: Bearer <token>")
token_auth_scheme = HTTPBearer()

# --- Generic Verification Dependencies ---

async def verify_any_active_token(token: str = Depends(token_auth_scheme)):
    \"\"\"
    A generic dependency to protect endpoints. It ensures the user provides
    a valid, active, and non-expired token, regardless of their role.
    
    Returns:
        The decoded token payload if valid.
    \"\"\"
    token_details = await get_valid_access_token(token_id=token.credentials)
    
    if not token_details:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid, expired, or inactive token provided."
        )
    
    # If the token is valid in the database, we can decode and return its contents
    decoded_payload = await decode_jwt_token(token=token.credentials)
    if not decoded_payload:
         raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Could not decode token."
        )
    return decoded_payload

# --- Role-Specific Verification Dependencies ---
"""

    # --- 4. Dynamically generate dependency functions for each role ---
    role_specific_functions = []
    for role in roles:
        # Sanitize role name for the function name
        safe_role_name = role.strip().lower()
        
        verify_func = f"""
async def verify_{safe_role_name}_token(token: str = Depends(token_auth_scheme)):
    \"\"\"
    Dependency to ensure the user is an authenticated '{safe_role_name}'
    with a valid, active, and non-expired token.
    \"\"\"
    token_details = await get_valid_access_token(token_id=token.credentials)
    
    # The get_valid_access_token function handles expiration, existence, and status.
    # We only need to add the role check.
    if not token_details or token_details.role != '{safe_role_name}':
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied. Requires '{safe_role_name}' privileges."
        )
        
    decoded_payload = await decode_jwt_token(token=token.credentials)
    if not decoded_payload:
         raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Could not decode token for {safe_role_name}."
        )
    return decoded_payload
"""
        role_specific_functions.append(verify_func)

    # --- 5. Add a token refresh dependency ---
    # This is a common requirement, so we'll add it here.
    # Note: This function would require your 'generate_x_access_tokens' functions.
    # You will need to import them manually in the generated file.
    refresh_dependency = """
# --- Token Refresh Dependency ---

async def refresh_access_token(token: str = Depends(token_auth_scheme)):
    \"\"\"
    Handles the logic for refreshing an access token. It expects an OLD,
    possibly expired access token and returns a new pair of access and refresh tokens.
    
    NOTE: You must import your token generation functions into this file for this
          to work, for example:
          `from security.tokens import generate_admin_access_tokens, generate_user_access_tokens`
    \"\"\"
    # This repo function gets token details without checking expiration
    old_token_details = await get_token_details_for_refresh(token_id=token.credentials)

    if not old_token_details:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token to be refreshed does not exist."
        )
        
    # Placeholder for your token generation logic.
    # You will need to import and call your specific generator functions here.
    # For example:
    # if old_token_details.role == "admin":
    #     new_access_token_obj = await generate_admin_access_tokens(userId=old_token_details.userId)
    # elif old_token_details.role == "user":
    #     new_access_token_obj = await generate_user_access_tokens(userId=old_token_details.userId)
    # else:
    #     raise HTTPException(status_code=400, detail="Cannot refresh token for unknown role.")
    
    # This is a simplified placeholder. Replace with your actual logic.
    raise HTTPException(status_code=501, detail="Token refresh logic not implemented. Please edit security/dependencies.py")
    
    # # ---- Example of full implementation ----
    # # (You would uncomment and adapt this section)
    #
    # # Create a new refresh token linked to the NEW access token
    # new_refresh_token_obj = await add_refresh_token(
    #     token_data={
    #         "userId": old_token_details.userId,
    #         "previousAccessToken": new_access_token_obj.accesstoken
    #     }
    # )
    #
    # # Clean up the old access token that was just refreshed
    # await delete_access_token(token_id=old_token_details.accesstoken)
    #
    # # Return the new pair of tokens to the client
    # return refreshedToken(
    #     userId=old_token_details.userId,
    #     refreshToken=new_refresh_token_obj.refreshtoken,
    #     accessToken=new_access_token_obj.accesstoken
    # )

"""
    # --- 6. Final Assembly and File Writing ---
    final_content = file_content + "\n".join(role_specific_functions) + refresh_dependency
    file_path = os.path.join(directory, "dependencies.py")
    
    try:
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(final_content)
        print(f"✅ Successfully generated dependency file at: '{file_path}'")
        print(f"   Dependencies created for roles: {', '.join(roles)}")
    except IOError as e:
        print(f"❌ Error writing to file: {e}")

 