import random
import string
import psycopg2
from psycopg2 import sql
from datetime import datetime, timedelta,timezone
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import base64
import json
from datetime import datetime
from jose import JWTError, jwt
import qrcode
import base64
from io import BytesIO

#schemas
from src.schemas.application_user import CurrentApplicationUser
from src.schemas.compnay_user import CurrentCompanyUser

from src.constants import UserType,ApplicationUserRoleEnum
from fastapi import  HTTPException, status

from src.auth.utils import create_jwt_access_token

def generate_password(length=8):
    # Define the possible characters for the password
    characters = string.ascii_letters + string.digits + string.punctuation
    # Randomly choose characters and form the password
    password = ''.join(random.choice(characters) for _ in range(length))
    return password


SECRET_KEY = "thrinath@123"  
ALGORITHM = "HS256"


def encrypt_reset_payload(payload: dict) -> str:
    token  = create_jwt_access_token(data=payload)
    return token

def decrypt_reset_token(token: str) -> dict:
    try:
        data = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        # Extract user details
        return data
    except JWTError:
        print(JWTError)
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials....",
            headers={"WWW-Authenticate": "Bearer"},
        )


def add_delete_update_company_user_access_check(currentCompanyUser:CurrentCompanyUser,action):

    if currentCompanyUser.role.lower() != "admin" or currentCompanyUser.department.lower() != "it":
        return False
    else:
        return True
    
def add_delete_update_application_user_access_check(currentApplicationUser:CurrentApplicationUser,action):
    print(currentApplicationUser)
    print(currentApplicationUser.role.lower(),ApplicationUserRoleEnum.ADMIN.value,currentApplicationUser.user_type,UserType.APPLICATION.value)
    
    if currentApplicationUser.role.lower() == ApplicationUserRoleEnum.ADMIN.value and currentApplicationUser.user_type == UserType.APPLICATION.value:
        return True
    else:
        return False



import logging
import os
from logging.handlers import RotatingFileHandler

# 1. Create logs directory if it doesn’t exist
os.makedirs("logs", exist_ok=True)

# 2. Get a named logger (you can choose any name you like)
logger = logging.getLogger("mcp_client")
logger.setLevel(logging.DEBUG)  # capture DEBUG and higher for this logger

# 3. Console handler: DEBUG+
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

console_formatter = logging.Formatter(
    "%(asctime)s %(name)s [%(levelname)s]  %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)

# 4. File handler (rotating): INFO+ goes to a file
file_handler = RotatingFileHandler(
    filename="app.log",
    maxBytes=5 * 1024 * 1024,  # 5 MB per file
    backupCount=3,             # keep up to 3 old log files
)
file_handler.setLevel(logging.INFO)

file_formatter = logging.Formatter(
    "%(asctime)s %(name)s [%(levelname)s] (%(filename)s:%(lineno)d)  %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)

# 5. (Optional) Silence overly‐verbose third‐party loggers
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.getLogger("asyncio").setLevel(logging.WARNING)



from sqlalchemy.ext.asyncio import create_async_engine
from src.core.database import Base

from sqlalchemy.ext.asyncio import create_async_engine

async def init_dynamic_db(db_url: str, tables_to_skip: list[str] = None):
    if tables_to_skip is None:
        tables_to_skip = []

    engine = create_async_engine(db_url, echo=True)

    # Filter tables to include only those not in the skip list
    tables_to_include = [
        table
        for name, table in Base.metadata.tables.items()
        if name not in tables_to_skip
    ]

    async with engine.begin() as conn:
        await conn.run_sync(lambda sync_conn: Base.metadata.create_all(sync_conn, tables=tables_to_include))

    await engine.dispose()

    # Return created table names for confirmation
    return [t.name for t in tables_to_include]
