// SPDX-License-Identifier: GPL-3.0-or-later
// File: ./src/gui/state.rs
// Manages the application state for the GUI (Iced).

rust_i18n::i18n!("../locales", fallback = "en");

use crate::client::RustyClient;
use crate::config::{AppTheme, Config, LogLevel};
use crate::context::AppContext;
use crate::gui::icon;
use crate::model::{Alarm, CalendarListEntry, Task as TodoTask};
use crate::store::TaskStore;
use crate::system::SystemEvent;
use iced::widget::text_editor;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use strum::IntoEnumIterator;
use tokio::sync::mpsc;

#[derive(PartialEq, Clone, Copy, Debug, Default)]
pub enum AppState {
    #[default]
    Loading,
    Onboarding,
    Active,
    Settings,
    Help(crate::help::HelpTab, u8),
}

#[derive(Default, PartialEq, Clone, Copy, Debug)]
pub enum SidebarMode {
    #[default]
    Calendars,
    Categories,
    Locations, // NEW
}

#[derive(PartialEq, Clone, Copy, Debug, Default)]
pub enum Focus {
    #[default]
    MainList,
    Sidebar,
    SearchInput,
    AddTaskInput,
}

#[derive(Debug, Clone, Copy)]
pub enum ResizeDirection {
    North,
    South,
    East,
    West,
    NorthEast,
    NorthWest,
    SouthEast,
    SouthWest,
}

pub struct GuiApp {
    pub core_config: Config,
    pub state: AppState,
    pub ctx: Arc<dyn AppContext>,
    pub store: TaskStore,
    pub controller: crate::controller::TaskController,
    pub session: crate::model::SessionState,
    pub tasks: Vec<crate::store::TaskListItem>,
    pub calendars: Vec<CalendarListEntry>,
    pub client: Option<RustyClient>,
    pub tag_aliases: HashMap<String, Vec<String>>,
    pub bg_tx: Option<tokio::sync::mpsc::Sender<crate::gui::async_ops::WorkerCommand>>,

    // Cached Sidebar Data (computed once, not in view())
    pub cached_categories: Vec<crate::store::AggregateItem>,
    pub cached_locations: Vec<crate::store::AggregateItem>,

    // --- Stable ID Cache ---
    // Maps Task UID -> Iced Widget ID. Ensures the View and Update loops use the exact same ID instance.
    pub task_ids: HashMap<String, iced::widget::Id>,

    // UI State
    pub sidebar_mode: SidebarMode,
    pub active_cal_href: Option<String>,
    pub hidden_calendars: HashSet<String>,
    pub disabled_calendars: HashSet<String>,
    pub yanked_uid: Option<String>,
    pub yank_lock_active: bool,

    pub hovered_tag_uid: Option<String>,

    // Track selected task for highlighting
    pub selected_uid: Option<String>,

    pub active_focus: Focus,
    pub sidebar_selection_idx: usize,

    // Preferences
    pub hide_completed: bool,
    pub strikethrough_completed: bool,
    pub hide_fully_completed_tags: bool,
    pub hide_aliases_in_sidebar: bool,
    pub sort_cutoff_months: Option<u32>,
    pub sort_standard_by_priority: bool,
    pub sort_preset: crate::config::SortPreset,
    pub current_theme: AppTheme,

    // Store the resolved random theme for this session
    pub resolved_random_theme: AppTheme,

    // Filter State
    pub filter_min_duration: Option<u32>,
    pub filter_max_duration: Option<u32>,
    pub filter_include_unset_duration: bool,

    pub quick_filter_term: String,
    pub quick_filter_icon: String,
    pub show_quick_filter: bool,
    pub sidebar_is_hidden: bool,
    pub ob_quick_filter_term_input: String,
    pub ob_quick_filter_icon_input: String,

    // Inputs - Main
    pub input_value: text_editor::Content,
    pub description_value: text_editor::Content,
    pub search_value: text_editor::Content,
    pub search_debounce_version: usize,
    pub editing_uid: Option<String>,
    pub creating_child_of: Option<String>,
    pub moving_task_uid: Option<String>,
    pub move_target_idx: usize,
    pub child_lock_active: bool,
    pub creating_with_desc: bool,
    pub new_task_title: String,
    pub expanded_tasks: HashSet<String>,
    pub help_expanded_sections: HashSet<String>,
    pub unsynced_changes: bool,
    pub unsynced_tooltip: String,
    pub last_sync_failed: bool,

    // Session UI state
    pub adding_session_uid: Option<String>,
    pub session_input: iced::widget::text_editor::Content,
    pub show_all_sessions: HashSet<String>,

    // Computed State (Persisted for view borrowing)
    pub current_placeholder: String,
    pub search_placeholder: String,
    pub notes_placeholder: String,

    // UI Visuals
    pub location_tab_icon: char,
    pub random_icon: char, // NEW

    // Inputs - Settings (Aliases)
    pub alias_input_key: String,
    pub alias_input_values: String,
    pub editing_alias_key: Option<String>,
    pub ob_trash_retention_input: String,
    pub trash_retention_days: u32,

    // System
    pub loading: bool,
    pub error_msg: Option<String>,

    // Onboarding / Config
    pub ob_url: String,
    pub ob_user: String,
    pub ob_pass: String,
    pub ob_password_visible: bool,
    pub ob_default_cal: Option<String>,
    pub ob_sort_months_input: String,
    pub ob_insecure: bool,
    /// If true, the config file exists but is invalid. We must block overwrites.
    pub config_was_corrupted: bool,

    // Local Calendar Management
    pub local_cals_editing: Vec<CalendarListEntry>,
    pub remote_cals_editing: Vec<CalendarListEntry>,
    pub color_picker_active_href: Option<String>,
    pub temp_color: iced::Color,
    pub scrollable_id: iced::widget::Id,
    pub sidebar_scrollable_id: iced::widget::Id,

    // Window Resizing State
    pub resize_direction: Option<ResizeDirection>,
    pub current_window_size: iced::Size,
    pub ob_urgent_days_input: String,
    pub ob_urgent_prio_input: String,
    pub ob_default_priority_input: String,
    pub ob_start_grace_input: String,
    pub urgent_days: u32,
    pub urgent_prio: u8,
    pub default_priority: u8,
    pub start_grace_period_days: u32,
    pub alarm_tx: Option<mpsc::Sender<SystemEvent>>, // Send tasks to actor
    pub ringing_tasks: Vec<(TodoTask, Alarm)>,       // Stack of firing alarms

    // Snooze Custom Input
    pub snooze_custom_input: String,

    // ICS Import Dialog State
    pub ics_import_dialog_open: bool,
    pub ics_import_file_path: Option<String>,
    pub ics_import_content: Option<String>,
    pub ics_import_selected_calendar: Option<String>,
    pub ics_import_task_count: Option<usize>,

    // Double click tracking
    pub last_click: Option<(std::time::Instant, String)>, // Added

    pub pinned_actions: Vec<crate::config::TaskAction>,
    pub active_context_menu: Option<(String, bool, iced::Point)>, // (UID, is_full_menu, pt)

    // Config cache (New fields)
    // Optional selected language for the GUI. `None` => use system default.
    pub language: Option<String>,
    pub auto_reminders: bool,
    pub default_reminder_time: String,
    pub snooze_short_mins: u32,
    pub snooze_long_mins: u32,
    pub create_events_for_tasks: bool,
    pub delete_events_on_completion: bool,
    pub deleting_events: bool,

    // Settings input buffers for duration strings
    pub ob_snooze_short_input: String,
    pub ob_snooze_long_input: String,
    pub ob_auto_refresh_input: String, // Added

    // Advanced Settings Inputs
    pub show_advanced_settings: bool,
    pub ob_max_done_roots_input: String,
    pub ob_max_done_subtasks_input: String,

    pub show_priority_numbers: bool,
    pub sync_settings: bool,

    // Logging level
    pub log_level: LogLevel,

    // Force Server-Side Decorations
    pub force_ssd: bool,

    // ADDED: Auto Refresh
    pub auto_refresh_interval_mins: u32,

    // ADDED: UI Scale (for global zooming)
    pub ui_scale: f32,
}

impl GuiApp {
    pub fn sort_calendars(&mut self) {
        self.calendars.sort_by_key(|c| {
            if c.href == "local://recovery" {
                1
            } else if c.href == crate::storage::LOCAL_TRASH_HREF {
                2
            } else {
                0
            }
        });
    }

    pub fn get_filtered_calendars(&self) -> Vec<&CalendarListEntry> {
        self.calendars
            .iter()
            .filter(|c| !self.disabled_calendars.contains(&c.href))
            .filter(|c| {
                if c.href == crate::storage::LOCAL_TRASH_HREF || c.href == "local://recovery" {
                    self.store
                        .calendars
                        .get(&c.href)
                        .is_some_and(|map| !map.is_empty())
                } else {
                    true
                }
            })
            .collect()
    }

    pub fn get_task_at_index(&self, idx: usize) -> Option<&TodoTask> {
        match self.tasks.get(idx) {
            Some(crate::store::TaskListItem::Task(t)) => Some(t),
            _ => None,
        }
    }

    pub fn find_task_index_by_uid(&self, uid: &str) -> Option<usize> {
        self.tasks.iter().position(|item| {
            if let crate::store::TaskListItem::Task(t) = item {
                t.uid == uid
            } else {
                false
            }
        })
    }

    pub fn get_move_targets(&self, task_calendar_href: &str) -> Vec<&CalendarListEntry> {
        self.calendars
            .iter()
            .filter(|c| {
                c.href != task_calendar_href
                    && !self.disabled_calendars.contains(&c.href)
                    && c.href != crate::storage::LOCAL_TRASH_HREF
                    && c.href != "local://recovery"
            })
            .collect()
    }
}

impl Default for GuiApp {
    fn default() -> Self {
        // Randomize Location Icon
        let loc_icons = [
            icon::LOCATION,
            icon::EARTH_ASIA,
            icon::EARTH_AMERICAS,
            icon::EARTH_AFRICA,
            icon::EARTH_GENERIC,
            icon::PLANET,
            icon::GALAXY,
            icon::ISLAND,
            icon::COMPASS,
            icon::MOUNTAINS,
            icon::GLOBE,
            icon::GLOBEMODEL,
            icon::MOON,
        ];

        let mut rng = fastrand::Rng::new();

        let location_tab_icon = loc_icons[rng.usize(..loc_icons.len())];

        // Pick initial random icon for the random-jump button
        let random_icon =
            crate::gui::icon::RANDOM_ICONS[rng.usize(..crate::gui::icon::RANDOM_ICONS.len())];

        // Select a random theme (excluding Random itself)
        let themes: Vec<AppTheme> = AppTheme::iter()
            .filter(|&t| t != AppTheme::Random)
            .collect();
        let resolved_random_theme = if !themes.is_empty() {
            themes[rng.usize(..themes.len())]
        } else {
            AppTheme::RustyDark
        };

        let ctx = Arc::new(crate::context::StandardContext::new(None));
        let store = TaskStore::new(ctx.clone());
        let client = Arc::new(tokio::sync::Mutex::new(None));
        let controller = crate::controller::TaskController::new(
            Arc::new(tokio::sync::Mutex::new(store.clone())),
            client,
            ctx.clone(),
        );
        Self {
            core_config: Config::default(),
            ctx: ctx.clone(),
            state: AppState::Loading,
            store,
            controller,
            session: crate::model::SessionState::default(),
            tasks: vec![],
            calendars: vec![],
            client: None,
            tag_aliases: HashMap::new(),
            bg_tx: None,

            cached_categories: Vec::new(),
            cached_locations: Vec::new(),

            task_ids: HashMap::new(),

            sidebar_mode: SidebarMode::Calendars,
            active_cal_href: None,
            hidden_calendars: HashSet::new(),
            disabled_calendars: HashSet::new(),
            yanked_uid: None,
            yank_lock_active: false,
            selected_uid: None,

            active_focus: Focus::MainList,
            sidebar_selection_idx: 0,

            hovered_tag_uid: None,

            hide_completed: false,
            hide_fully_completed_tags: true,
            hide_aliases_in_sidebar: true,
            sort_cutoff_months: Some(2),
            sort_standard_by_priority: false,
            sort_preset: crate::config::SortPreset::default(),
            ob_sort_months_input: "2".to_string(),
            current_theme: AppTheme::default(),
            resolved_random_theme,

            filter_min_duration: None,
            filter_max_duration: None,
            filter_include_unset_duration: true,

            quick_filter_term: "is:ready".to_string(),
            quick_filter_icon: "f0fa9".to_string(),
            show_quick_filter: true,
            sidebar_is_hidden: false,
            ob_quick_filter_term_input: "is:ready".to_string(),
            ob_quick_filter_icon_input: "f0fa9".to_string(),

            input_value: text_editor::Content::new(),
            description_value: text_editor::Content::new(),
            search_value: text_editor::Content::new(),
            search_debounce_version: 0,
            editing_uid: None,
            creating_child_of: None,
            moving_task_uid: None,
            move_target_idx: 0,
            child_lock_active: false,
            creating_with_desc: false,
            new_task_title: String::new(),
            expanded_tasks: HashSet::new(),
            help_expanded_sections: HashSet::new(),
            unsynced_changes: false,
            unsynced_tooltip: String::new(),
            last_sync_failed: false,

            // Session UI defaults
            adding_session_uid: None,
            session_input: iced::widget::text_editor::Content::new(),
            show_all_sessions: HashSet::new(),

            current_placeholder: rust_i18n::t!("new_task_prompt").to_string(),
            search_placeholder: rust_i18n::t!("search_placeholder").to_string(),
            notes_placeholder: rust_i18n::t!("notes_placeholder").to_string(),

            location_tab_icon,
            random_icon,
            alias_input_key: String::new(),
            alias_input_values: String::new(),
            editing_alias_key: None,
            ob_trash_retention_input: "14".to_string(),
            trash_retention_days: 14,

            loading: true,
            error_msg: None,
            ob_url: String::new(),
            ob_user: String::new(),
            ob_pass: String::new(),
            ob_password_visible: false,
            ob_default_cal: None,
            ob_insecure: false,
            config_was_corrupted: false,

            local_cals_editing: vec![],
            remote_cals_editing: vec![],
            color_picker_active_href: None,
            temp_color: iced::Color::WHITE,
            scrollable_id: iced::widget::Id::unique(),
            sidebar_scrollable_id: iced::widget::Id::unique(),

            resize_direction: None,
            current_window_size: iced::Size::new(800.0, 600.0),
            ob_urgent_days_input: "1".to_string(),
            ob_urgent_prio_input: "1".to_string(),
            ob_default_priority_input: "5".to_string(),
            ob_start_grace_input: "1".to_string(),
            urgent_days: 1,
            urgent_prio: 1,
            default_priority: 5,
            start_grace_period_days: 1,
            alarm_tx: None,
            ringing_tasks: Vec::new(),
            snooze_custom_input: String::new(),

            language: None,
            auto_reminders: true,
            default_reminder_time: "09:00".to_string(),
            snooze_short_mins: 60,
            snooze_long_mins: 1440,
            create_events_for_tasks: false,
            delete_events_on_completion: false,
            strikethrough_completed: false,
            deleting_events: false,
            ob_snooze_short_input: "1h".to_string(),
            ob_snooze_long_input: "1d".to_string(),
            ob_auto_refresh_input: "30m".to_string(),

            show_advanced_settings: false,
            ob_max_done_roots_input: "20".to_string(),
            ob_max_done_subtasks_input: "5".to_string(),
            show_priority_numbers: true,
            sync_settings: true,
            log_level: LogLevel::Info,

            force_ssd: {
                #[cfg(target_os = "windows")]
                {
                    let info = os_info::get();
                    matches!(info.os_type(), os_info::Type::Windows)
                        && info.version().to_string().starts_with("10")
                }
                #[cfg(not(target_os = "windows"))]
                {
                    false
                }
            },

            auto_refresh_interval_mins: 30,

            // Default UI scale
            ui_scale: 1.0,

            pinned_actions: crate::config::Config::default().pinned_actions,
            active_context_menu: None,

            last_click: None,

            ics_import_dialog_open: false,
            ics_import_file_path: None,
            ics_import_content: None,
            ics_import_selected_calendar: None,
            ics_import_task_count: None,
        }
    }
}
