/*
 * 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.
 */

use futures_util::future::BoxFuture;
use std::sync::{
    Arc,
    atomic::{AtomicBool, Ordering},
};

use crate::CodeExecutor;
use maka_agent_facts::event::EventSink;
use maka_agent_facts::event::Invocation;
use maka_agent_facts::language::Language;
use maka_agent_facts::model::ModelToolCall;
use maka_agent_facts::tool_call::ToolCallIdentity;
use maka_agent_facts::tool_call::ToolRejection;
use maka_agent_facts::tools::ToolError;
use maka_agent_facts::tools::ToolJournal;
use serde_json::Value;
use tokio_util::sync::CancellationToken;

use crate::availability::{Availability, LoadedTools, SEARCH};
use crate::{
    PreparedEffect, ToolCallContext, ToolCatalog, ToolDefinition, ToolMode, ToolSemantics, cell,
};

/// Run-scoped authority. Cell capacity is shared across runs, not recreated here.
pub struct RunTools {
    language: Language,
    model: Option<maka_agent_facts::tools::ModelToolContext>,
    journal: ToolJournal,
    availability: Availability,
    mode: ToolMode,
    cells: CodeExecutor,
    code: cell::Cells,
}

impl Drop for RunTools {
    fn drop(&mut self) {
        self.code.cancel();
    }
}

impl RunTools {
    pub fn new(
        language: Language,
        sink: Arc<dyn EventSink>,
        invocation: Invocation,
        catalog: ToolCatalog,
        mode: ToolMode,
        cells: CodeExecutor,
        loaded: LoadedTools,
    ) -> Self {
        Self {
            language,
            model: None,
            journal: ToolJournal::new(sink, invocation),
            availability: Availability::new(catalog, loaded),
            mode,
            cells,
            code: cell::Cells::default(),
        }
    }

    pub fn with_store(mut self, store: maka_code_runtime::CellStore) -> Self {
        self.code = cell::Cells::new(store);
        self
    }

    pub async fn shutdown(&self) -> Result<(), ToolError> {
        self.code.shutdown().await
    }

    pub fn code_idle(&self) -> bool {
        self.code.is_idle()
    }
    pub async fn finish_output(&self, observed: u64) -> Result<bool, ToolError> {
        self.code.finish_output(observed).await
    }

    pub fn with_model(mut self, model: maka_agent_facts::tools::ModelToolContext) -> Self {
        self.set_model(model);
        self
    }

    pub fn with_behavior(mut self, behavior: maka_agent_facts::execution::BehaviorId) -> Self {
        self.availability.set_behavior(behavior);
        self
    }

    pub fn set_model(&mut self, model: maka_agent_facts::tools::ModelToolContext) {
        self.model = Some(model);
    }

    pub fn checkpoint(&self) -> maka_agent_facts::handoff::HandoffTools {
        self.availability.checkpoint()
    }

    pub fn restore(
        &self,
        checkpoint: &maka_agent_facts::handoff::HandoffTools,
    ) -> Result<(), ToolError> {
        self.availability.restore(checkpoint)
    }

    /// Capture once per logical model step, before sending any physical attempt.
    pub async fn capture(
        &self,
        cwd: &str,
        cancellation: CancellationToken,
    ) -> Result<RequestTools<'_>, ToolError> {
        self.code.check()?;
        let current = self
            .availability
            .capture(
                self.model.clone(),
                self.journal.invocation().clone(),
                cwd.into(),
                cancellation,
            )
            .await?;
        Ok(self.request(current))
    }

    /// Replay seals settled history and registered capabilities, not live state.
    /// Each model step captures live bindings after invocation admission.
    pub fn replay_definitions(&self) -> Vec<ToolDefinition> {
        self.request(self.availability.clone()).definitions()
    }

    fn request(&self, current: Availability) -> RequestTools<'_> {
        let digest = current.digest();
        let direct = if self.mode == ToolMode::CodeMode {
            current.direct_only()
        } else {
            ToolCatalog::default()
        };
        let availability = if self.mode == ToolMode::CodeMode {
            current.nested()
        } else {
            current
        };
        let described = availability.snapshot();
        RequestTools {
            finished: Arc::new(AtomicBool::new(false)),
            digest,
            direct,
            run: self,
            catalog: if self.mode == ToolMode::CodeMode {
                availability.all()
            } else {
                described.clone()
            },
            described,
            availability,
        }
    }
}

/// The advertised schemas and their handlers share one captured capability view.
/// Search settlement affects future captures, never this request or its retries.
#[derive(Clone)]
pub struct RequestTools<'a> {
    finished: Arc<AtomicBool>,
    digest: String,
    direct: ToolCatalog,
    run: &'a RunTools,
    catalog: ToolCatalog,
    /// Frozen description selection, separate from Code Mode callability.
    described: ToolCatalog,
    availability: Availability,
}

impl<'a> RequestTools<'a> {
    pub fn finished(&self) -> bool {
        self.finished.load(Ordering::Acquire)
    }

    pub fn catalog_digest(&self) -> &str {
        &self.digest
    }

    pub fn definitions(&self) -> Vec<ToolDefinition> {
        if self.run.mode == ToolMode::CodeMode {
            let mut exec = cell::definition(self.run.cells.language());
            let definitions: Vec<_> = self.described.definitions().cloned().collect();
            exec.description.push('\n');
            exec.description
                .push_str(&cell::declarations(&definitions, self.run.cells.language()));
            std::iter::once(exec)
                .chain(std::iter::once(cell::wait_definition()))
                .chain(self.direct.definitions().cloned())
                .collect()
        } else {
            let mut definitions: Vec<_> = self.catalog.definitions().cloned().collect();
            definitions.extend(self.availability.definition());
            definitions
        }
    }

    pub fn into_step(self, step_id: &str) -> StepTools<'a> {
        StepTools {
            finished: self.finished.clone(),
            request: self,
            step_id: step_id.to_owned(),
            admission: Admission::Fresh,
        }
    }
}

/// Call-order admission is separate from execution scheduling. Serial execution
/// alone does not make exclusive-step siblings legal.
pub struct StepTools<'a> {
    finished: Arc<AtomicBool>,
    request: RequestTools<'a>,
    step_id: String,
    admission: Admission,
}

#[derive(Default)]
enum Admission {
    #[default]
    Fresh,
    Parallel,
    Exclusive,
}

impl Admission {
    fn admit(&mut self, semantics: ToolSemantics) -> Result<(), ToolRejection> {
        *self = match (&self, semantics) {
            (Self::Fresh, ToolSemantics::ExclusiveStep | ToolSemantics::FinishTurn) => {
                Self::Exclusive
            }
            (Self::Fresh | Self::Parallel, ToolSemantics::Parallel) => Self::Parallel,
            _ => return Err(ToolRejection::ExclusiveConflict),
        };
        Ok(())
    }
}

impl<'a> StepTools<'a> {
    pub fn finished(&self) -> bool {
        self.finished.load(Ordering::Acquire)
    }

    pub async fn invoke(
        &mut self,
        call: &ModelToolCall,
        cancellation: CancellationToken,
    ) -> Result<Value, ToolError> {
        self.dispatch(call.clone(), cancellation).await
    }

    /// Admission happens in arrival order before any concurrent future runs.
    pub fn dispatch(
        &mut self,
        call: ModelToolCall,
        cancellation: CancellationToken,
    ) -> BoxFuture<'a, Result<Value, ToolError>> {
        let request = self.request.clone();
        let run = request.run;
        let operation_id = format!("{}:{}", self.step_id, call.id);
        let identity = ToolCallIdentity::provider(self.step_id.clone(), call.id.clone());
        let finished = self.finished.clone();
        let catalog = if run.mode == ToolMode::CodeMode {
            &request.direct
        } else {
            &request.catalog
        };
        let semantics =
            if run.mode == ToolMode::CodeMode && matches!(call.name.as_str(), "exec" | "wait") {
                Ok(ToolSemantics::ExclusiveStep)
            } else if run.mode == ToolMode::Direct
                && call.name == SEARCH
                && request.availability.enabled()
            {
                Ok(ToolSemantics::Parallel)
            } else {
                catalog.semantics(&call.name)
            };
        let admission = if cancellation.is_cancelled() {
            Err(ToolRejection::Cancelled)
        } else {
            semantics.and_then(|semantics| self.admission.admit(semantics))
        };
        Box::pin(async move {
            run.code.check()?;
            let catalog = if run.mode == ToolMode::CodeMode {
                &request.direct
            } else {
                &request.catalog
            };
            let preparation: Result<(PreparedEffect, Value), ToolRejection> = async {
                if cancellation.is_cancelled() {
                    return Err(ToolRejection::Cancelled);
                }
                admission?;
                let input = call
                    .input
                    .as_json()
                    .ok_or_else(|| ToolRejection::InvalidInput {
                        message: "arguments are not valid JSON".into(),
                    })?;
                let effect = if call.name == "exec" && run.mode == ToolMode::CodeMode {
                    let executor = cell::CellTool::new(
                        run.cells.clone(),
                        cell::source(input, run.cells.language())?,
                        request.catalog.clone(),
                        run.journal.clone(),
                        operation_id.clone(),
                        call.id.clone(),
                    );
                    let code = run.code.clone();
                    let language = run.language;
                    let effect: PreparedEffect = PreparedEffect::new(move |cancellation| {
                        Box::pin(async move { code.start(executor, language, cancellation).await })
                    });
                    Ok(effect.titled(maka_agent_facts::display::Text::localized(
                        "Run tools",
                        "执行工具",
                        "執行工具",
                    )))
                } else if call.name == "wait" && run.mode == ToolMode::CodeMode {
                    let input = cell::wait_input(input)?;
                    let code = run.code.clone();
                    let language = run.language;
                    Ok(PreparedEffect::new(move |cancellation| {
                        Box::pin(async move { code.observe(input, language, cancellation).await })
                    }))
                } else if run.mode == ToolMode::Direct
                    && call.name == SEARCH
                    && request.availability.enabled()
                {
                    request.availability.prepare_search(input)
                } else {
                    catalog
                        .prepare(
                            call.name.clone(),
                            input.clone(),
                            ToolCallContext {
                                invocation: run.journal.invocation().clone(),
                                operation_id: operation_id.clone(),
                            },
                            cancellation.clone(),
                        )
                        .await
                }?;
                Ok((effect, input.clone()))
            }
            .await;
            let (effect, input) = match preparation {
                Ok(effect) => effect,
                Err(reason) => {
                    return run
                        .journal
                        .reject(
                            operation_id,
                            identity,
                            call.name.clone(),
                            call.input.clone(),
                            reason,
                        )
                        .await;
                }
            };
            let result = run
                .journal
                .invoke_prepared_call(
                    operation_id,
                    identity,
                    call.name.clone(),
                    input,
                    cancellation,
                    effect,
                )
                .await?;
            if catalog.semantics(&call.name) == Ok(ToolSemantics::FinishTurn) {
                finished.store(true, Ordering::Release);
            }
            request.availability.settled(&call.name, &result)?;
            Ok(result)
        })
    }
}
