use egui::{RichText, vec2};

use crate::{
    PROJECT_FOLDER,
    editors::{
        object_editor::ObjectInstance,
        template_editor::{FieldType, FieldValue, Template},
    },
};

pub struct EditorScene {
    rect: egui::Rect,
}

impl EditorScene {
    pub fn new() -> Self {
        Self {
            rect: egui::Rect::ZERO,
        }
    }

    pub fn ui(&mut self, ctx: &egui::Context, objects: &mut [ObjectInstance]) {
        egui::CentralPanel::default()
            .frame(egui::Frame::NONE)
            .show(ctx, |ui| {
                egui::Scene::default()
                    .zoom_range(0.1..=10.0)
                    .show(ui, &mut self.rect, |ui| {
                        ui.horizontal_wrapped(|ui| {
                            ui.set_max_width(5000.0);
                            // Group objects by their template_id
                            use std::collections::HashMap;
                            let mut objects_by_template: HashMap<String, Vec<&ObjectInstance>> =
                                HashMap::new();

                            for obj in objects {
                                objects_by_template
                                    .entry(obj.template_id.clone())
                                    .or_default()
                                    .push(obj);
                            }

                            // For each template with objects, create cards
                            for (template_id, template_objects) in objects_by_template {
                                // Try to load the template to get field definitions
                                if let Ok(mut template) = Template::load(&template_id) {
                                    for obj in template_objects {
                                        // Create a card for each object
                                        egui::Frame::group(ui.style())
                                            .fill(egui::Color32::from_rgba_premultiplied(
                                                30, 30, 30, 200,
                                            ))
                                            .corner_radius(4.0)
                                            .show(ui, |ui| {

                                                ui.vertical(|ui| {
                                                    ui.set_max_width(512.0);
                                                    ui.set_min_width(512.0);

                                                    // Object name as header
                                                    ui.heading(RichText::new(&obj.name).strong());

                                                    // Show fields with on_preview = true
                                                    template.fields.sort_by_key(|field| field.field_type != FieldType::Image);
                                                    for field_def in &template.fields {
                                                        if field_def.on_preview {
                                                            if let Some(field_value) =
                                                                obj.fields.get(&field_def.name)
                                                            {
                                                                ui.separator();

                                                                match field_value {
                                                                    FieldValue::SingleLine(
                                                                        text,
                                                                    ) => {
                                                                        ui.strong(&field_def.name);
                                                                        ui.label(text);
                                                                    }
                                                                    FieldValue::MultiLine(
                                                                        text,
                                                                    ) => {
                                                                        ui.strong(&field_def.name);
                                                                        ui.label(text);
                                                                    }
                                                                    FieldValue::Number(n) => {
                                                                        ui.strong(&field_def.name);
                                                                        ui.label(n.to_string());
                                                                    }
                                                                    FieldValue::Date(date) => {
                                                                        ui.strong(&field_def.name);
                                                                        ui.label(
                                                                            date.format(
                                                                                "%Y-%m-%d",
                                                                            )
                                                                            .to_string(),
                                                                        );
                                                                    }
                                                                    FieldValue::Image(value) => {
                                                                        if !value.is_empty() {
                                                                            let path = PROJECT_FOLDER.join("assets").join(value);

                                                                            if let Ok(bytes) = std::fs::read(&path) {
                                                                                let image_source = egui::ImageSource::Bytes {
                                                                                    uri: std::borrow::Cow::Owned(path.to_str().unwrap().to_string()),
                                                                                    bytes: bytes.into(),
                                                                                };
                                                                                ui.add(
                                                                                    egui::Image::new(image_source).fit_to_exact_size(vec2(512.0, 512.0)),
                                                                                );
                                                                            }
                                                                        }
                                                                    }
                                                                    FieldValue::Link(
                                                                        target_id,
                                                                    ) => {
                                                                        ui.strong(&field_def.name);
                                                                        ui.label(format!(
                                                                            "→ {target_id}"
                                                                        ));
                                                                    }
                                                                    FieldValue::Links(
                                                                        links,
                                                                    ) => {
                                                                        ui.strong(&field_def.name);
                                                                        ui.label(format!(
                                                                            "{} links",
                                                                            links.len()
                                                                        ));
                                                                    }
                                                                }

                                                            }
                                                        }
                                                    }
                                                });
                                            });

                                        // Add some spacing between cards
                                        ui.add_space(8.0);
                                    }
                                }
                            }
                        });
                    });
            });
    }
}
