//! Export dialog UI
//!
//! Provides a user interface for configuring and starting audio/video exports.

use eframe::egui;
use lightningbeam_core::export::{AudioExportSettings, AudioFormat, VideoExportSettings, VideoCodec, VideoQuality};
use std::path::PathBuf;

/// Export type selection
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExportType {
    Audio,
    Video,
}

/// Export result from dialog
#[derive(Debug, Clone)]
pub enum ExportResult {
    AudioOnly(AudioExportSettings, PathBuf),
    VideoOnly(VideoExportSettings, PathBuf),
    VideoWithAudio(VideoExportSettings, AudioExportSettings, PathBuf),
}

/// Export dialog state
pub struct ExportDialog {
    /// Is the dialog open?
    pub open: bool,

    /// Export type (Audio or Video)
    pub export_type: ExportType,

    /// Audio export settings
    pub audio_settings: AudioExportSettings,

    /// Video export settings
    pub video_settings: VideoExportSettings,

    /// Include audio with video?
    pub include_audio: bool,

    /// Output file path
    pub output_path: Option<PathBuf>,

    /// Selected audio preset index (for UI)
    pub selected_audio_preset: usize,

    /// Error message (if any)
    pub error_message: Option<String>,
}

impl Default for ExportDialog {
    fn default() -> Self {
        Self {
            open: false,
            export_type: ExportType::Audio,
            audio_settings: AudioExportSettings::default(),
            video_settings: VideoExportSettings::default(),
            include_audio: true,
            output_path: None,
            selected_audio_preset: 0,
            error_message: None,
        }
    }
}

impl ExportDialog {
    /// Open the dialog with default settings
    pub fn open(&mut self, timeline_duration: f64) {
        self.open = true;
        self.audio_settings.end_time = timeline_duration;
        self.video_settings.end_time = timeline_duration;
        self.error_message = None;
    }

    /// Close the dialog
    pub fn close(&mut self) {
        self.open = false;
        self.error_message = None;
    }

    /// Render the export dialog
    ///
    /// Returns Some(ExportResult) if the user clicked Export, None otherwise.
    pub fn render(&mut self, ctx: &egui::Context) -> Option<ExportResult> {
        if !self.open {
            return None;
        }

        let mut should_export = false;
        let mut should_close = false;
        let mut open = self.open;

        let window_title = match self.export_type {
            ExportType::Audio => "Export Audio",
            ExportType::Video => "Export Video",
        };

        egui::Window::new(window_title)
            .open(&mut open)
            .resizable(false)
            .collapsible(false)
            .anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
            .show(ctx, |ui| {
                ui.set_width(500.0);

                // Error message (if any)
                if let Some(error) = &self.error_message {
                    ui.colored_label(egui::Color32::RED, error);
                    ui.add_space(8.0);
                }

                // Export type selection (tabs)
                ui.horizontal(|ui| {
                    ui.selectable_value(&mut self.export_type, ExportType::Audio, "🎵 Audio");
                    ui.selectable_value(&mut self.export_type, ExportType::Video, "🎬 Video");
                });

                ui.add_space(12.0);
                ui.separator();
                ui.add_space(12.0);

                // Render either audio or video settings
                match self.export_type {
                    ExportType::Audio => self.render_audio_settings(ui),
                    ExportType::Video => self.render_video_settings(ui),
                }

                ui.add_space(12.0);

                // Time range (common to both)
                self.render_time_range(ui);

                ui.add_space(12.0);

                // Output file path (common to both)
                self.render_output_selection(ui);

                ui.add_space(16.0);

                // Buttons
                ui.horizontal(|ui| {
                    if ui.button("Cancel").clicked() {
                        should_close = true;
                    }

                    ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
                        if ui.button("Export").clicked() {
                            should_export = true;
                        }
                    });
                });
            });

        // Update open state (in case user clicked X button)
        self.open = open;

        if should_close {
            self.close();
            return None;
        }

        if should_export {
            return self.handle_export();
        }

        None
    }

    /// Render audio export settings UI
    fn render_audio_settings(&mut self, ui: &mut egui::Ui) {
        // Preset selection
        ui.heading("Preset");
                ui.horizontal(|ui| {
                    let presets = [
                        ("High Quality WAV", AudioExportSettings::high_quality_wav()),
                        ("High Quality FLAC", AudioExportSettings::high_quality_flac()),
                        ("Standard MP3", AudioExportSettings::standard_mp3()),
                        ("Standard AAC", AudioExportSettings::standard_aac()),
                        ("High Quality MP3", AudioExportSettings::high_quality_mp3()),
                        ("High Quality AAC", AudioExportSettings::high_quality_aac()),
                        ("Podcast MP3", AudioExportSettings::podcast_mp3()),
                        ("Podcast AAC", AudioExportSettings::podcast_aac()),
                    ];

                    egui::ComboBox::from_id_salt("export_preset")
                        .selected_text(presets[self.selected_audio_preset].0)
                        .show_ui(ui, |ui| {
                            for (i, (name, _)) in presets.iter().enumerate() {
                                if ui.selectable_value(&mut self.selected_audio_preset, i, *name).clicked() {
                                    // Save current time range before applying preset
                                    let saved_start = self.audio_settings.start_time;
                                    let saved_end = self.audio_settings.end_time;
                                    self.audio_settings = presets[i].1.clone();
                                    // Restore time range
                                    self.audio_settings.start_time = saved_start;
                                    self.audio_settings.end_time = saved_end;
                                }
                            }
                        });
                });

                ui.add_space(12.0);

        ui.add_space(12.0);

        // Format settings
        ui.heading("Format");
        ui.horizontal(|ui| {
            ui.label("Format:");
            egui::ComboBox::from_id_salt("audio_format")
                .selected_text(self.audio_settings.format.name())
                .show_ui(ui, |ui| {
                    ui.selectable_value(&mut self.audio_settings.format, AudioFormat::Wav, "WAV (Uncompressed)");
                    ui.selectable_value(&mut self.audio_settings.format, AudioFormat::Flac, "FLAC (Lossless)");
                    ui.selectable_value(&mut self.audio_settings.format, AudioFormat::Mp3, "MP3");
                    ui.selectable_value(&mut self.audio_settings.format, AudioFormat::Aac, "AAC");
                });
        });

        ui.add_space(8.0);

        // Audio settings
        ui.horizontal(|ui| {
            ui.label("Sample Rate:");
            egui::ComboBox::from_id_salt("sample_rate")
                .selected_text(format!("{} Hz", self.audio_settings.sample_rate))
                .show_ui(ui, |ui| {
                    ui.selectable_value(&mut self.audio_settings.sample_rate, 44100, "44100 Hz");
                    ui.selectable_value(&mut self.audio_settings.sample_rate, 48000, "48000 Hz");
                    ui.selectable_value(&mut self.audio_settings.sample_rate, 96000, "96000 Hz");
                });
        });

        ui.horizontal(|ui| {
            ui.label("Channels:");
            ui.radio_value(&mut self.audio_settings.channels, 1, "Mono");
            ui.radio_value(&mut self.audio_settings.channels, 2, "Stereo");
        });

        ui.add_space(8.0);

        // Format-specific settings
        if self.audio_settings.format.supports_bit_depth() {
            ui.horizontal(|ui| {
                ui.label("Bit Depth:");
                ui.radio_value(&mut self.audio_settings.bit_depth, 16, "16-bit");
                ui.radio_value(&mut self.audio_settings.bit_depth, 24, "24-bit");
            });
        }

        if self.audio_settings.format.uses_bitrate() {
            ui.horizontal(|ui| {
                ui.label("Bitrate:");
                egui::ComboBox::from_id_salt("bitrate")
                    .selected_text(format!("{} kbps", self.audio_settings.bitrate_kbps))
                    .show_ui(ui, |ui| {
                        ui.selectable_value(&mut self.audio_settings.bitrate_kbps, 128, "128 kbps");
                        ui.selectable_value(&mut self.audio_settings.bitrate_kbps, 192, "192 kbps");
                        ui.selectable_value(&mut self.audio_settings.bitrate_kbps, 256, "256 kbps");
                        ui.selectable_value(&mut self.audio_settings.bitrate_kbps, 320, "320 kbps");
                    });
            });
        }
    }

    /// Render video export settings UI
    fn render_video_settings(&mut self, ui: &mut egui::Ui) {
        // Codec selection
        ui.heading("Codec");
        ui.horizontal(|ui| {
            ui.label("Codec:");
            egui::ComboBox::from_id_salt("video_codec")
                .selected_text(format!("{:?}", self.video_settings.codec))
                .show_ui(ui, |ui| {
                    ui.selectable_value(&mut self.video_settings.codec, VideoCodec::H264, "H.264 (Most Compatible)");
                    ui.selectable_value(&mut self.video_settings.codec, VideoCodec::H265, "H.265 (Better Compression)");
                    ui.selectable_value(&mut self.video_settings.codec, VideoCodec::VP8, "VP8 (WebM)");
                    ui.selectable_value(&mut self.video_settings.codec, VideoCodec::VP9, "VP9 (WebM)");
                    ui.selectable_value(&mut self.video_settings.codec, VideoCodec::ProRes422, "ProRes 422 (Professional)");
                });
        });

        ui.add_space(12.0);

        // Resolution
        ui.heading("Resolution");
        ui.horizontal(|ui| {
            ui.label("Width:");
            let mut custom_width = self.video_settings.width.unwrap_or(1920);
            if ui.add(egui::DragValue::new(&mut custom_width).range(1..=7680)).changed() {
                self.video_settings.width = Some(custom_width);
            }

            ui.label("Height:");
            let mut custom_height = self.video_settings.height.unwrap_or(1080);
            if ui.add(egui::DragValue::new(&mut custom_height).range(1..=4320)).changed() {
                self.video_settings.height = Some(custom_height);
            }
        });

        // Resolution presets
        ui.horizontal(|ui| {
            if ui.button("1080p").clicked() {
                self.video_settings.width = Some(1920);
                self.video_settings.height = Some(1080);
            }
            if ui.button("4K").clicked() {
                self.video_settings.width = Some(3840);
                self.video_settings.height = Some(2160);
            }
            if ui.button("720p").clicked() {
                self.video_settings.width = Some(1280);
                self.video_settings.height = Some(720);
            }
        });

        ui.add_space(12.0);

        // Framerate
        ui.heading("Framerate");
        ui.horizontal(|ui| {
            ui.label("FPS:");
            egui::ComboBox::from_id_salt("framerate")
                .selected_text(format!("{}", self.video_settings.framerate as u32))
                .show_ui(ui, |ui| {
                    ui.selectable_value(&mut self.video_settings.framerate, 24.0, "24");
                    ui.selectable_value(&mut self.video_settings.framerate, 30.0, "30");
                    ui.selectable_value(&mut self.video_settings.framerate, 60.0, "60");
                });
        });

        ui.add_space(12.0);

        // Quality
        ui.heading("Quality");
        ui.horizontal(|ui| {
            ui.label("Quality:");
            egui::ComboBox::from_id_salt("video_quality")
                .selected_text(self.video_settings.quality.name())
                .show_ui(ui, |ui| {
                    ui.selectable_value(&mut self.video_settings.quality, VideoQuality::Low, VideoQuality::Low.name());
                    ui.selectable_value(&mut self.video_settings.quality, VideoQuality::Medium, VideoQuality::Medium.name());
                    ui.selectable_value(&mut self.video_settings.quality, VideoQuality::High, VideoQuality::High.name());
                    ui.selectable_value(&mut self.video_settings.quality, VideoQuality::VeryHigh, VideoQuality::VeryHigh.name());
                });
        });

        ui.add_space(12.0);

        // Include audio checkbox
        ui.checkbox(&mut self.include_audio, "Include Audio");
    }

    /// Render time range UI (common to both audio and video)
    fn render_time_range(&mut self, ui: &mut egui::Ui) {
        let (start_time, end_time) = match self.export_type {
            ExportType::Audio => (&mut self.audio_settings.start_time, &mut self.audio_settings.end_time),
            ExportType::Video => (&mut self.video_settings.start_time, &mut self.video_settings.end_time),
        };

        ui.heading("Time Range");
        ui.horizontal(|ui| {
            ui.label("Start:");
            ui.add(egui::DragValue::new(start_time)
                .speed(0.1)
                .range(0.0..=*end_time)
                .suffix(" s"));

            ui.label("End:");
            ui.add(egui::DragValue::new(end_time)
                .speed(0.1)
                .range(*start_time..=f64::MAX)
                .suffix(" s"));
        });

        let duration = *end_time - *start_time;
        ui.label(format!("Duration: {:.2} seconds", duration));
    }

    /// Render output file selection UI (common to both audio and video)
    fn render_output_selection(&mut self, ui: &mut egui::Ui) {
        ui.heading("Output");
        ui.horizontal(|ui| {
            let path_text = self.output_path.as_ref()
                .map(|p| p.display().to_string())
                .unwrap_or_else(|| "No file selected".to_string());

            ui.label("File:");
            ui.text_edit_singleline(&mut path_text.clone());

            if ui.button("Browse...").clicked() {
                // Determine file extension and filter based on export type
                let (default_name, filter_name, extensions) = match self.export_type {
                    ExportType::Audio => {
                        let ext = self.audio_settings.format.extension();
                        (format!("audio.{}", ext), "Audio", vec![ext])
                    }
                    ExportType::Video => {
                        let ext = self.video_settings.codec.container_format();
                        (format!("video.{}", ext), "Video", vec![ext])
                    }
                };

                if let Some(path) = rfd::FileDialog::new()
                    .set_file_name(&default_name)
                    .add_filter(filter_name, &extensions)
                    .save_file()
                {
                    self.output_path = Some(path);
                }
            }
        });
    }

    /// Handle export button click
    fn handle_export(&mut self) -> Option<ExportResult> {
        // Check if output path is set
        if self.output_path.is_none() {
            self.error_message = Some("Please select an output file".to_string());
            return None;
        }

        let output_path = self.output_path.clone().unwrap();

        let result = match self.export_type {
            ExportType::Audio => {
                // Validate audio settings
                if let Err(err) = self.audio_settings.validate() {
                    self.error_message = Some(err);
                    return None;
                }

                Some(ExportResult::AudioOnly(self.audio_settings.clone(), output_path))
            }
            ExportType::Video => {
                // Validate video settings
                if let Err(err) = self.video_settings.validate() {
                    self.error_message = Some(err);
                    return None;
                }

                if self.include_audio {
                    // Validate audio settings too
                    if let Err(err) = self.audio_settings.validate() {
                        self.error_message = Some(err);
                        return None;
                    }

                    // Sync time range from video to audio
                    self.audio_settings.start_time = self.video_settings.start_time;
                    self.audio_settings.end_time = self.video_settings.end_time;

                    Some(ExportResult::VideoWithAudio(
                        self.video_settings.clone(),
                        self.audio_settings.clone(),
                        output_path,
                    ))
                } else {
                    Some(ExportResult::VideoOnly(self.video_settings.clone(), output_path))
                }
            }
        };

        self.close();
        result
    }
}

/// Export progress dialog state
pub struct ExportProgressDialog {
    /// Is the dialog open?
    pub open: bool,

    /// Current progress message
    pub message: String,

    /// Progress (0.0 to 1.0)
    pub progress: f32,

    /// Start time for elapsed time calculation
    pub start_time: Option<std::time::Instant>,

    /// Was cancel requested?
    pub cancel_requested: bool,
}

impl Default for ExportProgressDialog {
    fn default() -> Self {
        Self {
            open: false,
            message: String::new(),
            progress: 0.0,
            start_time: None,
            cancel_requested: false,
        }
    }
}

impl ExportProgressDialog {
    /// Open the progress dialog
    pub fn open(&mut self) {
        self.open = true;
        self.message = "Starting export...".to_string();
        self.progress = 0.0;
        self.start_time = Some(std::time::Instant::now());
        self.cancel_requested = false;
    }

    /// Close the dialog
    pub fn close(&mut self) {
        self.open = false;
        self.start_time = None;
        self.cancel_requested = false;
    }

    /// Update progress
    pub fn update_progress(&mut self, message: String, progress: f32) {
        self.message = message;
        self.progress = progress.clamp(0.0, 1.0);
    }

    /// Render the export progress dialog
    ///
    /// Returns true if the user clicked Cancel
    pub fn render(&mut self, ctx: &egui::Context) -> bool {
        if !self.open {
            return false;
        }

        let mut should_cancel = false;

        egui::Window::new("Exporting...")
            .open(&mut self.open)
            .resizable(false)
            .collapsible(false)
            .anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
            .show(ctx, |ui| {
                ui.set_width(400.0);

                // Status message
                ui.label(&self.message);
                ui.add_space(8.0);

                // Progress bar
                let progress_text = format!("{:.0}%", self.progress * 100.0);
                ui.add(egui::ProgressBar::new(self.progress).text(progress_text));
                ui.add_space(8.0);

                // Elapsed time and estimate
                if let Some(start_time) = self.start_time {
                    let elapsed = start_time.elapsed();
                    let elapsed_secs = elapsed.as_secs();

                    ui.horizontal(|ui| {
                        ui.label(format!(
                            "Elapsed: {}:{:02}",
                            elapsed_secs / 60,
                            elapsed_secs % 60
                        ));

                        // Estimate remaining time if we have progress
                        if self.progress > 0.01 {
                            let total_estimated = elapsed.as_secs_f32() / self.progress;
                            let remaining = total_estimated - elapsed.as_secs_f32();
                            if remaining > 0.0 {
                                ui.label(format!(
                                    "  |  Remaining: ~{}:{:02}",
                                    (remaining as u64) / 60,
                                    (remaining as u64) % 60
                                ));
                            }
                        }
                    });
                }

                ui.add_space(12.0);

                // Cancel button
                ui.horizontal(|ui| {
                    ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
                        if ui.button("Cancel").clicked() {
                            should_cancel = true;
                        }
                    });
                });
            });

        if should_cancel {
            self.cancel_requested = true;
        }

        should_cancel
    }
}
