/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

mod auto_context;
mod cleanup;
mod compact;
mod context_input;
mod continuation;
mod executor;
pub use executor::ExecutorInput;
mod handoff;
pub use handoff::{HandoffGate, HandoffReservation, HeldHandoff, PendingSeal};
mod history;
mod interactions;
mod model_attempt;
mod model_source;
pub use model_source::{ModelSource, PreparedModel};
pub mod pricing;
mod request_composition;
pub use history::project as project_model_history;
mod prune;
mod runner;
mod running;
mod steps;
pub use running::{RunningCompletion, RunningInvocation};

#[derive(Clone, Debug, thiserror::Error)]
#[error("invocation cleanup is unconfirmed")]
pub struct CleanupUnconfirmed;

use std::collections::HashSet;
use std::sync::{Arc, Mutex};

use maka_agent_facts::event::CommitError;
use maka_agent_facts::event::Invocation;
use maka_agent_facts::execution::InvocationConfiguration;
use maka_agent_facts::input::MessageInput;
use maka_agent_facts::tools::ToolError;
use maka_event_log::{EventLog, StoreError};
use maka_model::{ModelError, ModelExecutor, ProviderConfig};
use maka_tools::CodeExecutor;
use maka_tools::ToolCatalog;
use serde_json::Value;
use tokio_util::sync::CancellationToken;
use tokio_util::task::TaskTracker;

#[derive(Debug, thiserror::Error)]
pub enum RunError {
    #[error("session already has an active invocation")]
    Busy,
    /// Preflight became stale; no invocation was opened or source claimed.
    #[error("Session tool loading changed during continuation preparation; prepare again")]
    ContinuationChanged,
    #[error("session requires reconciliation before another invocation: {0}")]
    ReconciliationRequired(String),
    #[error("invalid execution input: {0}")]
    InvalidInput(String),
    #[error("execution cancelled")]
    Cancelled,
    #[error("model output was incomplete; local tools from this response were not executed")]
    ModelIncomplete,
    #[error(transparent)]
    Commit(#[from] CommitError),
    #[error(transparent)]
    Store(#[from] StoreError),
    #[error(transparent)]
    Model(#[from] ModelError),
    #[error(transparent)]
    Tool(ToolError),
    /// Physical ownership is uncertain; an enclosing native owner must retain
    /// its Root and capacity rather than infer cleanup from business completion.
    #[error("execution cleanup is unconfirmed")]
    CleanupUnconfirmed,
    #[error("execution worker failed: {0}")]
    Internal(String),
}

impl RunError {
    /// Explicit unconfirmed cleanup in this error. Absence is not proof of
    /// cleanup; only the original RunningCompletion carries that observation.
    pub fn is_cleanup_unconfirmed(&self) -> bool {
        matches!(
            self,
            Self::CleanupUnconfirmed
                | Self::Tool(
                    ToolError::CleanupUnconfirmed(_)
                        | ToolError::OperationCleanupUnconfirmed { .. }
                )
        )
    }
}

impl From<ToolError> for RunError {
    fn from(error: ToolError) -> Self {
        if matches!(
            error,
            ToolError::CleanupUnconfirmed(_) | ToolError::OperationCleanupUnconfirmed { .. }
        ) {
            cleanup::unconfirmed();
        }
        Self::Tool(error)
    }
}

#[derive(Clone)]
pub struct RunInput<W = RunWork> {
    /// Optional for standalone adapters; Host executions supply a public provider source.
    pub model_source: Option<Arc<dyn ModelSource>>,
    pub model_revision: Option<maka_agent_facts::composition::SourceRevision>,
    /// Public access-path identity; not the transport protocol or adapter name.
    pub provider_id: String,
    pub invocation: Invocation,
    pub context: Option<maka_agent_facts::context::ModelRequestContext>,
    pub work: W,
    /// Stable domain admission identity, when this invocation was client-issued.
    pub request_fingerprint: Option<String>,
    pub provider: ProviderConfig,
    pub provider_options: Value,
    /// Resolved SDK reply budget; summaries additionally cap their text at 8K.
    pub main_output_limit: Option<u64>,
    /// Current selected-model capability; image bytes are projected per request.
    pub supports_vision: bool,
    pub configuration: InvocationConfiguration,
}

// Admission owns the submitted body. Running execution owns only settings and
// identity; canonical opening facts supply the body to bounded history reads.
type RunContext = RunInput<()>;

impl RunInput {
    fn into_context(self) -> (RunContext, RunWork) {
        let Self {
            work,
            model_source,
            model_revision,
            provider_id,
            invocation,
            context,
            request_fingerprint,
            provider,
            provider_options,
            main_output_limit,
            supports_vision,
            configuration,
        } = self;
        (
            RunInput {
                work: (),
                model_source,
                model_revision,
                provider_id,
                invocation,
                context,
                request_fingerprint,
                provider,
                provider_options,
                main_output_limit,
                supports_vision,
                configuration,
            },
            work,
        )
    }
}

#[derive(Clone)]
pub enum RunWork {
    Handoff {
        source: maka_agent_facts::continuation::RunBoundary,
        pause: Box<maka_agent_facts::handoff::HandoffPause>,
        tools: ToolCatalog,
    },
    Continuation {
        source: maka_agent_facts::continuation::RunBoundary,
        tools: ToolCatalog,
    },
    Message {
        message: MessageInput,
        source_messages: Vec<maka_agent_facts::message::RootSourceMessage>,
        tools: ToolCatalog,
        /// Only a newly submitted client Turn may observe a sealed, unknown prior tool effect.
        allow_prior_unknown: bool,
    },
    ContextCompact,
}

struct Inner {
    pricing: Option<Arc<dyn pricing::Pricing>>,
    log: Arc<EventLog>,
    model: ModelExecutor,
    cells: CodeExecutor,
    sessions: Mutex<std::collections::HashMap<String, SessionState>>,
    active: Mutex<HashSet<String>>,
    workers: TaskTracker,
}

#[derive(Clone, Default)]
struct SessionState {
    code_store: maka_code_runtime::CellStore,
    loaded: maka_tools::availability::LoadedTools,
}

impl Inner {
    fn session_state(&self, session: &str) -> SessionState {
        self.sessions
            .lock()
            .unwrap()
            .entry(session.into())
            .or_default()
            .clone()
    }

    fn loaded_snapshot(&self, session: &str) -> std::collections::BTreeSet<String> {
        self.sessions
            .lock()
            .unwrap()
            .get(session)
            .map(|state| state.loaded.snapshot())
            .unwrap_or_default()
    }

    fn clear_loaded(&self, session: &str) {
        if let Some(state) = self.sessions.lock().unwrap().get(session) {
            state.loaded.clear();
        }
    }
}

/// Owns session admission and the entire invocation lifetime, including effects
/// still draining after the caller stops waiting.
#[derive(Clone)]
pub struct Engine(Arc<Inner>);

/// Engine-derived replay proof and its immutable input. Preparation uses registered
/// tools; model steps capture live bindings only after durable admission revalidates
/// the discovery basis. A changed basis requires fresh preparation.
pub struct PreparedContinuation {
    engine: std::sync::Weak<Inner>,
    input: RunInput,
    claim: continuation::PreparedClaim,
}
impl PreparedContinuation {
    pub fn invocation(&self) -> &Invocation {
        &self.input.invocation
    }
}

impl Engine {
    pub fn new(log: Arc<EventLog>, model: ModelExecutor, cells: CodeExecutor) -> Self {
        Self::create(log, model, cells, None)
    }

    pub fn with_pricing(
        log: Arc<EventLog>,
        model: ModelExecutor,
        cells: CodeExecutor,
        pricing: Arc<dyn pricing::Pricing>,
    ) -> Self {
        Self::create(log, model, cells, Some(pricing))
    }

    fn create(
        log: Arc<EventLog>,
        model: ModelExecutor,
        cells: CodeExecutor,
        pricing: Option<Arc<dyn pricing::Pricing>>,
    ) -> Self {
        Self(Arc::new(Inner {
            pricing,
            log,
            model,
            cells,
            sessions: Mutex::default(),
            active: Mutex::new(HashSet::new()),
            workers: TaskTracker::new(),
        }))
    }

    pub async fn run(
        &self,
        input: RunInput,
        cancellation: CancellationToken,
    ) -> Result<Invocation, RunError> {
        self.start(input, cancellation).await?.wait().await
    }

    /// Host calls after session retirement has fenced and drained its runs.
    pub fn release_session_state(&self, session: &str) {
        self.0.sessions.lock().unwrap().remove(session);
    }

    /// Observe replay safety without reserving a source or creating a claim.
    /// Admission validates the claim against current canonical facts.
    pub async fn check_continuation(
        &self,
        input: &RunInput,
        cancellation: &CancellationToken,
    ) -> Result<(), RunError> {
        let (RunWork::Continuation { source, tools, .. } | RunWork::Handoff { source, tools, .. }) =
            &input.work
        else {
            return Err(RunError::InvalidInput("not a continuation request".into()));
        };
        self.0
            .log
            .prepare_prune_candidates(&input.invocation.session_id, None, 0, 0, None)
            .await?;
        continuation::inspect(
            &self.0,
            input,
            source,
            tools,
            cancellation,
            &self.0.loaded_snapshot(&input.invocation.session_id),
        )
        .await
        .map(|_| ())
    }

    pub async fn prepare_continuation(
        &self,
        input: RunInput,
        cancellation: &CancellationToken,
    ) -> Result<PreparedContinuation, RunError> {
        let (RunWork::Continuation { source, tools, .. } | RunWork::Handoff { source, tools, .. }) =
            &input.work
        else {
            return Err(RunError::InvalidInput("not a continuation request".into()));
        };
        self.0
            .log
            .prepare_prune_candidates(&input.invocation.session_id, None, 0, 0, None)
            .await?;
        let claim = continuation::prepare(&self.0, &input, source, tools, cancellation).await?;
        Ok(PreparedContinuation {
            engine: Arc::downgrade(&self.0),
            input,
            claim,
        })
    }

    pub async fn start_continuation(
        &self,
        prepared: PreparedContinuation,
        cancellation: CancellationToken,
    ) -> Result<RunningInvocation, RunError> {
        if !std::sync::Weak::ptr_eq(&prepared.engine, &Arc::downgrade(&self.0)) {
            return Err(RunError::InvalidInput(
                "continuation belongs to another Engine".into(),
            ));
        }
        self.start_model(prepared.input, Some(prepared.claim), cancellation)
            .await
    }

    /// The owner first stops admissions and requests cancellation. This barrier
    /// also covers workers whose admission waiter was dropped before receiving
    /// a RunningInvocation handle.
    /// Caller must fence admission and request cancellation first. Tracking task
    /// termination alone does not confirm successful resource cleanup; retain
    /// and observe each original RunningCompletion separately.
    pub async fn drain(&self) {
        self.0.workers.close();
        self.0.workers.wait().await;
    }

    /// Returns only after durable admission. The returned owner covers execution
    /// and draining; dropping it requests cancellation without abandoning effects.
    pub async fn start(
        &self,
        input: RunInput,
        cancellation: CancellationToken,
    ) -> Result<RunningInvocation, RunError> {
        self.start_model(input, None, cancellation).await
    }

    async fn start_model(
        &self,
        input: RunInput,
        claim: Option<continuation::PreparedClaim>,
        cancellation: CancellationToken,
    ) -> Result<RunningInvocation, RunError> {
        if input.main_output_limit.is_some_and(|limit| limit == 0) {
            return Err(RunError::InvalidInput("invalid Main output limit".into()));
        }
        if let Some(context) = &input.context {
            context
                .validate()
                .map_err(|reason| RunError::InvalidInput(reason.into()))?;
        }
        match &input.work {
            RunWork::Handoff { source, pause, .. } => {
                pause
                    .validate(&source.invocation)
                    .map_err(|reason| RunError::InvalidInput(reason.into()))?;
                if input.invocation != pause.intent.successor(&source.invocation)
                    || input.request_fingerprint.is_some()
                    || input.context != pause.execution.context
                    || input.provider_options != pause.execution.provider_options
                    || input.main_output_limit != pause.execution.main_output_limit
                    || input.supports_vision != pause.execution.supports_vision
                    || model_attempt::route_identity(&input)?
                        != pause.execution.replay.route_identity
                {
                    return Err(RunError::InvalidInput(
                        "handoff execution settings changed".into(),
                    ));
                }
            }
            RunWork::Continuation { source, .. } => {
                if source.invocation.session_id != input.invocation.session_id
                    || input
                        .request_fingerprint
                        .as_ref()
                        .is_none_or(|s| !maka_agent_facts::archive::valid_projection_digest(s))
                {
                    return Err(RunError::InvalidInput(
                        "invalid continuation request".into(),
                    ));
                }
            }
            RunWork::ContextCompact
                if input
                    .request_fingerprint
                    .as_ref()
                    .is_none_or(|value| value.is_empty()) =>
            {
                return Err(RunError::InvalidInput(
                    "compaction requires request fingerprint".into(),
                ));
            }
            RunWork::Message {
                message,
                source_messages,
                ..
            } => {
                maka_agent_facts::message::validate_sources(message, source_messages)
                    .map_err(|reason| RunError::InvalidInput(reason.into()))?;
            }
            _ => {}
        }
        if !std::path::Path::new(&input.configuration.cwd).is_absolute()
            || input.configuration.cwd.contains('\0')
            || input
                .configuration
                .model
                .as_ref()
                .is_some_and(|binding| binding.model != input.provider.model)
        {
            return Err(RunError::InvalidInput(
                "invalid invocation configuration".into(),
            ));
        }
        let handoff = (!matches!(input.work, RunWork::ContextCompact)).then(|| {
            let root = match &input.work {
                RunWork::Handoff { pause, .. } => &pause.intent.root_run_id,
                _ => &input.invocation.run_id,
            };
            HandoffGate::new(input.invocation.clone(), root.clone())
        });
        let inner = self.0.clone();
        let invocation = input.invocation.clone();
        let tool_names = Arc::new(match &input.work {
            RunWork::Message { tools, .. }
            | RunWork::Continuation { tools, .. }
            | RunWork::Handoff { tools, .. } => tools.names().into_iter().collect(),
            RunWork::ContextCompact => Default::default(),
        });
        let worker_handoff = handoff.clone();
        self.start_owned(
            invocation,
            tool_names,
            handoff,
            cancellation,
            move |cancellation, admitted| {
                runner::run(inner, input, cancellation, admitted, worker_handoff, claim)
            },
        )
        .await
    }

    async fn start_owned<F, Fut>(
        &self,
        invocation: Invocation,
        tool_names: Arc<HashSet<String>>,
        handoff: Option<HandoffGate>,
        cancellation: CancellationToken,
        run: F,
    ) -> Result<RunningInvocation, RunError>
    where
        F: FnOnce(CancellationToken, tokio::sync::oneshot::Sender<()>) -> Fut + Send + 'static,
        Fut: std::future::Future<Output = Result<Invocation, RunError>> + Send + 'static,
    {
        let session_id = invocation.session_id.clone();
        if !self
            .0
            .active
            .lock()
            .map_err(|_| RunError::Internal("admission poisoned".into()))?
            .insert(session_id.clone())
        {
            return Err(RunError::Busy);
        }
        let admission = Admission {
            inner: self.0.clone(),
            session_id,
            handoff: handoff.clone(),
        };
        let cancellation = cancellation.child_token();
        let cancel_on_drop = cancellation.clone().drop_guard();
        let worker_cancellation = cancellation.clone();
        let (admitted, ready) = tokio::sync::oneshot::channel();
        let cleanup = cleanup::Evidence::default();
        let worker = self.0.workers.spawn(async move {
            let _admission = admission;
            let result = cleanup.scope(run(worker_cancellation, admitted)).await;
            let physical = if cleanup.confirmed()
                && !result.as_ref().is_err_and(RunError::is_cleanup_unconfirmed)
            {
                Ok(())
            } else {
                Err(CleanupUnconfirmed)
            };
            RunningCompletion {
                result,
                cleanup: physical,
            }
        });
        if ready.await.is_err() {
            return match worker.await {
                Ok(completion) if completion.cleanup.is_err() => Err(RunError::CleanupUnconfirmed),
                Ok(completion) => match completion.result {
                    Err(error) => Err(error),
                    Ok(_) => Err(RunError::Internal(
                        "worker omitted durable admission".into(),
                    )),
                },
                Err(_) => Err(RunError::CleanupUnconfirmed),
            };
        }
        cancel_on_drop.disarm();
        Ok(RunningInvocation::new(
            invocation,
            tool_names,
            cancellation,
            handoff,
            worker,
        ))
    }
}

struct Admission {
    inner: Arc<Inner>,
    session_id: String,
    handoff: Option<HandoffGate>,
}

impl Drop for Admission {
    fn drop(&mut self) {
        if let Some(handoff) = &self.handoff {
            handoff.close();
        }
        self.inner.active.lock().unwrap().remove(&self.session_id);
    }
}
