use eframe::egui;
use crate::ui::theme::Theme;

#[derive(Clone, Copy)]
pub enum Rank { Guest, Member, Leadership }

pub struct User {
    pub id: u64,
    pub name: String,
    pub rank: Rank,
    pub is_speaking: bool,
    pub is_muted: bool,
    pub pos: egui::Pos2,        // World X, Y (Floor coordinates)
    pub current_pos: egui::Pos2, // Interpolated pos
}

pub struct Sector {
    pub id: String,
    pub name: String,
    pub pos: egui::Pos2, // Center in World X, Y
}

pub struct TacticalCanvas {
    pub zoom: f32,
    pub offset: egui::Vec2, // Panning offset in world coordinates
    pub sectors: Vec<Sector>,
    pub users: Vec<User>,
    
    // 3D Camera Settings (Fixed Angle)
    camera_pitch: f32, // Fixed downward angle
    camera_dist: f32,  // Base distance (for perspective)
}

impl TacticalCanvas {
    pub fn new() -> Self {
        let mut sectors = Vec::new();
        // Create a basic tactical grid
        sectors.push(Sector { id: "lobby".into(), name: "LOBBY".into(), pos: egui::pos2(0.0, 0.0) });
        sectors.push(Sector { id: "ops1".into(),  name: "OPS-1".into(), pos: egui::pos2(200.0, 200.0) });
        sectors.push(Sector { id: "ops2".into(),  name: "OPS-2".into(), pos: egui::pos2(-200.0, 200.0) });
        sectors.push(Sector { id: "debrief".into(), name: "DEBRIEF".into(), pos: egui::pos2(0.0, 400.0) });

        let mut users = Vec::new();
        users.push(User {
            id: 1,
            name: "Samuel".into(),
            rank: Rank::Leadership,
            is_speaking: false,
            is_muted: false,
            pos: egui::pos2(0.0, 0.0),
            current_pos: egui::pos2(0.0, 0.0),
        });

        Self {
            zoom: 1.0,
            offset: egui::Vec2::ZERO,
            sectors,
            users,
            camera_pitch: 0.6, // ~35 degrees
            camera_dist: 1000.0,
        }
    }

    /// Projects 3D World coordinates (X, Y, Z) to 2D Screen coordinates
    fn project(&self, world_pos: egui::Pos2, z: f32, rect: egui::Rect) -> egui::Pos2 {
        // 1. Apply Panning (Offset)
        let rx = world_pos.x - self.offset.x;
        let ry = world_pos.y - self.offset.y;
        
        // 2. Simple Fixed-Angle Perspective Projection
        // We simulate a camera looking from above and behind.
        // Y in world is "depth", X is "horizontal", Z is "height".
        
        let cos_p = self.camera_pitch.cos();
        let sin_p = self.camera_pitch.sin();
        
        // Rotate around X axis for pitch
        let dy = ry * cos_p - z * sin_p;
        let dz = ry * sin_p + z * cos_p + self.camera_dist / self.zoom;
        
        // Project
        let scale = self.camera_dist / dz;
        let screen_x = rect.center().x + rx * scale;
        let screen_y = rect.center().y + dy * scale;
        
        egui::pos2(screen_x, screen_y)
    }

    pub fn show(&mut self, ui: &mut egui::Ui) {
        let (rect, response) = ui.allocate_at_least(ui.available_size(), egui::Sense::drag());

        // Handle Panning
        if response.dragged() {
            // Adjust offset based on drag (inverse of projection)
            self.offset -= response.drag_delta() / self.zoom;
        }

        // Handle Zooming
        let scroll_delta = ui.input(|i| i.smooth_scroll_delta.y);
        if scroll_delta != 0.0 {
            self.zoom = (self.zoom + scroll_delta * 0.001).clamp(0.2, 5.0);
        }

        let painter = ui.painter_at(rect);
        
        // ── 1. Draw Infinite Horizon Grid (Sub-Floor) ──
        self.draw_horizon_grid(&painter, rect);

        // ── 2. Draw Volumetric Sectors ──
        // Sort sectors by projected Y (depth) to handle occlusion
        let mut sorted_sectors: Vec<_> = self.sectors.iter().collect();
        sorted_sectors.sort_by(|a, b| b.pos.y.partial_cmp(&a.pos.y).unwrap());

        for sector in sorted_sectors {
            self.draw_volumetric_sector(&painter, sector, rect);
        }

        // ── 3. Draw Floating Users ──
        // Update positions first
        for user in &mut self.users {
            user.current_pos.x += (user.pos.x - user.current_pos.x) * 0.1;
            user.current_pos.y += (user.pos.y - user.current_pos.y) * 0.1;
        }

        // Then draw
        for i in 0..self.users.len() {
            let user = &self.users[i];
            self.draw_floating_unit(&painter, user, rect);
        }
    }

    fn draw_horizon_grid(&self, painter: &egui::Painter, rect: egui::Rect) {
        let grid_color = Theme::BORDER.linear_multiply(0.2);
        let step = 100.0;
        let range = 10;
        
        for i in -range..=range {
            let p1 = self.project(egui::pos2(i as f32 * step, -range as f32 * step), 0.0, rect);
            let p2 = self.project(egui::pos2(i as f32 * step, range as f32 * step), 0.0, rect);
            painter.line_segment([p1, p2], egui::Stroke::new(1.0, grid_color));
            
            let p3 = self.project(egui::pos2(-range as f32 * step, i as f32 * step), 0.0, rect);
            let p4 = self.project(egui::pos2(range as f32 * step, i as f32 * step), 0.0, rect);
            painter.line_segment([p3, p4], egui::Stroke::new(1.0, grid_color));
        }
    }

    fn draw_volumetric_sector(&self, painter: &egui::Painter, sector: &Sector, rect: egui::Rect) {
        let size = 80.0;
        let height = 60.0;
        
        // Define 4 corners of the base
        let corners_base = [
            egui::pos2(sector.pos.x - size, sector.pos.y - size),
            egui::pos2(sector.pos.x + size, sector.pos.y - size),
            egui::pos2(sector.pos.x + size, sector.pos.y + size),
            egui::pos2(sector.pos.x - size, sector.pos.y + size),
        ];
        
        let projected_base: Vec<_> = corners_base.iter().map(|&p| self.project(p, 0.0, rect)).collect();
        let projected_top: Vec<_> = corners_base.iter().map(|&p| self.project(p, height, rect)).collect();
        
        // 1. Draw Floor
        painter.add(egui::Shape::convex_polygon(
            projected_base.clone(),
            Theme::BASE.linear_multiply(0.3),
            egui::Stroke::new(1.0, Theme::BORDER),
        ));
        
        // 2. Draw Walls (Transparent Glass)
        let wall_color = Theme::COBALT_BLUE.linear_multiply(0.05);
        let wall_stroke = egui::Stroke::new(0.5, Theme::BORDER);
        
        for i in 0..4 {
            let next = (i + 1) % 4;
            painter.add(egui::Shape::convex_polygon(
                vec![projected_base[i], projected_base[next], projected_top[next], projected_top[i]],
                wall_color,
                wall_stroke,
            ));
        }
        
        // 3. Draw Ceiling Wireframe
        painter.add(egui::Shape::closed_line(
            projected_top,
            egui::Stroke::new(1.0, Theme::BORDER.linear_multiply(0.5)),
        ));

        // 4. Label (Floating above)
        let label_pos = self.project(sector.pos, height + 10.0, rect);
        painter.text(
            label_pos,
            egui::Align2::CENTER_BOTTOM,
            &sector.name,
            egui::FontId::proportional(12.0),
            Theme::TEXT_SECONDARY,
        );
    }

    fn draw_floating_unit(&self, painter: &egui::Painter, user: &User, rect: egui::Rect) {
        let float_height = 30.0;
        let screen_pos = self.project(user.current_pos, float_height, rect);
        let shadow_pos = self.project(user.current_pos, 0.0, rect);
        
        // 1. Tether Line
        painter.line_segment(
            [shadow_pos, screen_pos],
            egui::Stroke::new(1.0, Theme::BORDER.linear_multiply(0.3)),
        );
        
        // 2. Drop Shadow
        painter.circle_filled(shadow_pos, 8.0 * self.zoom, egui::Color32::from_black_alpha(100));
        
        // 3. Floating Node
        let node_color = if user.is_speaking { Theme::SIGNAL_GREEN } else { Theme::COBALT_BLUE };
        
        // Rank-based shape
        match user.rank {
            Rank::Leadership => {
                self.draw_hexagon(painter, screen_pos, 15.0 * self.zoom, node_color);
            }
            _ => {
                painter.circle_filled(screen_pos, 12.0 * self.zoom, node_color);
            }
        }
        
        // 4. Name Tag
        painter.text(
            screen_pos + egui::vec2(0.0, -20.0 * self.zoom),
            egui::Align2::CENTER_BOTTOM,
            &user.name,
            egui::FontId::proportional(14.0),
            Theme::TEXT_PRIMARY,
        );
        
        // 5. Speaking Pulse
        if user.is_speaking {
            let t = (std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis() % 1000) as f32 / 1000.0;
            painter.circle_stroke(
                screen_pos,
                (15.0 + t * 20.0) * self.zoom,
                egui::Stroke::new(2.0 * (1.0 - t), Theme::SIGNAL_GREEN),
            );
        }
    }

    fn draw_hexagon(&self, painter: &egui::Painter, center: egui::Pos2, radius: f32, color: egui::Color32) {
        let mut points = Vec::new();
        for i in 0..6 {
            let angle = (i as f32 * 60.0).to_radians();
            points.push(center + egui::vec2(angle.cos() * radius, angle.sin() * radius));
        }
        painter.add(egui::Shape::convex_polygon(points, color, egui::Stroke::new(1.0, Theme::TEXT_PRIMARY)));
    }
}
