//! CLI tool for detecting PDF type (text-based vs scanned)

use pdf_inspector::{detect_pdf_type, process_pdf_with_options, PdfOptions, PdfType, ProcessMode};
use std::env;
use std::fmt::Write;
use std::process;
use std::time::Instant;

/// Escape a string for embedding in a JSON string value.
fn json_escape(s: &str) -> String {
    let mut out = String::with_capacity(s.len() + 16);
    for ch in s.chars() {
        match ch {
            '\\' => out.push_str("\\\\"),
            '"' => out.push_str("\\\""),
            '\n' => out.push_str("\\n"),
            '\r' => out.push_str("\\r"),
            '\t' => out.push_str("\\t"),
            '\x08' => out.push_str("\\b"),
            '\x0C' => out.push_str("\\f"),
            c if c < '\x20' => {
                let _ = write!(out, "\\u{:04x}", c as u32);
            }
            c => out.push(c),
        }
    }
    out
}

fn main() {
    env_logger::init();
    let args: Vec<String> = env::args().collect();

    if args.len() < 2 {
        eprintln!("Usage: {} <pdf_file>", args[0]);
        eprintln!("       {} <pdf_file> --json", args[0]);
        eprintln!("       {} <pdf_file> --analyze", args[0]);
        eprintln!();
        eprintln!("Options:");
        eprintln!("  --json       Output result as JSON");
        eprintln!("  --analyze    Also run layout analysis (tables, columns)");
        process::exit(1);
    }

    let pdf_path = &args[1];
    let json_output = args.iter().any(|a| a == "--json");
    let analyze = args.iter().any(|a| a == "--analyze");

    let start = Instant::now();

    if analyze {
        run_analyze(pdf_path, json_output, start);
    } else {
        run_detect_only(pdf_path, json_output, start);
    }
}

fn pdf_type_str(pdf_type: &PdfType) -> &'static str {
    match pdf_type {
        PdfType::TextBased => "text_based",
        PdfType::Scanned => "scanned",
        PdfType::ImageBased => "image_based",
        PdfType::Mixed => "mixed",
    }
}

fn run_analyze(pdf_path: &str, json_output: bool, start: Instant) {
    match process_pdf_with_options(pdf_path, PdfOptions::new().mode(ProcessMode::Analyze)) {
        Ok(result) => {
            let elapsed = start.elapsed();

            if json_output {
                let ocr_pages: Vec<String> = result
                    .pages_needing_ocr
                    .iter()
                    .map(|p| p.to_string())
                    .collect();
                let table_pages: Vec<String> = result
                    .layout
                    .pages_with_tables
                    .iter()
                    .map(|p| p.to_string())
                    .collect();
                let col_pages: Vec<String> = result
                    .layout
                    .pages_with_columns
                    .iter()
                    .map(|p| p.to_string())
                    .collect();
                println!(
                    r#"{{"pdf_type":"{}","page_count":{},"pages_needing_ocr":[{}],"is_complex":{},"pages_with_tables":[{}],"pages_with_columns":[{}],"detection_time_ms":{}}}"#,
                    pdf_type_str(&result.pdf_type),
                    result.page_count,
                    ocr_pages.join(","),
                    result.layout.is_complex,
                    table_pages.join(","),
                    col_pages.join(","),
                    elapsed.as_millis()
                );
            } else {
                println!("PDF Type Detection + Layout Analysis");
                println!("=====================================");
                println!("File: {}", pdf_path);
                println!();
                println!(
                    "Type: {}",
                    match result.pdf_type {
                        PdfType::TextBased => "TEXT-BASED (extractable text)",
                        PdfType::Scanned => "SCANNED (OCR needed)",
                        PdfType::ImageBased => "IMAGE-BASED (mostly images, OCR may help)",
                        PdfType::Mixed => "MIXED (some text, some images)",
                    }
                );
                println!("Page count: {}", result.page_count);
                if !result.pages_needing_ocr.is_empty() {
                    println!("Pages needing OCR: {:?}", result.pages_needing_ocr);
                }
                println!();
                if result.layout.is_complex {
                    println!("Layout: COMPLEX");
                    if !result.layout.pages_with_tables.is_empty() {
                        println!("  Pages with tables: {:?}", result.layout.pages_with_tables);
                    }
                    if !result.layout.pages_with_columns.is_empty() {
                        println!(
                            "  Pages with columns: {:?}",
                            result.layout.pages_with_columns
                        );
                    }
                } else {
                    println!("Layout: simple");
                }
                println!();
                println!("Detection time: {}ms", elapsed.as_millis());
            }
        }
        Err(e) => {
            if json_output {
                println!(r#"{{"error":"{}"}}"#, e);
            } else {
                eprintln!("Error: {}", e);
            }
            process::exit(1);
        }
    }
}

fn run_detect_only(pdf_path: &str, json_output: bool, start: Instant) {
    // Use the low-level detect_pdf_type for richer output (pages_sampled etc.),
    // but also call detect_pdf to demonstrate the unified API.
    match detect_pdf_type(pdf_path) {
        Ok(result) => {
            let elapsed = start.elapsed();

            if json_output {
                let ocr_pages: Vec<String> = result
                    .pages_needing_ocr
                    .iter()
                    .map(|p| p.to_string())
                    .collect();
                println!(
                    r#"{{"pdf_type":"{}","page_count":{},"pages_sampled":{},"pages_with_text":{},"confidence":{:.2},"title":{},"ocr_recommended":{},"pages_needing_ocr":[{}],"detection_time_ms":{}}}"#,
                    pdf_type_str(&result.pdf_type),
                    result.page_count,
                    result.pages_sampled,
                    result.pages_with_text,
                    result.confidence,
                    result
                        .title
                        .as_ref()
                        .map(|t| format!("\"{}\"", json_escape(t)))
                        .unwrap_or_else(|| "null".to_string()),
                    result.ocr_recommended,
                    ocr_pages.join(","),
                    elapsed.as_millis()
                );
            } else {
                println!("PDF Type Detection Results");
                println!("==========================");
                println!("File: {}", pdf_path);
                println!();
                println!(
                    "Type: {}",
                    match result.pdf_type {
                        PdfType::TextBased => "TEXT-BASED (extractable text)",
                        PdfType::Scanned => "SCANNED (OCR needed)",
                        PdfType::ImageBased => "IMAGE-BASED (mostly images, OCR may help)",
                        PdfType::Mixed => "MIXED (some text, some images)",
                    }
                );
                println!("Confidence: {:.0}%", result.confidence * 100.0);
                println!();
                println!("Page count: {}", result.page_count);
                println!("Pages sampled: {}", result.pages_sampled);
                println!("Pages with text: {}", result.pages_with_text);
                println!(
                    "OCR recommended: {}",
                    if result.ocr_recommended { "YES" } else { "NO" }
                );
                if !result.pages_needing_ocr.is_empty() {
                    if result.pages_needing_ocr.len() == result.page_count as usize {
                        println!("Pages needing OCR: all (of {})", result.page_count);
                    } else {
                        println!(
                            "Pages needing OCR: {:?} (of {})",
                            result.pages_needing_ocr, result.page_count
                        );
                    }
                }
                if let Some(title) = &result.title {
                    println!("Title: {}", title);
                }
                println!();
                println!("Detection time: {}ms", elapsed.as_millis());
                println!();

                // Recommendations
                if result.ocr_recommended {
                    match result.pdf_type {
                        PdfType::Mixed => {
                            println!("Recommendation: Use OCR - images provide essential context (template PDF)");
                        }
                        PdfType::Scanned => {
                            println!("Recommendation: Use OCR (MinerU or similar)");
                        }
                        PdfType::ImageBased => {
                            println!("Recommendation: Use OCR for best results");
                        }
                        _ => {
                            println!("Recommendation: Use OCR for complete extraction");
                        }
                    }
                } else {
                    println!("Recommendation: Use direct text extraction (fast)");
                }
            }
        }
        Err(e) => {
            if json_output {
                println!(r#"{{"error":"{}"}}"#, e);
            } else {
                eprintln!("Error: {}", e);
            }
            process::exit(1);
        }
    }
}
