use chrono::NaiveDate;
use core::fmt;
use egui::ScrollArea;
use serde::{Deserialize, Serialize};

use crate::{
    PROJECT_FOLDER, RightPanelContent,
    editors::object_editor::ObjectInstance,
    util::{self, Error},
};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum FieldType {
    Image,
    SingleLine,
    MultiLine,
    Date,
    Number,
    Link { template_id: Option<String> },
    Links,
}

impl Default for FieldType {
    fn default() -> Self {
        Self::SingleLine
    }
}

impl FieldType {
    fn types() -> Vec<FieldType> {
        vec![
            FieldType::Image,
            FieldType::SingleLine,
            FieldType::MultiLine,
            FieldType::Date,
            FieldType::Number,
            FieldType::Link { template_id: None },
            FieldType::Links,
        ]
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FieldValue {
    Image(String),
    SingleLine(String),
    MultiLine(String),
    Date(NaiveDate),
    Number(f64),
    Link(String),
    Links(Vec<String>),
}

impl FieldValue {
    pub fn from_type(_type: &FieldType) -> Self {
        match _type {
            FieldType::Image => Self::Image(String::new()),
            FieldType::SingleLine => Self::SingleLine(String::new()),
            FieldType::MultiLine => Self::MultiLine(String::new()),
            FieldType::Date => Self::Date(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()),
            FieldType::Number => Self::Number(0.0),
            FieldType::Link { template_id: None } => Self::Link(String::new()),
            FieldType::Link {
                template_id: Some(template_id),
            } => Self::Link(template_id.clone()),
            FieldType::Links => Self::Links(Vec::new()),
        }
    }
}

impl Default for FieldValue {
    fn default() -> Self {
        Self::SingleLine(String::new())
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldDefinition {
    pub name: String,
    pub field_type: FieldType,
    pub required: bool,

    #[serde(default)]
    pub on_preview: bool,
    pub description: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct Template {
    pub name: String,
    pub id: String,

    pub description: Option<String>,
    pub fields: Vec<FieldDefinition>,

    #[serde(skip)]
    pub saved: bool,

    #[serde(skip)]
    pub error: Option<Error>,

    #[serde(skip)]
    pub new_field_name: String,

    #[serde(skip)]
    pub new_field_type: FieldType,

    #[serde(skip)]
    pub new_field_required: bool,

    #[serde(skip)]
    pub new_field_description: String,

    #[serde(skip)]
    pub new_field_on_preview: bool,
}

impl fmt::Debug for Template {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Template")
            .field("name", &self.name)
            .field("id", &self.id)
            .field("description", &self.description)
            .field("fields", &self.fields)
            .field("saved", &self.saved)
            .field("new_field_name", &self.new_field_name)
            .field("new_field_type", &self.new_field_type)
            .field("new_field_required", &self.new_field_required)
            .field("new_field_description", &self.new_field_description)
            .finish()
    }
}

impl Clone for Template {
    fn clone(&self) -> Self {
        Self {
            name: self.name.clone(),
            id: self.id.clone(),
            description: self.description.clone(),
            fields: self.fields.clone(),
            saved: self.saved,
            error: None,

            new_field_name: "".to_string(),
            new_field_type: FieldType::default(),
            new_field_required: false,
            new_field_description: "".to_string(),
            new_field_on_preview: false,
        }
    }
}

impl Default for Template {
    fn default() -> Self {
        Self {
            name: "New Template".to_string(),
            id: uuid::Uuid::new_v4().to_string(),
            description: Some(String::from("Placeholder description")),
            fields: Vec::new(),
            saved: false,
            error: None,

            new_field_name: "".to_string(),
            new_field_type: FieldType::default(),
            new_field_required: false,
            new_field_description: "".to_string(),
            new_field_on_preview: false,
        }
    }
}

impl Template {
    pub fn load(id: &str) -> Result<Self, Box<dyn std::error::Error>> {
        let path = PROJECT_FOLDER.join("templates").join(format!("{id}.json"));

        let content = std::fs::read_to_string(&path)?;
        let mut template: Self = serde_json::from_str(&content)?;
        template.saved = true;
        Ok(template)
    }

    pub fn save(&mut self) -> Result<(), Box<dyn std::error::Error>> {
        let path = PROJECT_FOLDER
            .join("templates")
            .join(format!("{}.json", &self.id));

        let content = serde_json::to_string_pretty(self)?;
        std::fs::write(path, content)?;
        self.saved = true;
        Ok(())
    }

    pub fn ui(&mut self, ui: &mut egui::Ui, new_instance: &mut Option<RightPanelContent>) {
        if let Some(error) = &mut self.error {
            error.show(ui);
        }

        if ui.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl) {
            if let Err(e) = self.save() {
                eprintln!("Failed to save: {e}");
            }
        }

        ScrollArea::vertical().show(ui, |ui| {
            ui.vertical(|ui| {
                // ui.group(|ui| {
                //     ui.horizontal(|ui| {
                //         if self.saved {
                //             ui.label(RichText::new("✓ Saved").color(egui::Color32::GREEN));
                //         } else {
                //             ui.label(RichText::new("* Unsaved").color(egui::Color32::YELLOW));
                //         }
                //         ui.label(format!("id: {}", self.id));
                //     });
                // });
                util::saved_status(ui, self.saved, &self.id, &self.name);

                // Save/Cancel buttons
                ui.horizontal(|ui| {
                    if ui.button("Save").clicked() {
                        if let Err(e) = self.save() {
                            eprintln!("Failed to save: {e}");
                        }
                    }

                    if ui.button("Create Copy").clicked() {
                        let mut copy = self.clone();
                        copy.id = uuid::Uuid::new_v4().to_string();
                        copy.name = format!("{} (Copy)", self.name);
                        copy.save().unwrap();
                    }

                    if ui.button("Delete").clicked() {
                        std::fs::remove_file(
                            PROJECT_FOLDER
                                .join("templates")
                                .join(format!("{}.json", self.id)),
                        )
                        .unwrap();

                        *new_instance = Some(RightPanelContent::None);
                    }

                    if ui.button("Cancel").clicked() {
                        // load default state
                        *self = Self::load(&self.id).unwrap();
                    }

                    if ui.button("Use Template").clicked() {
                        if self.saved {
                            *new_instance = Some(RightPanelContent::Object(Box::new(
                                ObjectInstance::new(self),
                            )));
                        } else {
                            self.error = Some(Error::new(
                                "You must save the template before creating a new instance!"
                                    .to_string(),
                            ));
                        }
                    }
                });

                self.editor_ui(ui);
            });
        });
    }

    pub fn editor_ui(&mut self, ui: &mut egui::Ui) {
        egui::Grid::new("template_grid")
            .num_columns(2)
            .striped(true)
            .show(ui, |ui| {
                ui.label("Template Name:");
                if ui
                    .add(egui::TextEdit::singleline(&mut self.name).frame(false))
                    .changed()
                {
                    self.saved = false;
                }
                ui.end_row();

                ui.label("Description:");
                if ui
                    .add(
                        egui::TextEdit::multiline(self.description.get_or_insert_with(String::new))
                            .desired_rows(1)
                            .frame(false),
                    )
                    .changed()
                {
                    self.saved = false;
                }
                ui.end_row();
            });

        ui.separator();

        egui::CollapsingHeader::new("Name").show(ui, |ui: &mut egui::Ui| {
            egui::Grid::new("field_grid")
                .num_columns(2)
                .striped(true)
                .show(ui, |ui| {
                    ui.label("Name:");
                    ui.label("Name");
                    ui.end_row();

                    ui.label("Type:");
                    ui.label("SingleLine");
                    ui.end_row();

                    ui.label("Required");
                    ui.label("✓");
                    ui.end_row();

                    ui.label("Description:");
                    ui.label("Object name");
                    ui.end_row();
                });
        });

        // List of fields
        let mut to_remove = None;
        for (i, field) in self.fields.iter_mut().enumerate() {
            let id = ui.make_persistent_id(format!("field_{i}"));

            egui::collapsing_header::CollapsingState::load_with_default_open(ui.ctx(), id, true)
                .show_header(ui, |ui| {
                    if ui.button("❌").clicked() {
                        to_remove = Some(i);
                    }
                    ui.strong(field.name.clone());
                })
                .body(|ui| {
                    ui.separator();
                    egui::Grid::new("field_grid")
                        .num_columns(2)
                        .striped(true)
                        .show(ui, |ui| {
                            ui.label("Name:");
                            if ui.text_edit_singleline(&mut field.name).changed() {
                                self.saved = false;
                            }
                            ui.end_row();

                            ui.label("Type:");
                            egui::ComboBox::from_id_salt(format!("field_type_{i}"))
                                .selected_text(format!("{:?}", field.field_type))
                                .show_ui(ui, |ui| {
                                    for variant in FieldType::types() {
                                        if ui
                                            .selectable_value(
                                                &mut field.field_type,
                                                variant.clone(),
                                                format!("{variant:?}"),
                                            )
                                            .changed()
                                        {
                                            self.saved = false;
                                        }
                                    }
                                });
                            ui.end_row();

                            ui.label("Required:");
                            if ui.checkbox(&mut field.required, "").clicked() {
                                self.saved = false;
                            }
                            ui.end_row();

                            ui.label("On Preview:");
                            if ui.checkbox(&mut field.on_preview, "").clicked() {
                                self.saved = false;
                            }
                            ui.end_row();

                            ui.label("Description:");
                            if ui
                                .text_edit_singleline(
                                    field.description.get_or_insert_with(String::new),
                                )
                                .changed()
                            {
                                self.saved = false;
                            }
                            ui.end_row();
                            ui.separator();
                        });
                });
        }

        // Remove field if needed
        if let Some(index) = to_remove {
            self.fields.remove(index);
            self.saved = false;
        }

        // Add new field
        ui.separator();
        ui.heading("Add New Field");

        ui.horizontal(|ui| {
            egui::Grid::new("field_grid")
                .num_columns(2)
                .striped(true)
                .show(ui, |ui| {
                    ui.label("Name:");
                    ui.text_edit_singleline(&mut self.new_field_name);
                    ui.end_row();

                    ui.label("Type:");
                    egui::ComboBox::from_id_salt("new_field_type")
                        .selected_text(format!("{:?}", self.new_field_type))
                        .show_ui(ui, |ui| {
                            for variant in FieldType::types() {
                                ui.selectable_value(
                                    &mut self.new_field_type,
                                    variant.clone(),
                                    format!("{variant:?}"),
                                );
                            }
                        });
                    ui.end_row();

                    ui.label("Required:");
                    ui.checkbox(&mut self.new_field_required, "");
                    ui.end_row();

                    ui.label("On Preview:");
                    ui.checkbox(&mut self.new_field_on_preview, "");
                    ui.end_row();

                    ui.label("Description:");
                    ui.text_edit_singleline(&mut self.new_field_description);
                    ui.end_row();

                    if ui.button("Add Field").clicked() && !self.new_field_name.is_empty() {
                        self.fields.push(FieldDefinition {
                            name: self.new_field_name.clone(),
                            field_type: self.new_field_type.clone(),
                            on_preview: self.new_field_on_preview,
                            required: self.new_field_required,
                            description: if self.new_field_description.is_empty() {
                                None
                            } else {
                                Some(self.new_field_description.clone())
                            },
                        });

                        self.saved = false;

                        // Reset new field form
                        self.new_field_name.clear();
                        self.new_field_required = false;
                        self.new_field_description.clear();
                    }
                });
        });
    }
}
