use reqwest::Client;
use std::fs;
use tokio;
use serde_json::Value;
use clap::{Parser, Subcommand};

mod typescript_generator;
mod template_engine;
use typescript_generator::TypeScriptGenerator;

#[derive(Parser)]
#[command(name = "apifox-flow")]
#[command(about = "从 Apifox 生成 TypeScript 代码的工具")]
#[command(version = "1.0.0")]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// 生成所有代码（默认行为）
    Generate {
        /// 指定要生成的文件夹名称（可选）
        #[arg(short, long)]
        folder: Option<String>,
        /// 输出目录
        #[arg(short, long, default_value = "generated_by_folders")]
        output: String,
        /// Apifox 项目 ID
        #[arg(short, long, default_value = "162")]
        project_id: String,
        /// Apifox 服务地址
        #[arg(short, long, default_value = "http://127.0.0.1:4523")]
        base_url: String,
        /// 使用模板类型 (default, advanced, react, oboss)
        #[arg(short, long, default_value = "default")]
        template: String,
        /// 自定义模板目录
        #[arg(long)]
        template_dir: Option<String>,
    },
    /// 列出所有可用的文件夹
    ListFolders {
        /// Apifox 项目 ID
        #[arg(short, long, default_value = "162")]
        project_id: String,
        /// Apifox 服务地址
        #[arg(short, long, default_value = "http://127.0.0.1:4523")]
        base_url: String,
    },
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cli = Cli::parse();

    match cli.command {
        Commands::Generate { folder, output, project_id, base_url, template, template_dir } => {
            generate_code(folder, output, project_id, base_url, template, template_dir).await?;
        }
        Commands::ListFolders { project_id, base_url } => {
            list_folders(project_id, base_url).await?;
        }
    }

    Ok(())
}

async fn generate_code(
    folder: Option<String>, 
    output_dir: String, 
    project_id: String, 
    base_url: String,
    template: String,
    template_dir: Option<String>
) -> Result<(), Box<dyn std::error::Error>> {
    let api_url = format!("{}/export/openapi?projectId={}&specialPurpose=openapi-generator", base_url, project_id);
    let output_file = "openapi_doc.json";

    println!("正在从 {} 获取 OpenAPI 文档...", api_url);

    // 1. 创建 HTTP 客户端
    let client = Client::new();

    // 2. 发送 GET 请求
    let response = client.get(&api_url).send().await?;

    // 3. 检查响应状态码并获取文本内容
    if response.status().is_success() {
        let json_content = response.text().await?;

        // 4. 将内容保存到文件
        fs::write(output_file, &json_content)?;
        println!("文档已成功保存到 {} 文件中。", output_file);

        // 5. 解析 JSON 并生成 TypeScript 代码
        let openapi_doc: Value = serde_json::from_str(&json_content)?;
        let mut generator = TypeScriptGenerator::new(&openapi_doc);
        
        // 如果指定了模板目录，则使用模板
        if let Some(ref template_dir) = template_dir {
            generator = generator.with_templates(template_dir)?;
            println!("使用自定义模板目录: {}", template_dir);
        } else if template != "default" {
            // 使用内置模板，尝试多个可能的路径
            let mut template_paths: Vec<String> = vec![
                "templates".to_string(),  // 开发环境
                "./templates".to_string(), // 相对路径
                "../templates".to_string(), // 上级目录
            ];
            
            // 尝试基于可执行文件路径查找模板
            if let Ok(exe_path) = std::env::current_exe() {
                if let Some(exe_dir) = exe_path.parent() {
                    // 在可执行文件目录中查找
                    let exe_templates = exe_dir.join("templates");
                    template_paths.push(exe_templates.to_string_lossy().to_string());
                    
                    // 在可执行文件上级目录中查找
                    if let Some(parent_dir) = exe_dir.parent() {
                        let parent_templates = parent_dir.join("templates");
                        template_paths.push(parent_templates.to_string_lossy().to_string());
                        
                        // 在可执行文件上级的上级目录中查找（项目根目录）
                        if let Some(grandparent_dir) = parent_dir.parent() {
                            let grandparent_templates = grandparent_dir.join("templates");
                            template_paths.push(grandparent_templates.to_string_lossy().to_string());
                        }
                    }
                }
            }
            
            let mut template_found = false;
            for template_path in template_paths {
                if std::path::Path::new(&template_path).exists() {
                    generator = generator.with_templates(&template_path)?;
                    println!("使用内置模板: {} (路径: {})", template, template_path);
                    template_found = true;
                    break;
                }
            }
            
            // 如果找不到文件系统模板，尝试使用嵌入的内置模板
            if !template_found {
                generator = generator.with_templates("builtin")?;
                println!("使用嵌入的内置模板: {}", template);
            }
        }
        
        match folder {
            Some(folder_name) => {
                // 生成指定文件夹的代码
                if template != "default" || template_dir.is_some() {
                    // 使用模板生成
                    if let Err(e) = generator.generate_single_folder_with_template(&folder_name, &output_dir, &template) {
                        println!("错误: {}", e);
                        println!("可用的文件夹列表:");
                        list_available_folders(&generator);
                        return Err(e);
                    }
                } else {
                    // 使用默认方式生成
                    if let Err(e) = generator.generate_single_folder(&folder_name, &output_dir) {
                        println!("错误: {}", e);
                        println!("可用的文件夹列表:");
                        list_available_folders(&generator);
                        return Err(e);
                    }
                }
                println!("文件夹 '{}' 的代码已生成到 {} 目录中。", folder_name, output_dir);
            }
            None => {
                if template != "default" || template_dir.is_some() {
                    // 使用模板生成所有代码
                    generator.generate_by_folders_with_template(&output_dir, &template)?;
                } else {
                    // 生成所有代码（默认方式）
                    generate_all_code(&generator)?;
                    
                    // 按文件夹结构生成分离的 TypeScript 文件
                    generator.generate_by_folders(&output_dir)?;
                }
                println!("按文件夹结构的 TypeScript 代码已生成到 {} 目录中。", output_dir);
            }
        }

    } else {
        println!("请求失败，状态码：{}", response.status());
        println!("错误信息：{}", response.text().await?);
    }

    Ok(())
}

async fn list_folders(project_id: String, base_url: String) -> Result<(), Box<dyn std::error::Error>> {
    let api_url = format!("{}/export/openapi?projectId={}&specialPurpose=openapi-generator", base_url, project_id);
    let output_file = "openapi_doc.json";

    println!("正在从 {} 获取 OpenAPI 文档...", api_url);

    let client = Client::new();
    let response = client.get(&api_url).send().await?;

    if response.status().is_success() {
        let json_content = response.text().await?;
        fs::write(output_file, &json_content)?;
        println!("文档已成功保存到 {} 文件中。", output_file);

        let openapi_doc: Value = serde_json::from_str(&json_content)?;
        let generator = TypeScriptGenerator::new(&openapi_doc);
        
        list_available_folders(&generator);
    } else {
        println!("请求失败，状态码：{}", response.status());
        println!("错误信息：{}", response.text().await?);
    }

    Ok(())
}

fn generate_all_code(generator: &TypeScriptGenerator) -> Result<(), Box<dyn std::error::Error>> {
    // 生成 TypeScript 类型定义
    let types_output = "generated_types.ts";
    generator.save_to_file(types_output)?;
    println!("TypeScript 类型定义已生成到 {} 文件中。", types_output);

    // 生成 API 客户端
    let client_output = "api_client.ts";
    let client_content = generator.generate_api_client();
    fs::write(client_output, client_content)?;
    println!("API 客户端已生成到 {} 文件中。", client_output);

    // 生成完整的 TypeScript 文件
    let full_output = "generated_api.ts";
    let full_content = generator.generate_all();
    fs::write(full_output, full_content)?;
    println!("完整的 TypeScript API 文件已生成到 {} 文件中。", full_output);

    Ok(())
}

fn list_available_folders(generator: &TypeScriptGenerator) {
    println!("\n可用的文件夹列表:");
    println!("==================");
    
    let mut folders: Vec<_> = generator.folder_structure.keys().collect();
    folders.sort();
    
    for (i, folder_name) in folders.iter().enumerate() {
        let path_count = generator.folder_structure.get(*folder_name).map(|v| v.len()).unwrap_or(0);
        println!("{}. {} ({} 个 API 端点)", i + 1, folder_name, path_count);
    }
    
    println!("\n使用方法:");
    println!("cargo run generate --folder \"文件夹名称\"");
    println!("例如: cargo run generate --folder \"Customer Service\"");
}
