use std::path::PathBuf;

use iced::mouse;
/// Main application state and logic
use iced::{
    Element,
    Event,
    Subscription,
    Task,
};
use iced_code_editor::Message as EditorMessage;

use crate::{
    file_editor_state::FileEditorState,
    recent_projects::RecentProjects,
    ui,
};

/// Represents a tab in the editor
#[derive(Debug)]
pub enum Tab {
    Character(String),     // Character name
    File(FileEditorState), // File editor state
}

impl Tab {
    pub fn title(&self) -> String {
        match self {
            | Tab::Character(name) => name.clone(),
            | Tab::File(state) => state.filename(),
        }
    }
}

pub struct Editor {
    pub project_path: Option<PathBuf>,
    pub project: Option<storybook::Project>,
    pub error_message: Option<String>,
    pub tabs: Vec<Tab>,
    pub active_tab: Option<usize>,
    pub hovered_tab: Option<usize>,
    pub expanded_folders: std::collections::HashSet<String>, // Track which folders are expanded
    pub recent_projects: RecentProjects,
}

impl Default for Editor {
    fn default() -> Self {
        Self {
            project_path: None,
            project: None,
            error_message: None,
            tabs: Vec::new(),
            active_tab: None,
            hovered_tab: None,
            expanded_folders: std::collections::HashSet::new(),
            recent_projects: RecentProjects::load(),
        }
    }
}

#[derive(Debug, Clone)]
pub enum Message {
    // Menu actions
    OpenProjectDialog,
    ProjectSelected(Option<PathBuf>),
    ProjectLoaded(Result<storybook::Project, String>),
    CloseProject,
    SaveProject,
    Exit,
    // Entity selection
    SelectCharacter(String),
    // Quick actions
    ValidateProject,
    NewCharacter,
    // Tab management
    OpenCharacterTab(String),
    OpenFileTab(PathBuf),
    SwitchTab(usize),
    CloseTab(usize),
    TabHovered(Option<usize>),
    // File editing
    EditorAction(usize, EditorMessage),
    // File tree
    ToggleFolder(String),
    EventOccurred(Event),
}

impl Editor {
    pub fn new() -> (Self, Task<Message>) {
        (Self::default(), Task::none())
    }

    pub fn title(&self) -> String {
        "Storybook Editor".to_string()
    }

    pub fn theme(&self) -> iced::Theme {
        crate::theme::storybook_theme()
    }

    pub fn update(&mut self, message: Message) -> Task<Message> {
        match message {
            | Message::OpenProjectDialog => {
                // Open file picker dialog
                Task::perform(
                    async {
                        rfd::AsyncFileDialog::new()
                            .set_title("Select Storybook Project Directory")
                            .pick_folder()
                            .await
                            .map(|handle| handle.path().to_path_buf())
                    },
                    Message::ProjectSelected,
                )
            },
            | Message::ProjectSelected(Some(path)) => {
                self.project_path = Some(path.clone());
                self.error_message = None;

                // Load the project asynchronously
                Task::perform(
                    async move {
                        match storybook::Project::load(&path) {
                            | Ok(project) => Ok(project),
                            | Err(e) => Err(format!("Failed to load project: {}", e)),
                        }
                    },
                    Message::ProjectLoaded,
                )
            },
            | Message::ProjectSelected(None) => {
                // User cancelled the dialog
                Task::none()
            },
            | Message::ProjectLoaded(Ok(project)) => {
                self.project = Some(project);
                self.error_message = None;

                // Add to recent projects
                if let Some(ref path) = self.project_path {
                    self.recent_projects.add(path.clone());
                }

                Task::none()
            },
            | Message::ProjectLoaded(Err(error)) => {
                self.error_message = Some(error);
                self.project = None;
                Task::none()
            },
            | Message::CloseProject => {
                self.project_path = None;
                self.project = None;
                self.error_message = None;
                Task::none()
            },
            | Message::SaveProject => {
                // TODO: Implement save functionality
                Task::none()
            },
            | Message::Exit => iced::exit(),
            | Message::SelectCharacter(name) => {
                // Open character in a new tab (or switch to existing tab)
                Task::done(Message::OpenCharacterTab(name))
            },
            | Message::OpenCharacterTab(name) => {
                // Check if tab already exists
                if let Some(idx) = self
                    .tabs
                    .iter()
                    .position(|t| matches!(t, Tab::Character(n) if n == &name))
                {
                    self.active_tab = Some(idx);
                } else {
                    // For now, just create a character tab
                    // TODO: In the future, find the .sb file and open it as a File tab
                    self.tabs.push(Tab::Character(name));
                    self.active_tab = Some(self.tabs.len() - 1);
                }
                Task::none()
            },
            | Message::OpenFileTab(path) => {
                // Check if tab already exists
                if let Some(idx) = self
                    .tabs
                    .iter()
                    .position(|t| matches!(t, Tab::File(state) if state.path == path))
                {
                    self.active_tab = Some(idx);
                } else {
                    // Load file content
                    if let Ok(content) = std::fs::read_to_string(&path) {
                        let state = FileEditorState::new(path, content);
                        self.tabs.push(Tab::File(state));
                        self.active_tab = Some(self.tabs.len() - 1);
                    }
                }
                Task::none()
            },
            | Message::EditorAction(tab_idx, editor_msg) => {
                // Update the code editor
                if let Some(Tab::File(state)) = self.tabs.get_mut(tab_idx) {
                    return state
                        .editor
                        .update(&editor_msg)
                        .map(move |msg| Message::EditorAction(tab_idx, msg));
                }
                Task::none()
            },
            | Message::ToggleFolder(folder_path) => {
                // Toggle folder expanded/collapsed state
                if self.expanded_folders.contains(&folder_path) {
                    self.expanded_folders.remove(&folder_path);
                } else {
                    self.expanded_folders.insert(folder_path);
                }
                Task::none()
            },
            | Message::SwitchTab(idx) => {
                if idx < self.tabs.len() {
                    self.active_tab = Some(idx);
                }
                Task::none()
            },
            | Message::CloseTab(idx) => {
                if idx < self.tabs.len() {
                    self.tabs.remove(idx);
                    // Adjust active tab
                    if self.tabs.is_empty() {
                        self.active_tab = None;
                    } else if let Some(active) = self.active_tab {
                        if active >= self.tabs.len() {
                            self.active_tab = Some(self.tabs.len() - 1);
                        } else if active > idx {
                            self.active_tab = Some(active - 1);
                        }
                    }
                }
                Task::none()
            },
            | Message::ValidateProject => {
                // TODO: Run validation and show results
                // For now, just clear any error
                if self.project.is_some() {
                    self.error_message = Some("✓ Project validated successfully!".to_string());
                }
                Task::none()
            },
            | Message::NewCharacter => {
                // TODO: Open character creation dialog
                self.error_message = Some("New character creation coming soon!".to_string());
                Task::none()
            },
            | Message::TabHovered(idx) => {
                self.hovered_tab = idx;
                Task::none()
            },
            | Message::EventOccurred(event) => {
                // Handle middle-click to close tab
                if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Middle)) = event {
                    if let Some(idx) = self.hovered_tab {
                        return Task::done(Message::CloseTab(idx));
                    }
                }
                Task::none()
            },
        }
    }

    pub fn view(&self) -> Element<'_, Message> {
        ui::view(self)
    }

    pub fn subscription(&self) -> Subscription<Message> {
        iced::event::listen().map(Message::EventOccurred)
    }
}
