//! TUI components using ratatui

use crate::app::ViewTab;
use crate::cache::CachedSearch;
use crate::types::{AppState, CheckResult, CheckStatus};
use ratatui::{
    layout::{Alignment, Constraint, Direction, Layout, Rect},
    style::{Color, Modifier, Style},
    text::{Line, Span},
    widgets::{Block, Borders, Cell, Paragraph, Row, Table, TableState, Tabs},
    Frame,
};
use tui_textarea::TextArea;

/// Renders the search panel
pub fn render_search_panel(frame: &mut Frame, area: Rect, search_input: &TextArea, app_state: &AppState, spinner_frame: usize) {
    let spinner_chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧'];
    let spinner = spinner_chars[spinner_frame % spinner_chars.len()];
    
    let (title, border_color) = match app_state {
        AppState::Searching => {
            (format!(" {} Checking domains... ", spinner), Color::Yellow)
        },
        _ => {
            (" Search (Type domain name, Enter to check) ".to_string(), Color::Cyan)
        }
    };

    // Clone textarea to apply styling without mutating
    let mut textarea = search_input.clone();
    
    // Set block styling for textarea with dynamic border color
    textarea.set_block(
        Block::default()
            .title(title.as_str())
            .borders(Borders::ALL)
            .border_style(Style::default().fg(border_color))
    );

    // Set input text style
    textarea.set_style(Style::default().fg(Color::Yellow));

    frame.render_widget(&textarea, area);
}

/// Renders the results table
pub fn render_results_table(
    frame: &mut Frame,
    area: Rect,
    results: &[CheckResult],
    table_state: &mut TableState,
) {
    let header_cells = ["Domain", "TLD", "Status", "Registrar"]
        .iter()
        .map(|h| Cell::from(*h).style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)));
    let header = Row::new(header_cells).height(1).bottom_margin(1);

    let rows = results.iter().map(|result| {
        let status_text = match result.status {
            CheckStatus::Available => "Available",
            CheckStatus::Taken => "Taken",
            CheckStatus::Error => "Error",
        };

        let status_color = match result.status {
            CheckStatus::Available => Color::Green,
            CheckStatus::Taken => Color::Red,
            CheckStatus::Error => Color::Yellow,
        };

        let registrar = result.registrar.clone().unwrap_or_else(|| "-".to_string());

        Row::new(vec![
            Cell::from(result.domain.clone()),
            Cell::from(result.tld.clone()),
            Cell::from(status_text).style(Style::default().fg(status_color).add_modifier(Modifier::BOLD)),
            Cell::from(registrar),
        ])
    });

    let table = Table::new(
        rows,
        [
            Constraint::Percentage(30),
            Constraint::Percentage(15),
            Constraint::Percentage(20),
            Constraint::Percentage(35),
        ],
    )
    .header(header)
    .block(
        Block::default()
            .title(" Results ")
            .borders(Borders::ALL)
            .border_style(Style::default().fg(Color::Cyan)),
    )
    .row_highlight_style(
        Style::default()
            .bg(Color::DarkGray)
            .add_modifier(Modifier::BOLD),
    );

    frame.render_stateful_widget(table, area, table_state);
}

/// Renders the status bar for search view
pub fn render_status_bar(frame: &mut Frame, area: Rect, results_count: usize, expected_results: usize, app_state: &AppState) {
    let status_text = match app_state {
        AppState::Searching if expected_results > 0 => {
            format!("| Checking: {}/{}", results_count, expected_results)
        }
        _ => {
            format!("| Results: {}", results_count)
        }
    };
    
    let shortcuts = vec![
        Span::styled("Enter", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Check  "),
        Span::styled("↑↓", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Navigate  "),
        Span::styled("Tab", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Cache  "),
        Span::styled("Ctrl+X", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Export  "),
        Span::styled("q", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Quit  "),
        Span::raw(status_text),
    ];

    let status = Paragraph::new(Line::from(shortcuts))
        .style(Style::default().bg(Color::DarkGray))
        .alignment(Alignment::Left);

    frame.render_widget(status, area);
}

/// Renders the status bar for cache view
pub fn render_cache_status_bar(frame: &mut Frame, area: Rect, cache_count: usize) {
    let shortcuts = vec![
        Span::styled("↑↓", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Navigate  "),
        Span::styled("←→", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Switch Panel  "),
        Span::styled("x", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Delete  "),
        Span::styled("Shift+D", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Clear All  "),
        Span::styled("Tab", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Search  "),
        Span::styled("q", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
        Span::raw(" Quit  "),
        Span::raw(format!("| Cached: {}", cache_count)),
    ];

    let status = Paragraph::new(Line::from(shortcuts))
        .style(Style::default().bg(Color::DarkGray))
        .alignment(Alignment::Left);

    frame.render_widget(status, area);
}

/// Renders the details panel
pub fn render_details_panel(frame: &mut Frame, area: Rect, result: Option<&CheckResult>) {
    let content = if let Some(result) = result {
        let mut lines = vec![
            Line::from(vec![
                Span::styled("Domain: ", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
                Span::raw(format!("{}.{}", result.domain, result.tld)),
            ]),
            Line::from(vec![
                Span::styled("Status: ", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
                Span::styled(
                    format!("{:?}", result.status),
                    Style::default().fg(match result.status {
                        CheckStatus::Available => Color::Green,
                        CheckStatus::Taken => Color::Red,
                        CheckStatus::Error => Color::Yellow,
                    }),
                ),
            ]),
        ];

        if let Some(ref registrar) = result.registrar {
            lines.push(Line::from(vec![
                Span::styled("Registrar: ", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
                Span::raw(registrar),
            ]));
        }

        if let Some(ref error) = result.error_message {
            lines.push(Line::from(vec![
                Span::styled("Error: ", Style::default().fg(Color::Red).add_modifier(Modifier::BOLD)),
                Span::raw(error),
            ]));
        }

        lines.push(Line::from(""));
        lines.push(Line::from(vec![
            Span::styled("Checked: ", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
            Span::raw(result.checked_at.format("%Y-%m-%d %H:%M:%S").to_string()),
        ]));

        lines
    } else {
        vec![Line::from("No domain selected. Use ↑↓ to navigate and Space to select.")]
    };

    let paragraph = Paragraph::new(content).block(
        Block::default()
            .title(" Details ")
            .borders(Borders::ALL)
            .border_style(Style::default().fg(Color::Cyan)),
    );

    frame.render_widget(paragraph, area);
}

/// Renders the tab bar
pub fn render_tab_bar(frame: &mut Frame, area: Rect, current_tab: &ViewTab) {
    let titles = vec!["Search", "Cache"];
    let selected = match current_tab {
        ViewTab::Search => 0,
        ViewTab::Cache => 1,
    };
    
    let tabs = Tabs::new(titles)
        .block(Block::default().borders(Borders::ALL).title(" Tabs "))
        .select(selected)
        .style(Style::default().fg(Color::Cyan))
        .highlight_style(
            Style::default()
                .fg(Color::Yellow)
                .add_modifier(Modifier::BOLD),
        );
    
    frame.render_widget(tabs, area);
}

/// Creates the main layout
pub fn create_layout(area: Rect) -> Vec<Rect> {
    Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(3),     // Tab bar
            Constraint::Length(3),     // Search panel
            Constraint::Min(10),        // Results table
            Constraint::Length(8),      // Details panel
            Constraint::Length(1),      // Status bar
        ])
        .split(area)
        .to_vec()
}

/// Creates the cache view layout with sidebar
pub fn create_cache_layout(area: Rect) -> Vec<Rect> {
    let vertical = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(3),      // Tab bar
            Constraint::Min(10),        // Main content area
            Constraint::Length(1),      // Status bar
        ])
        .split(area);
    
    // Split main content area into sidebar and center panel
    let horizontal = Layout::default()
        .direction(Direction::Horizontal)
        .constraints([
            Constraint::Percentage(30),  // Left sidebar (cache list)
            Constraint::Percentage(70),  // Center panel (results + details)
        ])
        .split(vertical[1]);
    
    vec![vertical[0], horizontal[0], horizontal[1], vertical[2]]
}

/// Renders the cache sidebar (list of cached searches)
pub fn render_cache_sidebar(
    frame: &mut Frame,
    area: Rect,
    cached_searches: &[CachedSearch],
    table_state: &mut TableState,
) {
    let items: Vec<Line> = cached_searches
        .iter()
        .enumerate()
        .map(|(i, search)| {
            let available = search.available_count();
            let total = search.result_count();
            
            let availability_indicator = if available > 0 {
                format!("✓ {}/{}", available, total)
            } else {
                format!("✗ {}/{}", available, total)
            };
            
            let color = if available > 0 { Color::Green } else { Color::Red };
            
            // Check if this is the selected item
            let is_selected = table_state.selected() == Some(i);
            
            if is_selected {
                Line::from(vec![
                    Span::styled("▶ ", Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD)),
                    Span::styled(&search.query, Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD)),
                    Span::raw(" "),
                    Span::styled(availability_indicator, Style::default().fg(color).add_modifier(Modifier::BOLD)),
                ])
            } else {
                Line::from(vec![
                    Span::raw("  "),
                    Span::styled(&search.query, Style::default().fg(Color::White)),
                    Span::raw(" "),
                    Span::styled(availability_indicator, Style::default().fg(color)),
                ])
            }
        })
        .collect();

    let paragraph = Paragraph::new(items)
        .block(
            Block::default()
                .title(" Search History ")
                .borders(Borders::ALL)
                .border_style(Style::default().fg(Color::Cyan)),
        )
        .scroll((table_state.selected().unwrap_or(0).saturating_sub(area.height.saturating_sub(3) as usize / 2) as u16, 0));

    frame.render_widget(paragraph, area);
}

/// Renders the cache center panel (results table + details)
pub fn render_cache_center_panel(
    frame: &mut Frame,
    area: Rect,
    cached_search: Option<&CachedSearch>,
    selected_result_index: Option<usize>,
) {
    // Split center panel into results table and details
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Percentage(60),  // Results table
            Constraint::Percentage(40),  // Details panel
        ])
        .split(area);

    if let Some(search) = cached_search {
        // Render results table
        let header_cells = ["Domain", "TLD", "Status", "Registrar"]
            .iter()
            .map(|h| Cell::from(*h).style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)));
        let header = Row::new(header_cells).height(1).bottom_margin(1);

        let rows = search.results.iter().map(|result| {
            let status_text = match result.status {
                CheckStatus::Available => "Available",
                CheckStatus::Taken => "Taken",
                CheckStatus::Error => "Error",
            };

            let status_color = match result.status {
                CheckStatus::Available => Color::Green,
                CheckStatus::Taken => Color::Red,
                CheckStatus::Error => Color::Yellow,
            };

            let registrar = result.registrar.clone().unwrap_or_else(|| "-".to_string());

            Row::new(vec![
                Cell::from(result.domain.clone()),
                Cell::from(result.tld.clone()),
                Cell::from(status_text).style(Style::default().fg(status_color).add_modifier(Modifier::BOLD)),
                Cell::from(registrar),
            ])
        });

        let mut table_state = TableState::default();
        table_state.select(selected_result_index);

        let table = Table::new(
            rows,
            [
                Constraint::Percentage(30),
                Constraint::Percentage(15),
                Constraint::Percentage(20),
                Constraint::Percentage(35),
            ],
        )
        .header(header)
        .block(
            Block::default()
                .title(format!(" Results for '{}' ", search.query))
                .borders(Borders::ALL)
                .border_style(Style::default().fg(Color::Cyan)),
        )
        .row_highlight_style(
            Style::default()
                .bg(Color::DarkGray)
                .add_modifier(Modifier::BOLD),
        );

        frame.render_stateful_widget(table, chunks[0], &mut table_state);

        // Render details panel
        let selected_result = selected_result_index.and_then(|i| search.results.get(i));
        render_details_panel(frame, chunks[1], selected_result);
    } else {
        let empty_msg = Paragraph::new("No cached search selected.\n\nUse ↑↓ to navigate the search history.")
            .block(
                Block::default()
                    .title(" Cache Results ")
                    .borders(Borders::ALL)
                    .border_style(Style::default().fg(Color::Cyan)),
            )
            .alignment(Alignment::Center);
        
        frame.render_widget(empty_msg, area);
    }
}

/// Renders the cache details panel (DEPRECATED - use render_cache_center_panel)
#[allow(dead_code)]
pub fn render_cache_details(frame: &mut Frame, area: Rect, cached_search: Option<&CachedSearch>) {
    let content = if let Some(search) = cached_search {
        let mut lines = vec![
            Line::from(vec![
                Span::styled("Query: ", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
                Span::raw(&search.query),
            ]),
            Line::from(vec![
                Span::styled("Searched at: ", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
                Span::raw(search.timestamp.format("%Y-%m-%d %H:%M:%S").to_string()),
            ]),
            Line::from(vec![
                Span::styled("Total results: ", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
                Span::raw(search.result_count().to_string()),
            ]),
            Line::from(vec![
                Span::styled("Available: ", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
                Span::styled(
                    search.available_count().to_string(),
                    Style::default().fg(if search.available_count() > 0 { Color::Green } else { Color::Red }),
                ),
            ]),
            Line::from(""),
            Line::from(vec![
                Span::styled("Results:", Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
            ]),
        ];

        // Show first few available domains
        let available_domains: Vec<_> = search.results.iter()
            .filter(|r| r.status == CheckStatus::Available)
            .take(3)
            .collect();

        for result in available_domains {
            lines.push(Line::from(vec![
                Span::raw("  "),
                Span::styled(
                    format!("{}.{}", result.domain, result.tld),
                    Style::default().fg(Color::Green),
                ),
            ]));
        }

        if search.available_count() > 3 {
            lines.push(Line::from(vec![
                Span::raw("  "),
                Span::styled(
                    format!("...and {} more", search.available_count() - 3),
                    Style::default().fg(Color::DarkGray),
                ),
            ]));
        }

        lines
    } else {
        vec![Line::from("No cache entry selected. Use ↑↓ to navigate.")]
    };

    let paragraph = Paragraph::new(content).block(
        Block::default()
            .title(" Cache Details ")
            .borders(Borders::ALL)
            .border_style(Style::default().fg(Color::Cyan)),
    );

    frame.render_widget(paragraph, area);
}
