use anyhow::Result;
use chrono::{Local, Utc};
use crossterm::event::{self, Event, KeyCode, KeyEventKind};
use ratatui::{
    backend::Backend,
    layout::{Alignment, Constraint, Direction, Layout, Rect},
    style::{Modifier, Style},
    text::{Line, Span},
    widgets::{Block, Borders, Cell, Paragraph, Row, Table, TableState},
    Frame, Terminal,
};
use std::time::Duration;

use crate::{
    db::queries::SessionQueries,
    db::{get_database_path, Database},
    models::Session,
    ui::{formatter::Formatter, widgets::ColorScheme},
};

pub struct SessionHistoryBrowser {
    sessions: Vec<Session>,
    table_state: TableState,
    show_filters: bool,
    user_host_string: String,
}

impl SessionHistoryBrowser {
    pub async fn new() -> Result<Self> {
        let db_path = get_database_path()?;
        let db = Database::new(&db_path)?;

        // Load recent sessions (last 100)
        let sessions =
            SessionQueries::list_with_filter(&db.connection, None, None, None, Some(100))?;

        let mut table_state = TableState::default();
        if !sessions.is_empty() {
            table_state.select(Some(0));
        }

        // Get user@machine string
        let user = std::process::Command::new("git")
            .args(["config", "user.name"])
            .output()
            .ok()
            .and_then(|output| {
                if output.status.success() {
                    Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
                } else {
                    None
                }
            })
            .or_else(|| std::env::var("USER").ok())
            .unwrap_or_else(|| "user".to_string());

        let host = std::process::Command::new("hostname")
            .output()
            .ok()
            .and_then(|output| {
                if output.status.success() {
                    Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
                } else {
                    None
                }
            })
            .or_else(|| std::env::var("HOSTNAME").ok())
            .unwrap_or_else(|| "machine".to_string());

        let user_host_string = format!("{}@{}", user, host);

        Ok(Self {
            sessions,
            table_state,
            show_filters: false,
            user_host_string,
        })
    }

    pub async fn run<B: Backend>(&mut self, terminal: &mut Terminal<B>) -> Result<()> {
        loop {
            terminal.draw(|f| self.render(f))?;

            if event::poll(Duration::from_millis(100))? {
                match event::read()? {
                    Event::Key(key) if key.kind == KeyEventKind::Press => {
                        match key.code {
                            KeyCode::Char('q') | KeyCode::Esc => break,
                            KeyCode::Up => {
                                let i = match self.table_state.selected() {
                                    Some(i) => {
                                        if i == 0 {
                                            self.sessions.len() - 1
                                        } else {
                                            i - 1
                                        }
                                    }
                                    None => 0,
                                };
                                self.table_state.select(Some(i));
                            }
                            KeyCode::Down => {
                                let i = match self.table_state.selected() {
                                    Some(i) => {
                                        if i >= self.sessions.len() - 1 {
                                            0
                                        } else {
                                            i + 1
                                        }
                                    }
                                    None => 0,
                                };
                                self.table_state.select(Some(i));
                            }
                            KeyCode::Char('f') => {
                                self.show_filters = !self.show_filters;
                            }
                            KeyCode::Enter => {
                                // Could toggle details expansion or similar
                            }
                            _ => {}
                        }
                    }
                    _ => {}
                }
            }
        }

        Ok(())
    }

    fn render(&mut self, f: &mut Frame) {
        let chunks = Layout::default()
            .direction(Direction::Vertical)
            .constraints([
                Constraint::Length(3), // Header
                Constraint::Length(3), // Filter Bar
                Constraint::Min(0),    // Main Content (Table + Details)
                Constraint::Length(1), // Footer
            ])
            .split(f.size());

        // 0. Header
        self.render_header(f, chunks[0]);

        // 1. Filter Bar
        self.render_filter_bar(f, chunks[1]);

        // 2. Main Content
        self.render_main_content(f, chunks[2]);

        // 3. Footer
        self.render_footer(f, chunks[3]);
    }

    fn render_header(&self, f: &mut Frame, area: Rect) {
        let block = Block::default()
            .borders(Borders::BOTTOM)
            .border_style(Style::default().fg(ColorScheme::BORDER_DARK));

        f.render_widget(block, area);

        let chunks = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([
                Constraint::Percentage(50), // Title
                Constraint::Percentage(50), // User@Host
            ])
            .margin(1)
            .split(area);

        f.render_widget(
            Paragraph::new("SESSION HISTORY").style(
                Style::default()
                    .fg(ColorScheme::TEXT_MAIN)
                    .add_modifier(Modifier::BOLD),
            ),
            chunks[0],
        );

        f.render_widget(
            Paragraph::new(self.user_host_string.as_str())
                .alignment(Alignment::Right)
                .style(Style::default().fg(ColorScheme::TEXT_SECONDARY)),
            chunks[1],
        );
    }

    fn render_filter_bar(&self, f: &mut Frame, area: Rect) {
        let block = Block::default()
            .borders(Borders::BOTTOM)
            .border_style(Style::default().fg(ColorScheme::BORDER_DARK))
            .style(Style::default().bg(ColorScheme::BG_DARK));

        f.render_widget(block, area);

        let layout = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([
                Constraint::Length(20), // Start Date
                Constraint::Length(20), // End Date
                Constraint::Length(20), // Project
                Constraint::Length(20), // Duration
                Constraint::Min(10),    // Search
            ])
            .margin(1)
            .split(area);

        let filters = [
            "Start Date: [All]",
            "End Date: [All]",
            "Project: [All]",
            "Duration: [Any]",
            "Search: [None]",
        ];

        for (i, filter) in filters.iter().enumerate() {
            if i < layout.len() {
                f.render_widget(
                    Paragraph::new(*filter).style(Style::default().fg(ColorScheme::TEXT_SECONDARY)),
                    layout[i],
                );
            }
        }
    }

    fn render_main_content(&mut self, f: &mut Frame, area: Rect) {
        let chunks = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([
                Constraint::Percentage(70), // Table
                Constraint::Percentage(30), // Details
            ])
            .split(area);

        // Table
        self.render_session_table(f, chunks[0]);

        // Details
        self.render_details_panel(f, chunks[1]);
    }

    fn render_session_table(&mut self, f: &mut Frame, area: Rect) {
        let block = Block::default()
            .borders(Borders::RIGHT)
            .border_style(Style::default().fg(ColorScheme::BORDER_DARK));

        f.render_widget(block.clone(), area);
        let inner_area = block.inner(area);

        let header_cells = ["DATE", "PROJECT", "DURATION", "START", "END", "STATUS"]
            .iter()
            .map(|h| {
                Cell::from(*h).style(
                    Style::default()
                        .fg(ColorScheme::TEXT_SECONDARY)
                        .add_modifier(Modifier::BOLD),
                )
            });

        let header = Row::new(header_cells).height(1).bottom_margin(1);

        let rows = self.sessions.iter().map(|session| {
            let duration = if let Some(end) = session.end_time {
                (end - session.start_time).num_seconds() - session.paused_duration.num_seconds()
            } else {
                (Utc::now() - session.start_time).num_seconds()
                    - session.paused_duration.num_seconds()
            };

            let start_time = session.start_time.with_timezone(&Local);
            let date_str = start_time.format("%Y-%m-%d").to_string();
            let start_str = start_time.format("%H:%M").to_string();
            let end_str = if let Some(end) = session.end_time {
                end.with_timezone(&Local).format("%H:%M").to_string()
            } else {
                "-".to_string()
            };

            let duration_str = Formatter::format_duration(duration);
            let status = if session.end_time.is_none() {
                "RUNNING"
            } else {
                "COMPLETED"
            };

            // Placeholder for project name until we join with projects
            let project_str = format!("Project {}", session.project_id);

            let cells = vec![
                Cell::from(date_str).style(Style::default().fg(ColorScheme::TEXT_MAIN)),
                Cell::from(project_str).style(
                    Style::default()
                        .fg(ColorScheme::TEXT_MAIN)
                        .add_modifier(Modifier::BOLD),
                ),
                Cell::from(duration_str).style(Style::default().fg(ColorScheme::TEXT_SECONDARY)),
                Cell::from(start_str).style(Style::default().fg(ColorScheme::TEXT_SECONDARY)),
                Cell::from(end_str).style(Style::default().fg(ColorScheme::TEXT_SECONDARY)),
                Cell::from(status).style(Style::default().fg(if session.end_time.is_none() {
                    ColorScheme::SUCCESS
                } else {
                    ColorScheme::CLEAN_GREEN
                })),
            ];

            Row::new(cells).height(1)
        });

        let table = Table::new(rows)
            .widths(&[
                Constraint::Percentage(15),
                Constraint::Percentage(25),
                Constraint::Percentage(15),
                Constraint::Percentage(15),
                Constraint::Percentage(15),
                Constraint::Percentage(15),
            ])
            .header(header)
            .highlight_style(
                Style::default()
                    .bg(ColorScheme::PANEL_DARK)
                    .add_modifier(Modifier::BOLD),
            );

        f.render_stateful_widget(table, inner_area, &mut self.table_state);
    }

    fn render_details_panel(&self, f: &mut Frame, area: Rect) {
        let block = Block::default()
            .borders(Borders::NONE)
            .style(Style::default().bg(ColorScheme::BG_DARK));

        f.render_widget(block.clone(), area);
        let inner_area = block.inner(area);

        if let Some(selected_index) = self.table_state.selected() {
            if let Some(session) = self.sessions.get(selected_index) {
                let layout = Layout::default()
                    .direction(Direction::Vertical)
                    .constraints([
                        Constraint::Length(2), // Header
                        Constraint::Min(1),    // Content
                    ])
                    .split(inner_area);

                f.render_widget(
                    Paragraph::new("SESSION DETAILS")
                        .style(
                            Style::default()
                                .fg(ColorScheme::TEXT_MAIN)
                                .add_modifier(Modifier::BOLD),
                        )
                        .block(
                            Block::default()
                                .borders(Borders::BOTTOM)
                                .border_style(Style::default().fg(ColorScheme::BORDER_DARK)),
                        ),
                    layout[0],
                );

                let details = vec![
                    Line::from(Span::styled(
                        "NOTES",
                        Style::default()
                            .fg(ColorScheme::TEXT_SECONDARY)
                            .add_modifier(Modifier::BOLD),
                    )),
                    Line::from(Span::styled(
                        session.notes.clone().unwrap_or("No notes".to_string()),
                        Style::default().fg(ColorScheme::TEXT_MAIN),
                    )),
                    Line::from(""),
                    Line::from(Span::styled(
                        "TAGS",
                        Style::default()
                            .fg(ColorScheme::TEXT_SECONDARY)
                            .add_modifier(Modifier::BOLD),
                    )),
                    Line::from(Span::styled(
                        "coding, rust, ui", // Placeholder
                        Style::default().fg(ColorScheme::TEXT_MAIN),
                    )),
                    Line::from(""),
                    Line::from(Span::styled(
                        "CONTEXT",
                        Style::default()
                            .fg(ColorScheme::TEXT_SECONDARY)
                            .add_modifier(Modifier::BOLD),
                    )),
                    Line::from(Span::styled(
                        session.context.to_string(),
                        Style::default().fg(ColorScheme::TEXT_MAIN),
                    )),
                ];

                f.render_widget(
                    Paragraph::new(details)
                        .wrap(ratatui::widgets::Wrap { trim: true })
                        .block(
                            Block::default().padding(ratatui::widgets::Padding::new(1, 1, 1, 1)),
                        ),
                    layout[1],
                );
            }
        } else {
            f.render_widget(
                Paragraph::new("Select a session to view details")
                    .alignment(Alignment::Center)
                    .style(Style::default().fg(ColorScheme::TEXT_SECONDARY)),
                inner_area,
            );
        }
    }

    fn render_footer(&self, f: &mut Frame, area: Rect) {
        let hints = vec![
            Span::styled(
                "[↑/↓]",
                Style::default()
                    .fg(ColorScheme::PRIMARY_DASHBOARD)
                    .add_modifier(Modifier::BOLD),
            ),
            Span::raw(" Navigate  "),
            Span::styled(
                "[F]",
                Style::default()
                    .fg(ColorScheme::PRIMARY_DASHBOARD)
                    .add_modifier(Modifier::BOLD),
            ),
            Span::raw(" Filter  "),
            Span::styled(
                "[Enter]",
                Style::default()
                    .fg(ColorScheme::PRIMARY_DASHBOARD)
                    .add_modifier(Modifier::BOLD),
            ),
            Span::raw(" Details  "),
            Span::styled(
                "[Q]",
                Style::default()
                    .fg(ColorScheme::ERROR)
                    .add_modifier(Modifier::BOLD),
            ),
            Span::raw(" Quit"),
        ];

        f.render_widget(
            Paragraph::new(Line::from(hints))
                .alignment(Alignment::Center)
                .style(Style::default().fg(ColorScheme::TEXT_SECONDARY)),
            area,
        );
    }
}
