//! Kurulumun gerçek olarak yürütüldüğü ekran.
//!
//! Sol yarı : Slayt gösterisi (Slideshow)
//! Sağ yarı : İlerleme çubuğu + renkli log terminali
//!
//! Hata olursa tüm panel ErrorScreen ile kaplanır.

use std::sync::mpsc;
use std::thread;
use std::time::{Duration, Instant};
use eframe::egui;
use rust_i18n::t;

use crate::installer::{GlobalState, InstallerStep};
use crate::jobs::{self, InstallMessage, UiSender};
use crate::ui::{ErrorScreen, Slideshow};
use crate::ui::theme;

#[derive(Default)]
pub struct ExecutionStep {
    rx:           Option<mpsc::Receiver<InstallMessage>>,
    tx:           Option<mpsc::Sender<InstallMessage>>,
    finished:     bool,
    error_screen: Option<ErrorScreen>,
    slideshow:    Option<Slideshow>,
    /// rsync kopyalama fazı aktifken tek ilerleme çubuğu gösterilir.
    copy_active:  bool,
    /// Kurulum bitince tamamlandı ekranına otomatik geçiş için zaman damgası.
    finished_at:  Option<Instant>,
}

impl InstallerStep for ExecutionStep {
    fn name(&self) -> String { t!("execution").to_string() }

    fn on_enter(&mut self, state: &mut GlobalState) {
        let (tx, rx) = mpsc::channel::<InstallMessage>();
        self.rx           = Some(rx);
        self.tx           = Some(tx);
        self.finished     = false;
        self.error_screen = None;
        self.finished_at  = None;

        let desktop = std::env::var("XDG_CURRENT_DESKTOP")
            .unwrap_or_else(|_| "default".to_string())
            .to_lowercase();
        let cwd = std::env::current_dir().map(|d| d.display().to_string()).unwrap_or_default();
        let ss = Slideshow::new(&desktop, &state.language);
        state.install_log.push(format!("Slideshow: cwd={}, lang={}, desktop={}, slayt={}", cwd, state.language, desktop, ss.slide_count()));
        self.slideshow = Some(ss);

        state.install_progress = 0.0;
        state.install_sub_progress = 0.0;
        self.copy_active = false;
        state.install_log.clear();
        state.install_current_file = None;
        state.install_log.push(t!("install_starting").to_string());
    }

    fn show(&mut self, ui: &mut egui::Ui, state: &mut GlobalState) {
        // ── İş parçacığını ilk show()'da başlat ───────────────
        if let Some(tx) = self.tx.take() {
            let timezone   = state.timezone.clone();
            let language   = state.language.clone();
            let plan       = state.partition_plan.clone();
            let username   = state.username.clone();
            let password   = state.password.clone();
            let hostname   = state.hostname.clone();
            let kb_layout  = state.keyboard_layout.clone();
            let kb_variant = state.keyboard_variant.clone();
            let demo_mode  = state.demo_mode;
            let ctx        = ui.ctx().clone();
            let erase_disk = state.erase_disk;
            let custom_partitions = state.custom_partitions.clone();
            let volume_groups = state.volume_groups.clone();
            let logical_volumes = state.logical_volumes.clone();
            let selected_disk = state.selected_disk.clone();

            let boot_device         = state.bootloader_device.clone();
            let bootloader_timeout  = state.bootloader_timeout;
            let bootloader_password = state.bootloader_password.clone();
            let kernel_options      = state.kernel_options.clone();
            let use_ntp             = state.use_ntp;
            let root_password       = state.root_password.clone();
            let display_manager     = state.display_manager.clone();
            let autologin           = state.autologin;
            let desktop_environment = state.desktop_environment.clone();
            let selected_package_groups = state.selected_package_groups.clone();
            let manual_year         = state.manual_year;
            let manual_month        = state.manual_month;
            let manual_day          = state.manual_day;
            let manual_hour         = state.manual_hour;
            let manual_minute       = state.manual_minute;

            let ui_sender = UiSender::new(tx, ctx);

            thread::spawn(move || {
                let locale = if language == "tr" {
                    "tr_TR.UTF-8".to_string()
                } else {
                    "en_US.UTF-8".to_string()
                };
                let rt = tokio::runtime::Runtime::new().expect("tokio runtime");
                let src = jobs::detect_source_dir();

                if erase_disk {
                    if let Some(p) = plan {
                        let mut queue = jobs::build_full_job_queue(
                            p,
                            jobs::JobQueueConfig {
                                mount:               "/mnt".to_string(),
                                source:              src,
                                language,
                                locale,
                                timezone,
                                username,
                                password,
                                hostname,
                                kb_layout,
                                kb_variant,
                                demo_mode,
                                boot_device,
                                bootloader_timeout,
                                bootloader_password,
                                kernel_options,
                                use_ntp,
                                root_password,
                                display_manager: display_manager.clone(),
                                autologin,
                                desktop_environment: desktop_environment.clone(),
                                selected_package_groups: selected_package_groups.clone(),
                                manual_year,
                                manual_month,
                                manual_day,
                                manual_hour,
                                manual_minute,
                            },
                        );
                        rt.block_on(queue.run_all(ui_sender));
                    } else {
                        ui_sender.send(InstallMessage::Error(
                            t!("error_partition_plan_not_found").to_string()
                        ));
                    }
                } else if let Some(disk) = selected_disk {
                        let mut queue = jobs::build_custom_job_queue(
                            disk,
                            custom_partitions,
                            volume_groups,
                            logical_volumes,
                            jobs::JobQueueConfig {
                                mount:               "/mnt".to_string(),
                                source:              src,
                                language,
                                locale,
                                timezone,
                                username,
                                password,
                                hostname,
                                kb_layout,
                                kb_variant,
                                demo_mode,
                                boot_device,
                                bootloader_timeout,
                                bootloader_password,
                                kernel_options,
                                use_ntp,
                                root_password,
                                display_manager: display_manager.clone(),
                                autologin,
                                desktop_environment: desktop_environment.clone(),
                                selected_package_groups: selected_package_groups.clone(),
                                manual_year,
                                manual_month,
                                manual_day,
                                manual_hour,
                                manual_minute,
                            },
                        );
                        rt.block_on(queue.run_all(ui_sender));
                    } else {
                        ui_sender.send(InstallMessage::Error(
                            t!("error_target_disk_not_selected").to_string()
                        ));
                    }
            });
        }

        // ── Kanaldaki mesajları tüket ──────────────────────────
        if let Some(ref rx) = self.rx {
            loop {
                match rx.try_recv() {
                    Ok(InstallMessage::Log(line)) => {
                        state.install_log.push(line);
                    }
                    Ok(InstallMessage::Progress(p)) => {
                        state.install_progress = p;
                    }
                    Ok(InstallMessage::SubProgress(p)) => {
                        state.install_sub_progress = p;
                    }
                    Ok(InstallMessage::CopyStarted) => {
                        self.copy_active = true;
                    }
                    Ok(InstallMessage::CopyFinished) => {
                        self.copy_active = false;
                    }
                    Ok(InstallMessage::CurrentFile(f)) => {
                        state.install_current_file = Some(f);
                    }
                    Ok(InstallMessage::Done) => {
                        state.install_progress = 1.0;
                        self.finished = true;
                        self.finished_at = Some(Instant::now());
                    }
                    Ok(InstallMessage::Error(e)) => {
                        self.error_screen = Some(ErrorScreen::new(
                            t!("install_failed"),
                            e,
                            state.install_log.clone(),
                        ));
                    }
                    Err(mpsc::TryRecvError::Empty) => break,
                    Err(mpsc::TryRecvError::Disconnected) => {
                        if !self.finished && self.error_screen.is_none() {
                            self.error_screen = Some(ErrorScreen::new(
                                t!("install_failed"),
                                t!("error_thread_unexpectedly_terminated").to_string(),
                                state.install_log.clone(),
                            ));
                        }
                        break;
                    }
                }
            }
        }

        // ── Hata ekranı ────────────────────────────────────────
        if let Some(ref mut err) = self.error_screen {
            let mut retry = false;
            let mut quit  = false;
            err.show(ui, || retry = true, || quit = true);
            if retry { self.on_enter(state); }
            if quit  { ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close); }
            return;
        }

        // ── Normal kurulum görünümü ────────────────────────────
        // Üst: Slayt gösterisi (kalan alanı doldurur) | Alt: ilerleme durumu
        let available_w = ui.available_width();

        ui.vertical(|ui| {
            // ── Üst kısım — başlık + slayt gösterisi (kalan alanı doldurur) ──
            ui.add_space(8.0);
            theme::section_heading(ui, &t!("execution_title"));
            ui.label(
                egui::RichText::new(t!("execution_description"))
                    .color(theme::c_text_dim())
                    .size(13.0),
            );
            ui.add_space(16.0);

            // Alt kısım (ilerleme + durum) için ayrılan yükseklik.
            // bottom_up layout en sonda olduğu için slayt alanını kalan
            // yükseklikle sınırlandırıyoruz; aksi halde slayt gösterisi
            // ekranın dışına itilir.
            let bottom_h = 170.0;
            let slide_h = (ui.available_height() - bottom_h).max(200.0);
            ui.allocate_ui(egui::vec2(available_w, slide_h), |ui| {
                ui.set_min_height(slide_h);
                if let Some(ref mut ss) = self.slideshow {
                    ss.show(ui);
                }
            });

            ui.add_space(16.0);

            // ── Alt kısım — ilerleme + durum (en altta) ──────────
            ui.with_layout(egui::Layout::bottom_up(egui::Align::Min), |ui| {
                ui.add_space(8.0);

                // İlerleme çubuğu — yalnızca rsync kopyalama fazında
                // tek bar gösterilir (eski YALI düzeni). Diğer adımlar
                // (fstab, GRUB, temizlik vb.) metin + spinner olarak
                // görünür.
                let running = !self.finished
                    && self.error_screen.is_none()
                    && (self.copy_active || state.install_progress > 0.0);

                egui::Frame::none()
                    .fill(theme::c_bg_widget())
                    .rounding(egui::Rounding::same(8.0))
                    .inner_margin(egui::Margin::same(12.0))
                    .show(ui, |ui| {
                        ui.set_width(available_w - 4.0);
                        let step_label = state.install_log.last()
                            .cloned()
                            .unwrap_or_default();
                        ui.label(
                            egui::RichText::new(&step_label)
                                .size(12.0)
                                .color(theme::c_text_dim()),
                        );

                        if self.copy_active {
                            let pct = format!("{:.0}%", state.install_sub_progress * 100.0);
                            let bar = ui.add(
                                egui::ProgressBar::new(state.install_sub_progress)
                                    .animate(running)
                                    .desired_height(20.0),
                            );
                            ui.painter().text(
                                bar.rect.center(),
                                egui::Align2::CENTER_CENTER,
                                pct,
                                egui::FontId::proportional(14.0),
                                theme::c_text(),
                            );

                            if let Some(ref current_file) = state.install_current_file {
                                ui.add_space(4.0);
                                ui.label(
                                    egui::RichText::new(format!("{}: {}", t!("install_current_file"), current_file))
                                        .size(12.0)
                                        .color(theme::c_text_dim()),
                                );
                            }
                        } else if running {
                            ui.add_space(4.0);
                            ui.horizontal(|ui| {
                                ui.spinner();
                                ui.colored_label(theme::c_text_dim(), t!("install_in_progress"));
                            });
                        }
                    });

                // Durum etiketi
                ui.add_space(8.0);
                if self.finished {
                    theme::success_box(ui, &t!("install_done"));
                } else if running {
                    ui.horizontal(|ui| {
                        ui.spinner();
                        ui.colored_label(theme::c_text_dim(), t!("install_in_progress"));
                    });
                }

                ui.add_space(16.0);
                ui.separator();
                ui.add_space(16.0);
            });
        });

        // Kurulum devam ediyorsa sürekli yeniden çiz
        if !self.finished && self.error_screen.is_none() {
            ui.ctx().request_repaint();
        }

        // Kurulum tamamlanınca kısa bir bekleyişten sonra otomatik olarak
        // tamamlandı ekranına geç
        if self.finished && self.error_screen.is_none() {
            if let Some(at) = self.finished_at {
                if at.elapsed() >= Duration::from_secs(2) {
                    state.current_step += 1;
                } else {
                    ui.ctx().request_repaint_after(Duration::from_secs(1));
                }
            }
        }
    }

    fn is_complete(&self, _state: &GlobalState) -> bool {
        self.finished && self.error_screen.is_none()
    }
}

// fn log_color(line: &str) -> egui::Color32 {
//     if line.starts_with('✗') {
//         theme::c_error()
//     } else if line.starts_with('✓') {
//         theme::c_success()
//     } else if line.starts_with('▶') {
//         theme::c_accent()
//     } else if line.starts_with('⚠') {
//         theme::c_warning()
//     } else {
//         egui::Color32::from_rgb(185, 185, 205)
//     }
// }
