# #region TranslateDictionaryRoutesModule [C:3] [TYPE Module] [SEMANTICS fastapi, translate, api, search]
# @BRIEF Terminology Dictionary CRUD, entries management, and import routes.
# @LAYER API

from fastapi import Depends, HTTPException, Query, status
from sqlalchemy.orm import Session

from ....core.database import get_db
from ....core.logger import belief_scope, logger
from ....dependencies import get_current_user, has_permission
from ....plugins.translate.dictionary import DictionaryManager
from ....schemas.auth import User
from ....schemas.translate import (
    DictionaryCreate,
    DictionaryEntryCreate,
    DictionaryImport,
)
from ._helpers import _dict_to_response, _get_dictionary_entry_counts
from ._router import router

# ============================================================
# Terminology Dictionaries
# ============================================================

# #region list_dictionaries [C:4] [TYPE Function]
# @BRIEF List all terminology dictionaries.
# @PRE  User has translate.dictionary.view permission.
# @POST  Returns list of dictionaries with total count.
@router.get("/dictionaries")
async def list_dictionaries(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "VIEW")),
    db: Session = Depends(get_db),
):
    """List all terminology dictionaries."""
    with belief_scope("list_dictionaries"):
        logger.reason(f"User: {current_user.username}")
        dicts, total = DictionaryManager.list_dictionaries(db, page=page, page_size=page_size)
        dict_ids = [d.id for d in dicts]
        counts = _get_dictionary_entry_counts(db, dict_ids) if dict_ids else {}
        items = [_dict_to_response(d, counts.get(d.id, 0)) for d in dicts]
        logger.reflect("Dictionaries listed", {"total": total, "returned": len(items)})
        return {"items": items, "total": total, "page": page, "page_size": page_size}
# #endregion list_dictionaries


# #region get_dictionary [C:4] [TYPE Function]
# @BRIEF Get a single terminology dictionary by ID.
# @PRE  User has translate.dictionary.view permission.
# @POST  Returns the dictionary with entry_count.
@router.get("/dictionaries/{dictionary_id}")
async def get_dictionary(
    dictionary_id: str,
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "VIEW")),
    db: Session = Depends(get_db),
):
    """Get a terminology dictionary by ID."""
    with belief_scope("get_dictionary"):
        logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
        try:
            d = DictionaryManager.get_dictionary(db, dictionary_id)
            from ....models.translate import DictionaryEntry
            entry_count = db.query(DictionaryEntry.id).filter(DictionaryEntry.dictionary_id == dictionary_id).count()
            logger.reflect("Dictionary found", {"id": dictionary_id})
            return _dict_to_response(d, entry_count)
        except ValueError as e:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
# #endregion get_dictionary


# #region create_dictionary [C:4] [TYPE Function]
# @BRIEF Create a new terminology dictionary.
# @PRE  User has translate.dictionary.create permission.
# @POST  Returns the created dictionary.
@router.post("/dictionaries", status_code=status.HTTP_201_CREATED)
async def create_dictionary(
    payload: DictionaryCreate,
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "CREATE")),
    db: Session = Depends(get_db),
):
    """Create a new terminology dictionary."""
    with belief_scope("create_dictionary"):
        logger.reason(f"User: {current_user.username}")
        d = DictionaryManager.create_dictionary(
            db,
            name=payload.name,
            source_dialect=payload.source_dialect,
            target_dialect=payload.target_dialect,
            created_by=current_user.username,
            description=payload.description,
            is_active=payload.is_active,
        )
        logger.reflect("Dictionary created", {"id": d.id})
        return _dict_to_response(d, 0)
# #endregion create_dictionary


# #region update_dictionary [C:4] [TYPE Function]
# @BRIEF Update an existing terminology dictionary.
# @PRE  User has translate.dictionary.edit permission.
# @POST  Returns the updated dictionary.
@router.put("/dictionaries/{dictionary_id}")
async def update_dictionary(
    dictionary_id: str,
    payload: DictionaryCreate,
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "EDIT")),
    db: Session = Depends(get_db),
):
    """Update a terminology dictionary."""
    with belief_scope("update_dictionary"):
        logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
        try:
            d = DictionaryManager.update_dictionary(
                db,
                dict_id=dictionary_id,
                name=payload.name,
                description=payload.description,
                source_dialect=payload.source_dialect,
                target_dialect=payload.target_dialect,
                is_active=payload.is_active,
            )
            from ....models.translate import DictionaryEntry
            entry_count = db.query(DictionaryEntry.id).filter(DictionaryEntry.dictionary_id == dictionary_id).count()
            logger.reflect("Dictionary updated", {"id": dictionary_id})
            return _dict_to_response(d, entry_count)
        except ValueError as e:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
# #endregion update_dictionary


# #region delete_dictionary [C:4] [TYPE Function]
# @BRIEF Delete a terminology dictionary, blocked if attached to active/scheduled jobs.
# @PRE  User has translate.dictionary.delete permission.
# @POST  Dictionary is deleted.
@router.delete("/dictionaries/{dictionary_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_dictionary(
    dictionary_id: str,
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "DELETE")),
    db: Session = Depends(get_db),
):
    """Delete a terminology dictionary."""
    with belief_scope("delete_dictionary"):
        logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
        try:
            DictionaryManager.delete_dictionary(db, dictionary_id)
            logger.reflect("Dictionary deleted", {"id": dictionary_id})
            return None
        except ValueError as e:
            if "active/scheduled" in str(e):
                raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(e))
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
# #endregion delete_dictionary


# ============================================================
# Dictionary Entries CRUD
# ============================================================

# #region list_dictionary_entries [C:4] [TYPE Function]
# @BRIEF List entries for a dictionary, optionally filtered by language pair.
# @PRE  User has translate.dictionary.view permission.
# @POST  Returns paginated list of entries with language pair fields.
@router.get("/dictionaries/{dictionary_id}/entries")
async def list_dictionary_entries(
    dictionary_id: str,
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=500),
    source_language: str | None = Query(None, description="Filter by BCP-47 source language"),
    target_language: str | None = Query(None, description="Filter by BCP-47 target language"),
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "VIEW")),
    db: Session = Depends(get_db),
):
    """List entries for a dictionary."""
    with belief_scope("list_dictionary_entries"):
        logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
        try:
            entries, total = DictionaryManager.list_entries(db, dictionary_id, page=page, page_size=page_size)
            # Apply language pair filtering
            if source_language or target_language:
                filtered = []
                for e in entries:
                    if source_language and e.source_language != source_language and e.source_language != "und":
                        continue
                    if target_language and e.target_language != target_language:
                        continue
                    filtered.append(e)
                entries = filtered
                total = len(filtered)
            items = [
                {
                    "id": e.id,
                    "dictionary_id": e.dictionary_id,
                    "source_term": e.source_term,
                    "source_term_normalized": e.source_term_normalized,
                    "target_term": e.target_term,
                    "source_language": e.source_language,
                    "target_language": e.target_language,
                    "context_notes": e.context_notes,
                    "context_data": e.context_data,
                    "usage_notes": e.usage_notes,
                    "has_context": e.has_context,
                    "context_source": e.context_source,
                    "origin_source_language": e.origin_source_language,
                    "created_at": e.created_at,
                    "updated_at": e.updated_at,
                }
                for e in entries
            ]
            logger.reflect("Entries listed", {"dict_id": dictionary_id, "total": total, "source_language": source_language, "target_language": target_language})
            return {"items": items, "total": total, "page": page, "page_size": page_size}
        except ValueError as e:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
# #endregion list_dictionary_entries


# #region add_dictionary_entry [C:4] [TYPE Function]
# @BRIEF Add a new entry to a dictionary.
# @PRE  User has translate.dictionary.edit permission.
# @POST  Entry is created.
@router.post("/dictionaries/{dictionary_id}/entries", status_code=status.HTTP_201_CREATED)
async def add_dictionary_entry(
    dictionary_id: str,
    payload: DictionaryEntryCreate,
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "EDIT")),
    db: Session = Depends(get_db),
):
    """Add a new entry to a dictionary."""
    with belief_scope("add_dictionary_entry"):
        logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
        try:
            entry = DictionaryManager.add_entry(
                db, dictionary_id,
                source_term=payload.source_term,
                target_term=payload.target_term,
                context_notes=payload.context_notes,
                source_language=payload.source_language,
                target_language=payload.target_language,
            )
            logger.reflect("Entry added", {"entry_id": entry.id})
            return {
                "id": entry.id,
                "dictionary_id": entry.dictionary_id,
                "source_term": entry.source_term,
                "source_term_normalized": entry.source_term_normalized,
                "target_term": entry.target_term,
                "source_language": entry.source_language,
                "target_language": entry.target_language,
                "context_notes": entry.context_notes,
                "context_data": entry.context_data,
                "usage_notes": entry.usage_notes,
                "has_context": entry.has_context,
                "context_source": entry.context_source,
                "origin_source_language": entry.origin_source_language,
                "created_at": entry.created_at,
                "updated_at": entry.updated_at,
            }
        except ValueError as e:
            if "already exists" in str(e):
                raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(e))
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
# #endregion add_dictionary_entry


# #region edit_dictionary_entry [C:4] [TYPE Function]
# @BRIEF Update an existing dictionary entry.
# @PRE  User has translate.dictionary.edit permission.
# @POST  Entry is updated.
@router.put("/dictionaries/{dictionary_id}/entries/{entry_id}")
async def edit_dictionary_entry(
    dictionary_id: str,
    entry_id: str,
    payload: DictionaryEntryCreate,
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "EDIT")),
    db: Session = Depends(get_db),
):
    """Update an existing dictionary entry."""
    with belief_scope("edit_dictionary_entry"):
        logger.reason(f"Entry: {entry_id}, User: {current_user.username}")
        try:
            entry = DictionaryManager.edit_entry(
                db, entry_id,
                source_term=payload.source_term,
                target_term=payload.target_term,
                context_notes=payload.context_notes,
                source_language=payload.source_language,
                target_language=payload.target_language,
            )
            logger.reflect("Entry updated", {"entry_id": entry_id})
            return {
                "id": entry.id,
                "dictionary_id": entry.dictionary_id,
                "source_term": entry.source_term,
                "source_term_normalized": entry.source_term_normalized,
                "target_term": entry.target_term,
                "source_language": entry.source_language,
                "target_language": entry.target_language,
                "context_notes": entry.context_notes,
                "context_data": entry.context_data,
                "usage_notes": entry.usage_notes,
                "has_context": entry.has_context,
                "context_source": entry.context_source,
                "origin_source_language": entry.origin_source_language,
                "created_at": entry.created_at,
                "updated_at": entry.updated_at,
            }
        except ValueError as e:
            if "already exists" in str(e):
                raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(e))
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
# #endregion edit_dictionary_entry


# #region delete_dictionary_entry [C:4] [TYPE Function]
# @BRIEF Delete a dictionary entry.
# @PRE  User has translate.dictionary.edit permission.
# @POST  Entry is deleted.
@router.delete("/dictionaries/{dictionary_id}/entries/{entry_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_dictionary_entry(
    dictionary_id: str,
    entry_id: str,
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "EDIT")),
    db: Session = Depends(get_db),
):
    """Delete a dictionary entry."""
    with belief_scope("delete_dictionary_entry"):
        logger.reason(f"Entry: {entry_id}, User: {current_user.username}")
        try:
            DictionaryManager.delete_entry(db, entry_id)
            logger.reflect("Entry deleted", {"entry_id": entry_id})
            return None
        except ValueError as e:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
# #endregion delete_dictionary_entry


# #region import_dictionary_entries [C:4] [TYPE Function]
# @BRIEF Import entries into a terminology dictionary from CSV/TSV content.
# @PRE User has translate.dictionary.edit permission.
# @POST Entries are imported per conflict mode.
# @COMPLEXITY 4

@router.post("/dictionaries/{dictionary_id}/import")
async def import_dictionary_entries(
    dictionary_id: str,
    payload: DictionaryImport,
    current_user: User = Depends(get_current_user),
    _ = Depends(has_permission("translate.dictionary", "EDIT")),
    db: Session = Depends(get_db),
):
    """Import entries into a terminology dictionary from CSV/TSV content."""
    with belief_scope("import_dictionary_entries"):
        logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")

        if payload.on_conflict not in ("overwrite", "keep_existing", "cancel"):
            raise HTTPException(
                status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
                detail="on_conflict must be 'overwrite', 'keep_existing', or 'cancel'",
            )

        try:
            result = DictionaryManager.import_entries(
                db,
                dict_id=dictionary_id,
                content=payload.content,
                delimiter=payload.delimiter,
                on_conflict=payload.on_conflict,
                preview_only=payload.preview_only,
                default_source_language=payload.default_source_language,
                default_target_language=payload.default_target_language,
            )
            logger.reflect("Import completed", {
                "dict_id": dictionary_id,
                "total": result["total"],
                "errors": len(result["errors"]),
            })
            return result
        except ValueError as e:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
# #endregion import_dictionary_entries

# #endregion TranslateDictionaryRoutesModule
