#![allow(clippy::result_large_err)]

//! typedialog-tui - Terminal UI tool for interactive forms
//!
//! A terminal UI (TUI) tool for creating interactive forms with enhanced visual presentation.
//! Uses ratatui for advanced terminal rendering capabilities.

mod commands;

use clap::{Parser, Subcommand};
use std::path::PathBuf;
use typedialog_core::cli_common;
use typedialog_core::config::load_backend_config;
use typedialog_core::prelude::*;

#[derive(Parser)]
#[command(
    name = "typedialog-tui",
    version,
    about = "Terminal UI tool for interactive forms",
    long_about = cli_common::TUI_MAIN_LONG_ABOUT
)]
struct Args {
    #[command(subcommand)]
    command: Option<Commands>,

    /// TUI backend configuration file (TOML)
    ///
    /// If provided, uses this file exclusively.
    /// If not provided, searches: ~/.config/typedialog/tui/{TYPEDIALOG_ENV}.toml → ~/.config/typedialog/tui/config.toml → defaults
    #[arg(global = true, short = 'c', long, value_name = "FILE")]
    backend_config: Option<PathBuf>,

    /// Path to TOML form configuration file (for default form command)
    config: Option<PathBuf>,

    /// Output format: json, yaml, toml, or text
    #[arg(short, long, default_value = "text", help = cli_common::FORMAT_FLAG_HELP)]
    format: String,

    /// Output file (if not specified, writes to stdout)
    #[arg(short, long, help = cli_common::OUT_FLAG_HELP)]
    out: Option<PathBuf>,

    /// Locale override for form localization
    #[arg(short, long, help = cli_common::LOCALE_FLAG_HELP)]
    locale: Option<String>,
}

#[derive(Subcommand)]
enum Commands {
    /// Execute interactive form from TOML configuration
    Form {
        /// Path to TOML form configuration file
        config: PathBuf,

        /// Path to JSON file with default field values
        #[arg(long)]
        defaults: Option<PathBuf>,
    },

    /// Convert Nickel schema to TOML form
    #[command(name = "nickel-to-form")]
    NickelToForm {
        /// Path to Nickel schema file (.ncl)
        schema: PathBuf,

        /// Optional path to current data file (.ncl or .json) for defaults
        #[arg(value_name = "CURRENT_DATA")]
        current_data: Option<PathBuf>,

        /// Flatten nested records into flat field names
        #[arg(long)]
        flatten: bool,

        /// Use semantic grouping for form organization
        #[arg(long)]
        groups: bool,

        /// Generate fragments for large schemas based on @fragment markers
        #[arg(long)]
        fragments: bool,

        /// Generate conditionals from optional fields and boolean dependencies
        #[arg(long)]
        conditionals: bool,

        /// Extract i18n translations from doc comments
        #[arg(long)]
        i18n: bool,

        /// Output directory for generated forms (default: stdout for single file)
        #[arg(long)]
        output: Option<PathBuf>,
    },

    /// Convert form results to Nickel output
    #[command(name = "form-to-nickel")]
    FormToNickel {
        /// Path to TOML form definition
        form: PathBuf,

        /// Path to results JSON file OR Nickel template (.ncl.j2)
        /// - If .json: Read pre-computed results (3-step workflow)
        /// - If .ncl.j2: Execute form + render template (2-step workflow)
        input: PathBuf,

        /// Validate output with nickel typecheck
        #[arg(long)]
        validate: bool,
    },

    /// Render Nickel template with form results
    #[command(name = "nickel-template")]
    NickelTemplate {
        /// Path to Nickel template file (.ncl.j2)
        template: PathBuf,

        /// Path to results JSON file
        results: PathBuf,
    },

    /// Complete roundtrip: .ncl → form → .ncl with preserved validators
    #[command(name = "nickel-roundtrip")]
    NickelRoundtrip {
        /// Path to input Nickel file (.ncl)
        input: PathBuf,

        /// Path to form definition (.toml)
        form: PathBuf,

        /// Path to output Nickel file (.ncl)
        #[arg(long)]
        output: PathBuf,

        /// Optional Tera template file (.ncl.j2) for rendering output
        #[arg(long)]
        ncl_template: Option<PathBuf>,

        /// Disable validation with nickel typecheck
        #[arg(long)]
        no_validate: bool,

        /// Print verbose progress messages
        #[arg(short, long)]
        verbose: bool,
    },
}

#[tokio::main]
async fn main() -> Result<()> {
    // Initialize tracing subscriber with env filter (respects RUST_LOG)
    tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
        )
        .init();

    let args = Args::parse();

    // Load configuration with CLI override
    let config_path = args.backend_config.as_deref();
    let _config =
        load_backend_config::<TypeDialogConfig>("tui", config_path, TypeDialogConfig::default())?;

    if let Some(path) = config_path {
        eprintln!("📋 Using config: {}", path.display());
    }

    match args.command {
        Some(Commands::Form { config, defaults }) => {
            commands::execute_form(config, defaults, &args.format, &args.out, &args.locale).await?;
        }
        Some(Commands::NickelToForm {
            schema,
            current_data,
            flatten,
            groups,
            fragments,
            conditionals,
            i18n,
            output,
        }) => {
            commands::nickel_to_form_cmd(
                schema,
                current_data,
                flatten,
                groups,
                fragments,
                conditionals,
                i18n,
                output,
            )?;
        }
        Some(Commands::FormToNickel {
            form,
            input,
            validate,
        }) => {
            commands::form_to_nickel_cmd(form, input, &args.out, validate)?;
        }
        Some(Commands::NickelTemplate { template, results }) => {
            commands::nickel_template_cmd(template, results, &args.out)?;
        }
        Some(Commands::NickelRoundtrip {
            input,
            form,
            output,
            ncl_template,
            no_validate,
            verbose,
        }) => {
            commands::nickel_roundtrip_cmd(
                input,
                form,
                output,
                ncl_template,
                !no_validate,
                verbose,
            )
            .await?;
        }
        None => {
            let config = args.config.ok_or_else(|| {
                Error::validation_failed("Please provide a form configuration file")
            })?;
            commands::execute_form(config, None, &args.format, &args.out, &args.locale).await?;
        }
    }

    Ok(())
}
