# # app/services/agent.py

# import hashlib
# from sqlalchemy import select, update
# from sqlalchemy.ext.asyncio import AsyncSession
# from app.models.agent import Agent
# from app.schemas.agent import AgentCreate, AgentLogin


# def _hash_password(password: str) -> str:
#     return hashlib.sha256(password.encode("utf-8")).hexdigest()


# async def create_agent(db: AsyncSession, data: AgentCreate) -> Agent:
#     hashed = _hash_password(data.password)

#     agent = Agent(
#         name=data.name,
#         email=data.email,
#         password_hash=hashed,
#     )
#     db.add(agent)
#     await db.commit()
#     await db.refresh(agent)
#     return agent


# async def authenticate_agent(db: AsyncSession, data: AgentLogin) -> Agent | None:
#     hashed = _hash_password(data.password)
#     result = await db.execute(
#         select(Agent).where( Agent.email == data.email, Agent.password_hash == hashed )
#     )
#     return result.scalar_one_or_none()


# async def set_agent_online(db: AsyncSession, agent_id: int, online: bool) -> None:
#     await db.execute(update(Agent).where(Agent.id == agent_id).values(is_online=online))
#     await db.commit()


# ---------------------------------------------------------------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------------------------------------------------------------

# app/services/agent.py

from sqlalchemy.sql import func
from sqlalchemy import select, update
from datetime import datetime ,timezone
from sqlalchemy.ext.asyncio import AsyncSession
from app.schemas.agent import AgentCreate, AgentLogin
from app.models.agent import Agent, AgentAssignmentHistory

# ------------------------
# Agent CRUD
# ------------------------
async def get_agent_by_id(db: AsyncSession, agent_id: int) -> Agent | None:
    result = await db.execute(select(Agent).where(Agent.id == agent_id))
    return result.scalar_one_or_none()


async def register_agent(db: AsyncSession, data: AgentCreate) -> Agent:
    
    result = await db.execute(select(Agent).where(Agent.email == data.email))
    existing = result.scalar_one_or_none()
    if existing:
        raise ValueError("Agent with this email already exists")

    agent = Agent( name=data.name, email=data.email, password_hash=data.password )
    
    db.add(agent)
    await db.commit()
    await db.refresh(agent)
    return agent


async def login_agent(db: AsyncSession, data: AgentLogin) -> Agent | None:
    result = await db.execute(select(Agent).where(Agent.email == data.email))
    agent = result.scalar_one_or_none()
    if not agent or agent.password_hash != data.password:
        return None
    return agent


async def set_agent_status(db: AsyncSession, agent_id: int, status: str):
    await db.execute(
        update(Agent).where(Agent.id == agent_id).values(status=status)
    )
    await db.commit()


# ------------------------
# Assignment logic
# ------------------------

async def get_active_assignment(db: AsyncSession, visitor_id: int) -> AgentAssignmentHistory | None:
    result = await db.execute(
        select(AgentAssignmentHistory).where(
            AgentAssignmentHistory.visitor_id == visitor_id,
            AgentAssignmentHistory.ended_at.is_(None)
        )
    )
    return result.scalar_one_or_none()


async def assign_agent_to_visitor(db: AsyncSession, agent_id: int, visitor_id: int) -> AgentAssignmentHistory:
    # Check if already assigned to someone
    existing = await get_active_assignment(db, visitor_id)
    if existing and existing.agent_id != agent_id:
        # Someone else already owns this chat
        raise ValueError("Visitor already assigned to another agent")

    if existing and existing.agent_id == agent_id:
        # Already assigned to same agent
        return existing

    # Create new assignment
    assignment = AgentAssignmentHistory(
        agent_id=agent_id,
        visitor_id=visitor_id,
    )
    db.add(assignment)
    await db.commit()
    await db.refresh(assignment)
    return assignment


async def release_assignment(db: AsyncSession, agent_id: int, visitor_id: int):
    # End active assignment for this agent + visitor
    result = await db.execute(
        select(AgentAssignmentHistory).where(
            AgentAssignmentHistory.agent_id == agent_id,
            AgentAssignmentHistory.visitor_id == visitor_id,
            AgentAssignmentHistory.ended_at.is_(None),
        )
    )
    assignment = result.scalar_one_or_none()
    if not assignment:
        return
    assignment.ended_at = func.now()
    await db.commit()


async def update_agent_status(db: AsyncSession, agent_id: int, is_online: bool):
    
    result = await db.execute(select(Agent).where(Agent.id == agent_id))
    agent = result.scalar_one_or_none()

    if agent:
        agent.is_online = is_online
        agent.last_seen_at = datetime.now(timezone.utc)
        await db.commit()
        await db.refresh(agent)

    return agent
