# #region TranslationPlanner [C:4] [TYPE Class] [SEMANTICS sqlalchemy, translate, orchestration, planning]
# @BRIEF Handle translation run planning: validation, config hashing, dictionary snapshot.
# @PRE Database session and config manager are available.
# @POST TranslationRun is planned with hashes and config snapshot; events recorded.
# @SIDE_EFFECT Creates TranslationRun; computes config and dict hashes; logs events.
# @RELATION DEPENDS_ON -> [TranslationRun]
# @RELATION DEPENDS_ON -> [TranslationJob]
# @RELATION DEPENDS_ON -> [TranslationEventLog]
# @RELATION DEPENDS_ON -> [TranslationPreviewSession]
# @RATIONALE Split from monolithic class: validation -> orchestrator_validation, hashing -> orchestrator_config.

from datetime import UTC, datetime
import hashlib
import json
import uuid

from sqlalchemy.orm import Session

from ...core.logger import belief_scope, logger
from ...models.translate import (
    TranslationJob,
    TranslationRun,
)
from .events import TranslationEventLog
from .orchestrator_config import compute_config_hash, compute_dict_snapshot_hash
from .orchestrator_validation import validate_job_preconditions


class TranslationPlanner:
    """Plan translation runs: validate preconditions, compute hashes, create run records."""

    def __init__(self, db: Session, event_log: TranslationEventLog, current_user: str | None = None):
        self.db = db
        self.event_log = event_log
        self.current_user = current_user

    # region plan_run [TYPE Function]
    # @PURPOSE: Validate, compute hashes, and create a new TranslationRun.
    # @PRE  job_id exists. For manual runs, an accepted preview session exists.
    # @POST  TranslationRun is created in PENDING status with hash fields and config snapshot.
    # @SIDE_EFFECT  DB writes; event recorded.
    def plan_run(
        self,
        job_id: str,
        is_scheduled: bool = False,
        trigger_type: str | None = None,
        full_translation: bool = False,
    ) -> TranslationRun:
        with belief_scope("TranslationPlanner.plan_run"):
            job = self.db.query(TranslationJob).filter(TranslationJob.id == job_id).first()
            if not job:
                raise ValueError(f"Translation job '{job_id}' not found")

            validate_job_preconditions(job, self.db, is_scheduled=is_scheduled)

            config_hash_value = compute_config_hash(job)
            dict_hash_value = compute_dict_snapshot_hash(self.db, job_id)

            config_snapshot = {
                "source_dialect": job.source_dialect,
                "target_dialect": job.target_dialect,
                "database_dialect": job.database_dialect,
                "source_datasource_id": job.source_datasource_id,
                "source_table": job.source_table,
                "target_schema": job.target_schema,
                "target_table": job.target_table,
                "source_key_cols": job.source_key_cols,
                "target_key_cols": job.target_key_cols,
                "translation_column": job.translation_column,
                "target_column": job.target_column,
                "context_columns": job.context_columns,
                "provider_id": job.provider_id,
                "batch_size": job.batch_size,
                "upsert_strategy": job.upsert_strategy,
                "dictionary_ids": dict_hash_value,
                "full_translation": full_translation,
            }

            key_hash_input = json.dumps({
                "source_key_cols": job.source_key_cols,
                "source_datasource_id": job.source_datasource_id,
                "source_table": job.source_table,
            }, sort_keys=True)
            key_hash = hashlib.sha256(key_hash_input.encode()).hexdigest()[:16]

            run = TranslationRun(
                id=str(uuid.uuid4()),
                job_id=job_id,
                status="PENDING",
                trigger_type=trigger_type or ("scheduled" if is_scheduled else "manual"),
                config_snapshot=config_snapshot,
                key_hash=key_hash,
                config_hash=config_hash_value,
                dict_snapshot_hash=dict_hash_value,
                created_by=self.current_user,
                created_at=datetime.now(UTC),
            )
            self.db.add(run)
            self.db.flush()

            self.event_log.log_event(
                job_id=job_id,
                run_id=run.id,
                event_type="RUN_STARTED",
                payload={
                    "is_scheduled": is_scheduled,
                    "trigger_type": run.trigger_type,
                    "config_hash": config_hash_value,
                    "dict_snapshot_hash": dict_hash_value,
                    "key_hash": key_hash,
                },
                created_by=self.current_user,
            )

            self.db.commit()
            self.db.refresh(run)

            logger.reflect("Run created", {
                "run_id": run.id,
                "job_id": job_id,
                "status": run.status,
                "trigger_type": run.trigger_type,
            })
            return run
    # endregion plan_run

# #endregion TranslationPlanner
