# app/api/v1/endpoints/chores.py
import logging
from typing import List as PyList, Optional
from datetime import datetime, timezone

from fastapi import APIRouter, Depends, HTTPException, status, Response
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from app.database import get_transactional_session, get_session
from app.auth import current_active_user
from app.models import User as UserModel, Chore as ChoreModel, ChoreTypeEnum, TimeEntry
from app.schemas.chore import (
    ChoreCreate, ChoreUpdate, ChorePublic, 
    ChoreAssignmentCreate, ChoreAssignmentUpdate, ChoreAssignmentPublic,
    ChoreHistoryPublic, ChoreAssignmentHistoryPublic
)
from app.schemas.time_entry import TimeEntryPublic
from app.crud import chore as crud_chore
from app.crud import history as crud_history
from app.crud import group as crud_group
from app.core.exceptions import ChoreNotFoundError, PermissionDeniedError, GroupNotFoundError, DatabaseIntegrityError, GroupMembershipError, GroupPermissionError

logger = logging.getLogger(__name__)
router = APIRouter()

# --- Remove legacy duplicate chore endpoints (personal/* and groups/*/chores/*) ---
_UNSUPPORTED_CHORE_PATHS = {
    "/personal",
    "/personal/{chore_id}",
    "/groups/{group_id}/chores",
    "/groups/{group_id}/chores/{chore_id}",
}
router.routes = [r for r in router.routes if getattr(r, "path", None) not in _UNSUPPORTED_CHORE_PATHS]

@router.get(
    "/all",
    response_model=PyList[ChorePublic],
    summary="List All Chores",
    tags=["Chores"]
)
async def list_all_chores(
    db: AsyncSession = Depends(get_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Retrieves all chores (personal and group) for the current user in a single optimized request."""
    logger.info(f"User {current_user.email} listing all their chores")
    
    all_chores = await crud_chore.get_all_user_chores(db=db, user_id=current_user.id)
    
    return all_chores

# --- Personal Chores Endpoints ---

@router.post(
    "/personal",
    response_model=ChorePublic,
    status_code=status.HTTP_201_CREATED,
    summary="Create Personal Chore",
    tags=["Chores", "Personal Chores"]
)
async def create_personal_chore(
    chore_in: ChoreCreate,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Creates a new personal chore for the current user."""
    logger.info(f"User {current_user.email} creating personal chore: {chore_in.name}")
    if chore_in.type != ChoreTypeEnum.personal:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Chore type must be personal.")
    if chore_in.group_id is not None:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="group_id must be null for personal chores.")
    try:
        return await crud_chore.create_chore(db=db, chore_in=chore_in, user_id=current_user.id)
    except ValueError as e:
        logger.warning(f"ValueError creating personal chore for user {current_user.email}: {str(e)}")
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError creating personal chore for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

@router.get(
    "/personal",
    response_model=PyList[ChorePublic],
    summary="List Personal Chores",
    tags=["Chores", "Personal Chores"]
)
async def list_personal_chores(
    db: AsyncSession = Depends(get_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Retrieves all personal chores for the current user."""
    logger.info(f"User {current_user.email} listing their personal chores")
    return await crud_chore.get_personal_chores(db=db, user_id=current_user.id)

@router.put(
    "/personal/{chore_id}",
    response_model=ChorePublic,
    summary="Update Personal Chore",
    tags=["Chores", "Personal Chores"]
)
async def update_personal_chore(
    chore_id: int,
    chore_in: ChoreUpdate,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Updates a personal chore for the current user."""
    logger.info(f"User {current_user.email} updating personal chore ID: {chore_id}")
    if chore_in.type is not None and chore_in.type != ChoreTypeEnum.personal:
         raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Cannot change chore type to group via this endpoint.")
    if chore_in.group_id is not None:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="group_id must be null for personal chores.")
    try:
        updated_chore = await crud_chore.update_chore(db=db, chore_id=chore_id, chore_in=chore_in, user_id=current_user.id, group_id=None)
        if not updated_chore:
            raise ChoreNotFoundError(chore_id=chore_id)
        if updated_chore.type != ChoreTypeEnum.personal or updated_chore.created_by_id != current_user.id:
            # This should ideally be caught by the CRUD layer permission checks
            raise PermissionDeniedError(detail="Chore is not a personal chore of the current user or does not exist.")
        return updated_chore
    except ChoreNotFoundError as e:
        logger.warning(f"Personal chore {e.chore_id} not found for user {current_user.email} during update.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} updating personal chore {chore_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except ValueError as e:
        logger.warning(f"ValueError updating personal chore {chore_id} for user {current_user.email}: {str(e)}")
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError updating personal chore {chore_id} for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

@router.put(
    "/{chore_id}",
    response_model=ChorePublic,
    summary="Update Chore (Any Type)",
    tags=["Chores"]
)
async def update_chore_any_type(
    chore_id: int,
    chore_in: ChoreUpdate,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Updates a chore of any type, including conversions between personal and group chores."""
    logger.info(f"User {current_user.email} updating chore ID: {chore_id}")
    
    # Get the current chore to determine its type and group
    current_chore = await crud_chore.get_chore_by_id(db, chore_id)
    if not current_chore:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Chore {chore_id} not found")
    
    # Check permissions on the current chore
    if current_chore.type == ChoreTypeEnum.personal:
        if current_chore.created_by_id != current_user.id:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="You can only update your own personal chores")
    else:  # group chore
        if not await crud_group.is_user_member(db, current_chore.group_id, current_user.id):
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=f"You are not a member of group {current_chore.group_id}")
    
    # If converting to group chore, validate the target group
    if chore_in.type == ChoreTypeEnum.group and chore_in.group_id:
        if not await crud_group.is_user_member(db, chore_in.group_id, current_user.id):
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=f"You are not a member of target group {chore_in.group_id}")
    
    try:
        # Use the current group_id for the update call if not changing groups
        group_id_for_update = current_chore.group_id if current_chore.type == ChoreTypeEnum.group else None
        
        updated_chore = await crud_chore.update_chore(
            db=db, 
            chore_id=chore_id, 
            chore_in=chore_in, 
            user_id=current_user.id, 
            group_id=group_id_for_update
        )
        if not updated_chore:
            raise ChoreNotFoundError(chore_id=chore_id)
        return updated_chore
    except ChoreNotFoundError as e:
        logger.warning(f"Chore {e.chore_id} not found for user {current_user.email} during update.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} updating chore {chore_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except ValueError as e:
        logger.warning(f"ValueError updating chore {chore_id} for user {current_user.email}: {str(e)}")
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError updating chore {chore_id} for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

@router.delete(
    "/personal/{chore_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Delete Personal Chore",
    tags=["Chores", "Personal Chores"]
)
async def delete_personal_chore(
    chore_id: int,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Deletes a personal chore for the current user."""
    logger.info(f"User {current_user.email} deleting personal chore ID: {chore_id}")
    try:
        chore_to_delete = await crud_chore.get_chore_by_id(db, chore_id)
        if not chore_to_delete or chore_to_delete.type != ChoreTypeEnum.personal or chore_to_delete.created_by_id != current_user.id:
            raise ChoreNotFoundError(chore_id=chore_id, detail="Personal chore not found or not owned by user.")

        success = await crud_chore.delete_chore(db=db, chore_id=chore_id, user_id=current_user.id, group_id=None)
        if not success:
            raise ChoreNotFoundError(chore_id=chore_id)
        return Response(status_code=status.HTTP_204_NO_CONTENT)
    except ChoreNotFoundError as e:
        logger.warning(f"Personal chore {e.chore_id} not found for user {current_user.email} during delete.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e: # Should be caught by the check above
        logger.warning(f"Permission denied for user {current_user.email} deleting personal chore {chore_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError deleting personal chore {chore_id} for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

# --- Group Chores Endpoints ---

@router.post(
    "/groups/{group_id}/chores",
    response_model=ChorePublic,
    status_code=status.HTTP_201_CREATED,
    summary="Create Group Chore",
    tags=["Chores", "Group Chores"]
)
async def create_group_chore(
    group_id: int,
    chore_in: ChoreCreate,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Creates a new chore within a specific group."""
    logger.info(f"User {current_user.email} creating chore in group {group_id}: {chore_in.name}")
    if chore_in.type != ChoreTypeEnum.group:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Chore type must be group.")
    if chore_in.group_id != group_id and chore_in.group_id is not None: # Make sure chore_in.group_id matches path if provided
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Chore's group_id ({chore_in.group_id}) must match path group_id ({group_id}) or be omitted.")
    
    # Ensure chore_in has the correct group_id and type for the CRUD operation
    chore_payload = chore_in.model_copy(update={"group_id": group_id, "type": ChoreTypeEnum.group})

    try:
        return await crud_chore.create_chore(db=db, chore_in=chore_payload, user_id=current_user.id)
    except GroupNotFoundError as e:
        logger.warning(f"Group {e.group_id} not found for chore creation by user {current_user.email}.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} in group {group_id} for chore creation: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except ValueError as e:
        logger.warning(f"ValueError creating group chore for user {current_user.email} in group {group_id}: {str(e)}")
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError creating group chore for {current_user.email} in group {group_id}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

@router.get(
    "/groups/{group_id}/chores",
    response_model=PyList[ChorePublic],
    summary="List Group Chores",
    tags=["Chores", "Group Chores"]
)
async def list_group_chores(
    group_id: int,
    db: AsyncSession = Depends(get_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Retrieves all chores for a specific group, if the user is a member."""
    logger.info(f"User {current_user.email} listing chores for group {group_id}")
    try:
        return await crud_chore.get_chores_by_group_id(db=db, group_id=group_id, user_id=current_user.id)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} accessing chores for group {group_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)

@router.put(
    "/groups/{group_id}/chores/{chore_id}",
    response_model=ChorePublic,
    summary="Update Group Chore",
    tags=["Chores", "Group Chores"]
)
async def update_group_chore(
    group_id: int,
    chore_id: int,
    chore_in: ChoreUpdate,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Updates a chore's details. The group_id in path is the current group of the chore."""
    logger.info(f"User {current_user.email} updating chore ID {chore_id} in group {group_id}")
    
    # Validate that the chore is in the specified group
    chore_to_update = await crud_chore.get_chore_by_id_and_group(db, chore_id, group_id, current_user.id)
    if not chore_to_update:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Chore {chore_id} not found in group {group_id}")

    try:
        updated_chore = await crud_chore.update_chore(db=db, chore_id=chore_id, chore_in=chore_in, user_id=current_user.id, group_id=group_id)
        if not updated_chore:
            raise ChoreNotFoundError(chore_id=chore_id, group_id=group_id)
        return updated_chore
    except ChoreNotFoundError as e:
        logger.warning(f"Chore {e.chore_id} in group {e.group_id} not found for user {current_user.email} during update.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} updating chore {chore_id} in group {group_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except ValueError as e:
        logger.warning(f"ValueError updating group chore {chore_id} for user {current_user.email} in group {group_id}: {str(e)}")
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError updating group chore {chore_id} for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

@router.delete(
    "/groups/{group_id}/chores/{chore_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Delete Group Chore",
    tags=["Chores", "Group Chores"]
)
async def delete_group_chore(
    group_id: int,
    chore_id: int,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Deletes a chore from a group, ensuring user has permission."""
    logger.info(f"User {current_user.email} deleting chore ID {chore_id} from group {group_id}")
    try:
        chore_to_delete = await crud_chore.get_chore_by_id_and_group(db, chore_id, group_id, current_user.id) # checks permission too
        if not chore_to_delete : # get_chore_by_id_and_group will raise PermissionDeniedError if user not member
             raise ChoreNotFoundError(chore_id=chore_id, group_id=group_id)

        success = await crud_chore.delete_chore(db=db, chore_id=chore_id, user_id=current_user.id, group_id=group_id)
        if not success:
            raise ChoreNotFoundError(chore_id=chore_id, group_id=group_id)
        return Response(status_code=status.HTTP_204_NO_CONTENT)
    except ChoreNotFoundError as e:
        logger.warning(f"Chore {e.chore_id} in group {e.group_id} not found for user {current_user.email} during delete.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} deleting chore {chore_id} in group {group_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError deleting group chore {chore_id} for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

# === CHORE ASSIGNMENT ENDPOINTS ===

@router.post(
    "/assignments",
    response_model=ChoreAssignmentPublic,
    status_code=status.HTTP_201_CREATED,
    summary="Create Chore Assignment",
    tags=["Chore Assignments"]
)
async def create_chore_assignment(
    assignment_in: ChoreAssignmentCreate,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Creates a new chore assignment. User must have permission to manage the chore."""
    logger.info(f"User {current_user.email} creating assignment for chore {assignment_in.chore_id}")
    try:
        return await crud_chore.create_chore_assignment(db=db, assignment_in=assignment_in, user_id=current_user.id)
    except ChoreNotFoundError as e:
        logger.warning(f"Chore {e.chore_id} not found for assignment creation by user {current_user.email}.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} creating assignment: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except ValueError as e:
        logger.warning(f"ValueError creating assignment for user {current_user.email}: {str(e)}")
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError creating assignment for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

@router.get(
    "/assignments/my",
    response_model=PyList[ChoreAssignmentPublic],
    summary="List My Chore Assignments",
    tags=["Chore Assignments"]
)
async def list_my_assignments(
    include_completed: bool = False,
    db: AsyncSession = Depends(get_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Retrieves all chore assignments for the current user."""
    logger.info(f"User {current_user.email} listing their assignments (include_completed={include_completed})")
    try:
        return await crud_chore.get_user_assignments(db=db, user_id=current_user.id, include_completed=include_completed)
    except Exception as e:
        logger.error(f"Error listing assignments for user {current_user.email}: {e}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to retrieve assignments")

@router.get(
    "/{chore_id}/assignments",
    response_model=PyList[ChoreAssignmentPublic],
    summary="List Chore Assignments",
    tags=["Chore Assignments"]
)
async def list_chore_assignments(
    chore_id: int,
    db: AsyncSession = Depends(get_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Retrieves all assignments for a specific chore."""
    logger.info(f"User {current_user.email} listing assignments for chore {chore_id}")
    try:
        return await crud_chore.get_chore_assignments(db=db, chore_id=chore_id, user_id=current_user.id)
    except ChoreNotFoundError as e:
        logger.warning(f"Chore {e.chore_id} not found for assignment listing by user {current_user.email}.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} listing assignments for chore {chore_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)

@router.put(
    "/assignments/{assignment_id}",
    response_model=ChoreAssignmentPublic,
    summary="Update Chore Assignment",
    tags=["Chore Assignments"]
)
async def update_chore_assignment(
    assignment_id: int,
    assignment_in: ChoreAssignmentUpdate,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Updates a chore assignment. Only assignee can mark complete, managers can reschedule."""
    logger.info(f"User {current_user.email} updating assignment {assignment_id}")
    try:
        updated_assignment = await crud_chore.update_chore_assignment(
            db=db, assignment_id=assignment_id, assignment_in=assignment_in, user_id=current_user.id
        )
        if not updated_assignment:
            raise ChoreNotFoundError(assignment_id=assignment_id)
        return updated_assignment
    except ChoreNotFoundError as e:
        logger.warning(f"Assignment {assignment_id} not found for user {current_user.email} during update.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} updating assignment {assignment_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except ValueError as e:
        logger.warning(f"ValueError updating assignment {assignment_id} for user {current_user.email}: {str(e)}")
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError updating assignment {assignment_id} for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

@router.delete(
    "/assignments/{assignment_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Delete Chore Assignment",
    tags=["Chore Assignments"]
)
async def delete_chore_assignment(
    assignment_id: int,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Deletes a chore assignment. User must have permission to manage the chore."""
    logger.info(f"User {current_user.email} deleting assignment {assignment_id}")
    try:
        success = await crud_chore.delete_chore_assignment(db=db, assignment_id=assignment_id, user_id=current_user.id)
        if not success:
            raise ChoreNotFoundError(assignment_id=assignment_id)
        return Response(status_code=status.HTTP_204_NO_CONTENT)
    except ChoreNotFoundError as e:
        logger.warning(f"Assignment {assignment_id} not found for user {current_user.email} during delete.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} deleting assignment {assignment_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError deleting assignment {assignment_id} for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

@router.patch(
    "/assignments/{assignment_id}/complete",
    response_model=ChoreAssignmentPublic,
    summary="Mark Assignment Complete",
    tags=["Chore Assignments"]
)
async def complete_chore_assignment(
    assignment_id: int,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Convenience endpoint to mark an assignment as complete."""
    logger.info(f"User {current_user.email} marking assignment {assignment_id} as complete")
    assignment_update = ChoreAssignmentUpdate(is_complete=True)
    try:
        updated_assignment = await crud_chore.update_chore_assignment(
            db=db, assignment_id=assignment_id, assignment_in=assignment_update, user_id=current_user.id
        )
        if not updated_assignment:
            raise ChoreNotFoundError(assignment_id=assignment_id)
        return updated_assignment
    except ChoreNotFoundError as e:
        logger.warning(f"Assignment {assignment_id} not found for user {current_user.email} during completion.")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=e.detail)
    except PermissionDeniedError as e:
        logger.warning(f"Permission denied for user {current_user.email} completing assignment {assignment_id}: {e.detail}")
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except DatabaseIntegrityError as e:
        logger.error(f"DatabaseIntegrityError completing assignment {assignment_id} for {current_user.email}: {e.detail}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=e.detail)

# === CHORE HISTORY ENDPOINTS ===

@router.get(
    "/{chore_id}/history",
    response_model=PyList[ChoreHistoryPublic],
    summary="Get Chore History",
    tags=["Chores", "History"]
)
async def get_chore_history(
    chore_id: int,
    db: AsyncSession = Depends(get_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Retrieves the history of a specific chore."""
    chore = await crud_chore.get_chore_by_id(db, chore_id)
    if not chore:
        raise ChoreNotFoundError(chore_id=chore_id)
    
    if chore.type == ChoreTypeEnum.personal and chore.created_by_id != current_user.id:
        raise PermissionDeniedError("You can only view history for your own personal chores.")
    
    if chore.type == ChoreTypeEnum.group:
        is_member = await crud_chore.is_user_member(db, chore.group_id, current_user.id)
        if not is_member:
            raise PermissionDeniedError("You must be a member of the group to view this chore's history.")

    logger.info(f"User {current_user.email} getting history for chore {chore_id}")
    return await crud_history.get_chore_history(db=db, chore_id=chore_id)

@router.get(
    "/assignments/{assignment_id}/history",
    response_model=PyList[ChoreAssignmentHistoryPublic],
    summary="Get Chore Assignment History",
    tags=["Chore Assignments", "History"]
)
async def get_chore_assignment_history(
    assignment_id: int,
    db: AsyncSession = Depends(get_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Retrieves the history of a specific chore assignment."""
    assignment = await crud_chore.get_chore_assignment_by_id(db, assignment_id)
    if not assignment:
        raise ChoreNotFoundError(assignment_id=assignment_id)

    chore = await crud_chore.get_chore_by_id(db, assignment.chore_id)
    if not chore:
        raise ChoreNotFoundError(chore_id=assignment.chore_id)

    if chore.type == ChoreTypeEnum.personal and chore.created_by_id != current_user.id:
        raise PermissionDeniedError("You can only view history for assignments of your own personal chores.")
    
    if chore.type == ChoreTypeEnum.group:
        is_member = await crud_chore.is_user_member(db, chore.group_id, current_user.id)
        if not is_member:
            raise PermissionDeniedError("You must be a member of the group to view this assignment's history.")

    logger.info(f"User {current_user.email} getting history for assignment {assignment_id}")
    return await crud_history.get_assignment_history(db=db, assignment_id=assignment_id)

# === TIME ENTRY ENDPOINTS ===

@router.get(
    "/assignments/{assignment_id}/time-entries",
    response_model=PyList[TimeEntryPublic],
    summary="Get Time Entries",
    tags=["Time Tracking"]
)
async def get_time_entries_for_assignment(
    assignment_id: int,
    db: AsyncSession = Depends(get_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Retrieves all time entries for a specific chore assignment."""
    assignment = await crud_chore.get_chore_assignment_by_id(db, assignment_id)
    if not assignment:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Assignment not found")
    
    chore = await crud_chore.get_chore_by_id(db, assignment.chore_id)
    if not chore:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Chore not found")

    # Permission check
    if chore.type == ChoreTypeEnum.personal and chore.created_by_id != current_user.id:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Permission denied")
    
    if chore.type == ChoreTypeEnum.group:
        is_member = await crud_chore.is_user_member(db, chore.group_id, current_user.id)
        if not is_member:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Permission denied")

    # For now, return time entries for the current user only
    time_entries = await db.execute(
        select(TimeEntry)
        .where(TimeEntry.chore_assignment_id == assignment_id)
        .where(TimeEntry.user_id == current_user.id)
        .order_by(TimeEntry.start_time.desc())
    )
    return time_entries.scalars().all()

@router.post(
    "/assignments/{assignment_id}/time-entries",
    response_model=TimeEntryPublic,
    status_code=status.HTTP_201_CREATED,
    summary="Start Time Entry",
    tags=["Time Tracking"]
)
async def start_time_entry(
    assignment_id: int,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Starts a new time entry for a chore assignment."""
    assignment = await crud_chore.get_chore_assignment_by_id(db, assignment_id)
    if not assignment:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Assignment not found")
    
    chore = await crud_chore.get_chore_by_id(db, assignment.chore_id)
    if not chore:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Chore not found")

    # Permission check - only assigned user can track time
    if assignment.assigned_to_user_id != current_user.id:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Only assigned user can track time")

    # Check if there's already an active time entry
    existing_active = await db.execute(
        select(TimeEntry)
        .where(TimeEntry.chore_assignment_id == assignment_id)
        .where(TimeEntry.user_id == current_user.id)
        .where(TimeEntry.end_time.is_(None))
    )
    if existing_active.scalar_one_or_none():
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Time entry already active")

    # Create new time entry
    time_entry = TimeEntry(
        chore_assignment_id=assignment_id,
        user_id=current_user.id,
        start_time=datetime.now(timezone.utc)
    )
    db.add(time_entry)
    await db.commit()
    await db.refresh(time_entry)
    
    return time_entry

@router.put(
    "/time-entries/{time_entry_id}",
    response_model=TimeEntryPublic,
    summary="Stop Time Entry",
    tags=["Time Tracking"]
)
async def stop_time_entry(
    time_entry_id: int,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Stops an active time entry."""
    time_entry = await db.get(TimeEntry, time_entry_id)
    if not time_entry:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Time entry not found")
    
    if time_entry.user_id != current_user.id:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Permission denied")
    
    if time_entry.end_time:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Time entry already stopped")

    # Stop the time entry
    end_time = datetime.now(timezone.utc)
    time_entry.end_time = end_time
    time_entry.duration_seconds = int((end_time - time_entry.start_time).total_seconds())
    
    await db.commit()
    await db.refresh(time_entry)
    
    return time_entry

@router.post(
    "",
    response_model=ChorePublic,
    status_code=status.HTTP_201_CREATED,
    summary="Create Chore (Any Type)",
    tags=["Chores"],
)
async def create_chore_any_type(
    chore_in: ChoreCreate,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Create either a personal or group chore using a single endpoint."""
    logger.info(f"User {current_user.email} creating chore (type={chore_in.type}) name={chore_in.name}")

    # Basic permission & validation
    if chore_in.type == ChoreTypeEnum.personal:
        if chore_in.group_id is not None:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="group_id must be null for personal chores")
    elif chore_in.type == ChoreTypeEnum.group:
        if chore_in.group_id is None:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="group_id is required for group chores")
        # ensure membership
        try:
            await crud_group.check_group_membership(db, group_id=chore_in.group_id, user_id=current_user.id, action="create chores for")
        except (GroupMembershipError, GroupNotFoundError) as e:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(e))
    else:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid chore type")

    try:
        created = await crud_chore.create_chore(db=db, chore_in=chore_in, user_id=current_user.id)
        return created
    except Exception as e:
        logger.error(f"Error creating chore: {e}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))

@router.delete(
    "/{chore_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Delete Chore (Any Type)",
    tags=["Chores"],
)
async def delete_chore_any_type(
    chore_id: int,
    db: AsyncSession = Depends(get_transactional_session),
    current_user: UserModel = Depends(current_active_user),
):
    """Delete a personal or group chore based on permissions."""
    chore = await crud_chore.get_chore_by_id(db, chore_id)
    if not chore:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Chore not found")

    if chore.type == ChoreTypeEnum.personal:
        if chore.created_by_id != current_user.id:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="You can only delete your own personal chores")
        allowed = True
        target_group_id = None
    else:
        target_group_id = chore.group_id
        try:
            await crud_group.check_user_role_in_group(db, group_id=target_group_id, user_id=current_user.id, required_role=UserRoleEnum.owner, action="delete chore in group")
            allowed = True
        except GroupPermissionError:
            # fallback: creator may delete their own group chore
            allowed = (chore.created_by_id == current_user.id)
        except (GroupMembershipError, GroupNotFoundError):
            allowed = False

    if not allowed:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Not authorized to delete this chore")

    try:
        success = await crud_chore.delete_chore(db=db, chore_id=chore_id, user_id=current_user.id, group_id=target_group_id)
        if not success:
            raise ChoreNotFoundError(chore_id=chore_id)
    except ChoreNotFoundError:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Chore not found")
    except PermissionDeniedError as e:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=e.detail)
    except Exception as e:
        logger.error(f"Error deleting chore {chore_id}: {e}", exc_info=True)
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response(status_code=status.HTTP_204_NO_CONTENT) 