//! Common types used across the tool system

use crate::tools::ExecSessionId;
use crate::utils::serde_helpers::{deserialize_maybe_quoted, deserialize_opt_maybe_quoted};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::time::Instant;

/// Enhanced cache entry with performance tracking
#[derive(Debug, Clone)]
pub struct EnhancedCacheEntry<T> {
    pub data: T,
    pub timestamp: Instant,
    pub access_count: usize,
    pub size_bytes: usize,
    pub last_accessed: Instant,
    pub priority: u8, // 0=low, 1=medium, 2=high priority
}

impl<T> EnhancedCacheEntry<T> {
    #[inline]
    pub fn new(data: T, size_bytes: usize) -> Self {
        let now = Instant::now();
        Self {
            data,
            timestamp: now,
            access_count: 1,
            size_bytes,
            last_accessed: now,
            priority: 1,
        }
    }

    #[inline]
    pub fn access(&mut self) {
        self.access_count += 1;
        self.last_accessed = Instant::now();
    }
}

/// Cache statistics
#[derive(Debug, Clone, Default)]
pub struct EnhancedCacheStats {
    pub hits: usize,
    pub misses: usize,
    pub entries: usize,
    pub total_size_bytes: usize,
    pub evictions: usize,
    pub memory_evictions: usize,
    pub expired_evictions: usize,
    pub total_memory_saved: usize,
}

/// Operation statistics for performance monitoring
#[derive(Debug, Clone, Default)]
pub struct OperationStats {
    pub total_calls: usize,
    pub total_duration_ms: u64,
    pub avg_duration_ms: f64,
    pub success_count: usize,
    pub error_count: usize,
    pub last_called: Option<Instant>,
}

/// Input structures for various tools
#[derive(Debug, Deserialize)]
pub struct Input {
    #[serde(
        alias = "file_path",
        alias = "filepath",
        alias = "target_path",
        alias = "file",
        alias = "p"
    )]
    pub path: String,
    #[serde(default, deserialize_with = "deserialize_opt_maybe_quoted")]
    pub max_bytes: Option<usize>,
    #[serde(default)]
    pub encoding: Option<String>,
    #[serde(default, deserialize_with = "deserialize_opt_maybe_quoted")]
    pub chunk_lines: Option<usize>,
    #[serde(default, deserialize_with = "deserialize_opt_maybe_quoted")]
    pub max_lines: Option<usize>,
    #[serde(default, deserialize_with = "deserialize_opt_maybe_quoted")]
    pub max_tokens: Option<usize>,
    #[serde(
        default,
        alias = "offset",
        alias = "byte_offset",
        deserialize_with = "deserialize_opt_maybe_quoted"
    )]
    pub offset_bytes: Option<u64>,
    #[serde(
        default,
        alias = "line_offset",
        deserialize_with = "deserialize_opt_maybe_quoted"
    )]
    pub offset_lines: Option<usize>,
    #[serde(
        default,
        alias = "page_size",
        alias = "byte_page_size",
        deserialize_with = "deserialize_opt_maybe_quoted"
    )]
    pub page_size_bytes: Option<usize>,
    #[serde(
        default,
        alias = "line_page_size",
        deserialize_with = "deserialize_opt_maybe_quoted"
    )]
    pub page_size_lines: Option<usize>,
}

#[derive(Debug, Deserialize)]
pub struct WriteInput {
    #[serde(
        alias = "file_path",
        alias = "filepath",
        alias = "target_path",
        alias = "file"
    )]
    pub path: String,
    #[serde(alias = "contents", alias = "text", alias = "data")]
    pub content: String,
    #[serde(default)]
    pub overwrite: bool,
    #[serde(default)]
    pub encoding: Option<String>,
    #[serde(default = "default_write_mode", alias = "write_mode")]
    pub mode: String,
}

#[derive(Debug, Deserialize)]
pub struct CreateInput {
    #[serde(
        alias = "file_path",
        alias = "filepath",
        alias = "target_path",
        alias = "file"
    )]
    pub path: String,
    #[serde(alias = "contents", alias = "text", alias = "data")]
    pub content: String,
    #[serde(default)]
    pub encoding: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct DeleteInput {
    #[serde(
        alias = "file_path",
        alias = "filepath",
        alias = "target_path",
        alias = "file"
    )]
    pub path: String,
    #[serde(default)]
    pub recursive: bool,
    #[serde(default)]
    pub force: bool,
}

#[derive(Debug, Deserialize)]
pub struct MoveInput {
    #[serde(
        alias = "file_path",
        alias = "filepath",
        alias = "target_path",
        alias = "file"
    )]
    pub path: String,
    pub destination: String,
    #[serde(default)]
    pub force: bool,
}

#[derive(Debug, Deserialize)]
pub struct CopyInput {
    #[serde(
        alias = "file_path",
        alias = "filepath",
        alias = "target_path",
        alias = "file"
    )]
    pub path: String,
    pub destination: String,
    #[serde(default)]
    pub recursive: bool,
}

#[derive(Debug, Deserialize)]
pub struct PathArgs {
    #[serde(
        alias = "file_path",
        alias = "filepath",
        alias = "target_path",
        alias = "file",
        alias = "p"
    )]
    pub path: String,
}

#[derive(Debug, Deserialize)]
pub struct EditInput {
    #[serde(
        alias = "file_path",
        alias = "filepath",
        alias = "target_path",
        alias = "file"
    )]
    pub path: String,
    #[serde(
        alias = "old_text",
        alias = "original",
        alias = "target",
        alias = "from"
    )]
    pub old_str: String,
    #[serde(alias = "new_text", alias = "replacement", alias = "to")]
    pub new_str: String,
    #[serde(default)]
    pub encoding: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ListInput {
    #[serde(default = "default_list_path")]
    pub path: String,
    #[serde(
        default = "default_max_items",
        deserialize_with = "deserialize_maybe_quoted"
    )]
    pub max_items: usize,
    /// Optional page number for pagination (1-based)
    #[serde(default, deserialize_with = "deserialize_opt_maybe_quoted")]
    pub page: Option<usize>,
    /// Optional page size for pagination
    #[serde(default, deserialize_with = "deserialize_opt_maybe_quoted")]
    pub per_page: Option<usize>,
    /// Controls verbosity of tool output: "concise" (default) or "detailed"
    #[serde(default)]
    pub response_format: Option<String>,
    #[serde(default)]
    pub include_hidden: bool,
    #[serde(default, alias = "pattern", alias = "query")]
    pub glob_pattern: Option<String>,
    // Enhanced file discovery parameters
    #[serde(default)]
    pub mode: Option<String>, // "list", "recursive", "find_name", "find_content", "largest"
    #[serde(default)]
    pub name_pattern: Option<String>, // For recursive and find_name modes
    #[serde(default)]
    pub content_pattern: Option<String>, // For find_content mode
    #[serde(default)]
    pub file_extensions: Option<Vec<String>>, // Filter by extensions
    #[serde(default)]
    pub case_sensitive: Option<bool>, // For pattern matching
}

#[derive(Debug, Deserialize, Serialize)]
pub struct EnhancedTerminalInput {
    pub command: Vec<String>,
    #[serde(default)]
    pub working_dir: Option<String>,
    #[serde(default, deserialize_with = "deserialize_opt_maybe_quoted")]
    pub timeout_secs: Option<u64>,
    #[serde(default)]
    pub mode: Option<String>, // "terminal", "pty"
    /// Controls verbosity of tool output: "concise" (default) or "detailed"
    #[serde(default)]
    pub response_format: Option<String>,
    #[serde(default)]
    pub raw_command: Option<String>,
    #[serde(default)]
    pub shell: Option<String>,
    #[serde(default)]
    pub login: Option<bool>,
    /// Explicit confirmation to run potentially destructive operations
    #[serde(default)]
    pub confirm: Option<bool>,
    /// Maximum number of tokens to return in the output
    #[serde(default, deserialize_with = "deserialize_opt_maybe_quoted")]
    pub max_tokens: Option<usize>,
}

/// PTY Session structure for managing interactive terminal sessions
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum VTCodeSessionLifecycleState {
    Running,
    Exited,
}

/// PTY Session structure for managing interactive terminal sessions
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VTCodePtySession {
    pub id: String,
    pub command: String,
    pub args: Vec<String>,
    pub working_dir: Option<String>,
    pub rows: u16,
    pub cols: u16,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub child_pid: Option<u32>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub started_at: Option<DateTime<Utc>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub lifecycle_state: Option<VTCodeSessionLifecycleState>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub exit_code: Option<i32>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub screen_contents: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub scrollback: Option<String>,
}

/// Backend-neutral exec session metadata used by `unified_exec`.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct VTCodeExecSession {
    pub id: ExecSessionId,
    pub backend: String,
    pub command: String,
    pub args: Vec<String>,
    pub working_dir: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub rows: Option<u16>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub cols: Option<u16>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub child_pid: Option<u32>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub started_at: Option<DateTime<Utc>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub lifecycle_state: Option<VTCodeSessionLifecycleState>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub exit_code: Option<i32>,
}

impl From<VTCodePtySession> for VTCodeExecSession {
    fn from(session: VTCodePtySession) -> Self {
        Self {
            id: session.id.into(),
            backend: "pty".to_string(),
            command: session.command,
            args: session.args,
            working_dir: session.working_dir,
            rows: Some(session.rows),
            cols: Some(session.cols),
            child_pid: session.child_pid,
            started_at: session.started_at,
            lifecycle_state: session.lifecycle_state,
            exit_code: session.exit_code,
        }
    }
}
// Default value functions
fn default_max_items() -> usize {
    20 // Better discovery defaults while still bounded for context efficiency
}

fn default_list_path() -> String {
    ".".into()
}
fn default_write_mode() -> String {
    "fail_if_exists".into()
}

// Search path default
pub fn default_search_path() -> String {
    ".".into()
}
