use ratatui::prelude::*;
use std::env;

/// Render mode: Local (full borders) vs Browser (no outer borders)
#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(dead_code)]
pub enum RenderMode {
    Local,   // Full borders, rich UI
    Browser, // No outer borders, larger margins
}

impl RenderMode {
    pub fn detect() -> Self {
        // Allow explicit override
        if let Ok(mode) = env::var("TUI_RENDER_MODE") {
            match mode.to_lowercase().as_str() {
                "local" => return RenderMode::Local,
                "browser" | "web" => return RenderMode::Browser,
                _ => {}
            }
        }

        // Auto-detect
        if is_cloudshell_mode() {
            RenderMode::Browser
        } else {
            RenderMode::Local
        }
    }
}

/// Safe viewport configuration from environment variables
#[derive(Debug, Clone)]
pub struct SafeViewportConfig {
    pub margin_x: u16,
    pub margin_y: u16,
    pub guard_right: u16,
    pub guard_bottom: u16,
}

impl Default for SafeViewportConfig {
    fn default() -> Self {
        let render_mode = RenderMode::detect();

        match render_mode {
            RenderMode::Browser => Self {
                margin_x: env::var("TUI_MARGIN_X")
                    .ok()
                    .and_then(|v| v.parse().ok())
                    .unwrap_or(2),
                margin_y: env::var("TUI_MARGIN_Y")
                    .ok()
                    .and_then(|v| v.parse().ok())
                    .unwrap_or(1),
                guard_right: env::var("TUI_GUARD_RIGHT")
                    .ok()
                    .and_then(|v| v.parse().ok())
                    .unwrap_or(6), // Was 4, increase to 6
                guard_bottom: env::var("TUI_GUARD_BOTTOM")
                    .ok()
                    .and_then(|v| v.parse().ok())
                    .unwrap_or(3), // Was 2, increase to 3
            },
            RenderMode::Local => Self {
                margin_x: env::var("TUI_MARGIN_X")
                    .ok()
                    .and_then(|v| v.parse().ok())
                    .unwrap_or(0), // Was 1, no margin needed locally
                margin_y: env::var("TUI_MARGIN_Y")
                    .ok()
                    .and_then(|v| v.parse().ok())
                    .unwrap_or(0),
                guard_right: env::var("TUI_GUARD_RIGHT")
                    .ok()
                    .and_then(|v| v.parse().ok())
                    .unwrap_or(1), // Minimal guard
                guard_bottom: env::var("TUI_GUARD_BOTTOM")
                    .ok()
                    .and_then(|v| v.parse().ok())
                    .unwrap_or(1),
            },
        }
    }
}

/// Detect if running in CloudShell/browser terminal
pub fn is_cloudshell_mode() -> bool {
    // AWS CloudShell
    env::var("AWS_EXECUTION_ENV").is_ok()
        || env::var("CLOUDSHELL").is_ok()
        // Google Cloud Shell
        || env::var("CLOUD_SHELL").is_ok()
        || env::var("DEVSHELL_PROJECT_ID").is_ok()
        // Azure Cloud Shell
        || env::var("ACC_CLOUD").is_ok()
        // Generic web terminal indicators
        || env::var("TUI_WEB").map(|v| v == "1").unwrap_or(false)
        || env::var("TERM_PROGRAM").map(|v| v.contains("xterm.js")).unwrap_or(false)
        // SSH through web console (likely browser-based)
        || (env::var("SSH_CONNECTION").is_ok() && env::var("DISPLAY").is_err())
}

/// Safe viewport calculation result
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct SafeViewport {
    pub canvas_cols: u16,
    pub canvas_rows: u16,
    pub safe_cols: u16,
    pub safe_rows: u16,
    pub safe_rect: Rect,
    pub config: SafeViewportConfig,
    pub render_mode: RenderMode,
}

impl SafeViewport {
    /// Calculate safe viewport from terminal size
    pub fn new(full_area: Rect) -> Self {
        let render_mode = RenderMode::detect();
        let config = SafeViewportConfig::default();

        let canvas_cols = full_area.width;
        let canvas_rows = full_area.height;

        // Calculate safe area with margins and guards
        // Hard rule: never draw on last column/row
        let left_margin = config.margin_x;
        let right_margin = config.margin_x + config.guard_right;
        let top_margin = config.margin_y;
        let bottom_margin = config.margin_y + config.guard_bottom;

        let safe_x = full_area.x + left_margin;
        let safe_y = full_area.y + top_margin;
        let safe_w = full_area
            .width
            .saturating_sub(left_margin + right_margin)
            .max(1);
        let safe_h = full_area
            .height
            .saturating_sub(top_margin + bottom_margin)
            .max(1);

        let safe_rect = Rect {
            x: safe_x,
            y: safe_y,
            width: safe_w,
            height: safe_h,
        };

        Self {
            canvas_cols,
            canvas_rows,
            safe_cols: safe_w,
            safe_rows: safe_h,
            safe_rect,
            config,
            render_mode,
        }
    }

    /// Check if terminal is too small for minimum requirements
    pub fn is_too_small(&self, required_cols: u16, required_rows: u16) -> bool {
        self.safe_cols < required_cols || self.safe_rows < required_rows
    }

    /// Validate a rectangle before rendering
    #[allow(dead_code)]
    pub fn validate_rect(&self, rect: Rect, min_w: u16, min_h: u16, name: &str) -> RectValidation {
        // Check minimum size
        if rect.width < min_w || rect.height < min_h {
            return RectValidation::Invalid {
                reason: format!(
                    "{}: size {}x{} below minimum {}x{}",
                    name, rect.width, rect.height, min_w, min_h
                ),
            };
        }

        // Check bounds: rect must fit within safe_rect (using ABSOLUTE coordinates)
        let max_x = rect.x + rect.width;
        let max_y = rect.y + rect.height;
        let safe_max_x = self.safe_rect.x + self.safe_rect.width; // FIXED: use absolute bound
        let safe_max_y = self.safe_rect.y + self.safe_rect.height; // FIXED: use absolute bound

        if max_x > safe_max_x {
            return RectValidation::Invalid {
                reason: format!(
                    "{}: right edge {} exceeds safe bound {}",
                    name, max_x, safe_max_x
                ),
            };
        }

        if max_y > safe_max_y {
            return RectValidation::Invalid {
                reason: format!(
                    "{}: bottom edge {} exceeds safe bound {}",
                    name, max_y, safe_max_y
                ),
            };
        }

        // Clamp to safe bounds
        let clamped = rect.intersection(self.safe_rect);

        if clamped.width == 0 || clamped.height == 0 {
            return RectValidation::Invalid {
                reason: format!("{}: clamped rect has zero size", name),
            };
        }

        RectValidation::Valid(clamped)
    }
}

#[derive(Debug, Clone)]
#[allow(dead_code)]
pub enum RectValidation {
    Valid(Rect),
    Invalid { reason: String },
}

impl RectValidation {
    #[allow(dead_code)]
    pub fn is_valid(&self) -> bool {
        matches!(self, RectValidation::Valid(_))
    }

    #[allow(dead_code)]
    pub fn unwrap_or_default(self) -> Rect {
        match self {
            RectValidation::Valid(rect) => rect,
            RectValidation::Invalid { .. } => Rect::default(),
        }
    }
}
