# #region InlineCorrectionService [C:4] [TYPE Class] [SEMANTICS translate, correction, inline, dictionary]
# @BRIEF Service for inline editing translated values and submitting corrections to dictionaries.
# @PRE Database session is available.
# @POST Inline edits applied with optional dictionary submission.
# @SIDE_EFFECT Modifies TranslationLanguage entries; optionally creates DictionaryEntry rows.
# @RELATION DEPENDS_ON -> [TranslationLanguage]
# @RELATION DEPENDS_ON -> [TranslationRecord]
# @RELATION DEPENDS_ON -> [DictionaryEntry]
# @RELATION DEPENDS_ON -> [_normalize_term]


from sqlalchemy.orm import Session

from ...core.logger import belief_scope, logger
from ...models.translate import DictionaryEntry, TranslationLanguage, TranslationRecord
from ._utils import _normalize_term


class InlineCorrectionService:
    """Handle inline correction of translated values with optional dictionary submission."""

    @staticmethod
    def apply_inline_edit(
        db: Session,
        run_id: str,
        record_id: str,
        language_code: str,
        final_value: str,
        submit_to_dictionary: bool = False,
        dictionary_id: str | None = None,
        current_user: str | None = None,
        context_data_override: dict | None = None,
        usage_notes: str | None = None,
        keep_context: bool = True,
    ) -> dict:
        """Apply an inline edit to a TranslationLanguage entry.

        Updates final_value and user_edit fields. Optionally submits to dictionary.
        Returns the updated TranslationLanguage data as a dict.

        Args:
            context_data_override: If provided, overrides auto-captured context data.
            usage_notes: Usage notes for the dictionary entry.
            keep_context: If False, clear context on the dictionary entry.
        """
        lang_entry = (
            db.query(TranslationLanguage)
            .filter(
                TranslationLanguage.record_id == record_id,
                TranslationLanguage.language_code == language_code,
            )
            .first()
        )
        if not lang_entry:
            raise ValueError(f"Language entry '{language_code}' not found for record '{record_id}'")

        record = (
            db.query(TranslationRecord)
            .filter(
                TranslationRecord.id == record_id,
                TranslationRecord.run_id == run_id,
            )
            .first()
        )
        if not record:
            raise ValueError(f"Translation record '{record_id}' not found in run '{run_id}'")

        lang_entry.final_value = final_value
        lang_entry.user_edit = final_value
        if lang_entry.status in ("pending", "translated"):
            lang_entry.status = "edited"
        db.flush()

        dict_result = None
        if submit_to_dictionary and dictionary_id:
            try:
                dict_result = InlineCorrectionService.submit_correction_to_dict(
                    db=db, record_id=record_id, language_code=language_code,
                    dictionary_id=dictionary_id, corrected_value=final_value,
                    current_user=current_user, context_data_override=context_data_override,
                    usage_notes=usage_notes, keep_context=keep_context,
                )
            except Exception as e:
                dict_result = {"error": str(e), "action": "failed"}

        db.commit()
        db.refresh(lang_entry)

        from ...schemas.translate import TranslationLanguageResponse
        response = TranslationLanguageResponse.model_validate(lang_entry)
        result = response.model_dump()
        if dict_result:
            result["dictionary_result"] = dict_result
        return result

    @staticmethod
    def submit_correction_to_dict(
        db: Session,
        record_id: str,
        language_code: str,
        dictionary_id: str,
        corrected_value: str,
        current_user: str | None = None,
        context_data_override: dict | None = None,
        usage_notes: str | None = None,
        keep_context: bool = True,
    ) -> dict:
        """Submit a correction from an inline edit to the dictionary.

        Fetches the TranslationLanguage entry, auto-captures source text and context,
        and creates/updates a DictionaryEntry.

        Args:
            context_data_override: If provided, overrides auto-captured context_data.
            usage_notes: Optional usage notes to store on the dictionary entry.
            keep_context: If False, sets has_context=False and clears context_data.
        """
        with belief_scope("InlineCorrectionService.submit_correction_to_dict"):
            lang_entry = (
                db.query(TranslationLanguage)
                .filter(
                    TranslationLanguage.record_id == record_id,
                    TranslationLanguage.language_code == language_code,
                )
                .first()
            )
            if not lang_entry:
                raise ValueError(f"Language entry '{language_code}' not found for record '{record_id}'")

            record = (
                db.query(TranslationRecord)
                .filter(TranslationRecord.id == record_id)
                .first()
            )
            if not record:
                raise ValueError(f"Translation record '{record_id}' not found")

            source_term = record.source_sql or record.source_object_name or ""
            if not source_term:
                raise ValueError("No source text available for this record")

            source_language = lang_entry.source_language_detected or "und"
            target_language = language_code

            context_data = {}
            if record.source_data:
                context_data["source_data"] = record.source_data
            if record.source_object_type:
                context_data["source_object_type"] = record.source_object_type
            if record.source_object_name:
                context_data["source_object_name"] = record.source_object_name
            if record.source_object_id:
                context_data["source_object_id"] = record.source_object_id

            if context_data_override is not None:
                context_data = context_data_override
                context_source = "manual"
            else:
                context_source = "auto"

            if not keep_context:
                context_data = None
                context_source = "manual"

            normalized = _normalize_term(source_term)

            existing = (
                db.query(DictionaryEntry)
                .filter(
                    DictionaryEntry.dictionary_id == dictionary_id,
                    DictionaryEntry.source_term_normalized == normalized,
                    DictionaryEntry.source_language == source_language,
                    DictionaryEntry.target_language == target_language,
                )
                .first()
            )

            result = {"action": "created", "entry_id": None, "conflict": None, "message": None}

            if existing:
                result["action"] = "conflict_detected"
                result["conflict"] = {
                    "source_term": source_term,
                    "existing_target_term": existing.target_term,
                    "submitted_target_term": corrected_value,
                    "action": "keep_existing",
                }
                result["message"] = (
                    f"Existing entry found: '{existing.target_term}' "
                    f"for source '{source_term}' ({source_language} → {target_language})"
                )
                logger.reason("Correction conflict detected", result)
                return result

            entry = DictionaryEntry(
                dictionary_id=dictionary_id,
                source_term=source_term.strip(),
                source_term_normalized=normalized,
                target_term=corrected_value.strip(),
                source_language=source_language,
                target_language=target_language,
                context_data=context_data if context_data else None,
                context_notes=None,
                has_context=bool(context_data) and keep_context,
                context_source=context_source,
                usage_notes=usage_notes,
                origin_source_language=source_language,
                origin_run_id=record.run_id,
                origin_row_key=record.id,
                origin_user_id=current_user,
            )
            db.add(entry)
            db.flush()
            result["entry_id"] = entry.id
            result["message"] = (
                f"Entry created for '{source_term}' ({source_language}) → "
                f"'{corrected_value}' ({target_language})"
            )
            logger.reflect("Dictionary entry created from correction", result)
            return result
# #endregion InlineCorrectionService
