use std::path::PathBuf;
use anyhow::{Result, Context};
use crate::dna::mds::init::ProjectManifest;
use serde::{Serialize, Deserialize};
use serde_json;
use serde_yaml;
use toml;
use chrono;


pub fn export_project(
    format: String,
    output: Option<PathBuf>,
    include_deps: bool,
    verbose: bool,
) -> Result<()> {
    let project_dir = find_project_root()?;
    if verbose {
        println!("📤 Exporting HELIX project:");
        println!("  Project: {}", project_dir.display());
        println!("  Format: {}", format);
        println!("  Include dependencies: {}", include_deps);
    }
    match format.as_str() {
        "json" => export_to_json(&project_dir, output, include_deps, verbose)?,
        "yaml" => export_to_yaml(&project_dir, output, include_deps, verbose)?,
        "toml" => export_to_toml(&project_dir, output, include_deps, verbose)?,
        "docker" => export_to_docker(&project_dir, output, verbose)?,
        "k8s" => export_to_kubernetes(&project_dir, output, verbose)?,
        _ => {
            return Err(
                anyhow::anyhow!(
                    "Unknown export format '{}'. Available formats: json, yaml, toml, docker, k8s",
                    format
                ),
            );
        }
    }
    println!("✅ Export completed successfully!");
    Ok(())
}
pub fn import_project(
    input: PathBuf,
    format: Option<String>,
    force: bool,
    verbose: bool,
) -> Result<()> {
    if verbose {
        println!("📥 Importing HELIX project:");
        println!("  Input: {}", input.display());
        println!("  Format: {}", format.as_deref().unwrap_or("auto-detect"));
    }
    if !input.exists() {
        return Err(anyhow::anyhow!("Input file not found: {}", input.display()));
    }
    let detected_format = format
        .unwrap_or_else(|| {
            if let Some(extension) = input.extension().and_then(|ext| ext.to_str()) {
                match extension {
                    "json" => "json".to_string(),
                    "yaml" | "yml" => "yaml".to_string(),
                    "toml" => "toml".to_string(),
                    _ => "json".to_string(),
                }
            } else {
                "json".to_string()
            }
        });
    match detected_format.as_str() {
        "json" => import_from_json(&input, force, verbose)?,
        "yaml" => import_from_yaml(&input, force, verbose)?,
        "toml" => import_from_toml(&input, force, verbose)?,
        _ => {
            return Err(
                anyhow::anyhow!("Unsupported import format: {}", detected_format),
            );
        }
    }
    println!("✅ Import completed successfully!");
    Ok(())
}
pub fn export_to_json(
    project_dir: &PathBuf,
    output: Option<PathBuf>,
    include_deps: bool,
    verbose: bool,
) -> Result<()> {
    let manifest = read_project_manifest(project_dir)?;
    let source_files = collect_source_files(project_dir)?;
    let export_data = ExportData {
        manifest,
        source_files,
        dependencies: if include_deps {
            Some(collect_dependencies(project_dir)?)
        } else {
            None
        },
        metadata: ExportMetadata {
            exported_at: chrono::Utc::now().to_rfc3339(),
            format_version: "1.0".to_string(),
            tool_version: env!("CARGO_PKG_VERSION").to_string(),
        },
    };
    let json_content = serde_json::to_string_pretty(&export_data)
        .context("Failed to serialize to JSON")?;
    let output_path = output.unwrap_or_else(|| project_dir.join("export.json"));
    std::fs::write(&output_path, json_content).context("Failed to write JSON export")?;
    if verbose {
        println!("  ✅ Exported to: {}", output_path.display());
    }
    Ok(())
}
pub fn export_to_yaml(
    project_dir: &PathBuf,
    output: Option<PathBuf>,
    include_deps: bool,
    verbose: bool,
) -> Result<()> {
    let manifest = read_project_manifest(project_dir)?;
    let source_files = collect_source_files(project_dir)?;
    let export_data = ExportData {
        manifest,
        source_files,
        dependencies: if include_deps {
            Some(collect_dependencies(project_dir)?)
        } else {
            None
        },
        metadata: ExportMetadata {
            exported_at: chrono::Utc::now().to_rfc3339(),
            format_version: "1.0".to_string(),
            tool_version: env!("CARGO_PKG_VERSION").to_string(),
        },
    };
    let yaml_content = serde_yaml::to_string(&export_data)
        .context("Failed to serialize to YAML")?;
    let output_path = output.unwrap_or_else(|| project_dir.join("export.yaml"));
    std::fs::write(&output_path, yaml_content).context("Failed to write YAML export")?;
    if verbose {
        println!("  ✅ Exported to: {}", output_path.display());
    }
    Ok(())
}
pub fn export_to_toml(
    project_dir: &PathBuf,
    output: Option<PathBuf>,
    include_deps: bool,
    verbose: bool,
) -> Result<()> {
    let manifest = read_project_manifest(project_dir)?;
    let toml_content = toml::to_string_pretty(&manifest)
        .context("Failed to serialize to TOML")?;
    let output_path = output.unwrap_or_else(|| project_dir.join("export.toml"));
    std::fs::write(&output_path, toml_content).context("Failed to write TOML export")?;
    if verbose {
        println!("  ✅ Exported to: {}", output_path.display());
        if include_deps {
            println!("  Note: Dependencies not yet supported in TOML export");
        }
    }
    Ok(())
}
pub fn export_to_docker(
    project_dir: &PathBuf,
    output: Option<PathBuf>,
    verbose: bool,
) -> Result<()> {
    let manifest = read_project_manifest(project_dir)?;
    let dockerfile_content = format!(
        r#"# Dockerfile for HELIX project: {}
FROM ubuntu:22.04

# Install hlx runtime
RUN apt-get update && apt-get install -y \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Install hlx compiler
RUN curl -sSL https://get.helix.cm/install.sh | bash

# Set working directory
WORKDIR /app

# Copy project files
COPY . .

# Build the project
RUN helix build

# Expose port
EXPOSE 8080

# Run the project
CMD ["helix", "run"]
"#,
        manifest.name
    );
    let output_path = output.unwrap_or_else(|| project_dir.join("Dockerfile"));
    std::fs::write(&output_path, dockerfile_content)
        .context("Failed to write Dockerfile")?;
    if verbose {
        println!("  ✅ Exported to: {}", output_path.display());
    }
    Ok(())
}
pub fn export_to_kubernetes(
    project_dir: &PathBuf,
    output: Option<PathBuf>,
    verbose: bool,
) -> Result<()> {
    let manifest = read_project_manifest(project_dir)?;
    let k8s_content = format!(
        r#"apiVersion: apps/v1
kind: Deployment
metadata:
  name: {}-deployment
  labels:
    app: {}
spec:
  replicas: 3
  selector:
    matchLabels:
      app: {}
  template:
    metadata:
      labels:
        app: {}
    spec:
      containers:
      - name: {}
        image: {}:latest
        ports:
        - containerPort: 8080
        env:
        - name: hlx_ENV
          value: "production"
---
apiVersion: v1
kind: Service
metadata:
  name: {}-service
spec:
  selector:
    app: {}
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: LoadBalancer
"#,
        manifest.name, manifest.name, manifest.name, manifest
        .name, manifest.name, manifest.name, manifest
        .name, manifest.name
    );
    let output_path = output.unwrap_or_else(|| project_dir.join("k8s.yaml"));
    std::fs::write(&output_path, k8s_content)
        .context("Failed to write Kubernetes manifest")?;
    if verbose {
        println!("  ✅ Exported to: {}", output_path.display());
    }
    Ok(())
}
pub fn import_from_json(input: &PathBuf, force: bool, verbose: bool) -> Result<()> {
    let content = std::fs::read_to_string(input).context("Failed to read input file")?;
    let export_data: ExportData = serde_json::from_str(&content)
        .context("Failed to parse JSON")?;
    import_export_data(export_data, force, verbose)
}
pub fn import_from_yaml(input: &PathBuf, force: bool, verbose: bool) -> Result<()> {
    let content = std::fs::read_to_string(input).context("Failed to read input file")?;
    let export_data: ExportData = serde_yaml::from_str(&content)
        .context("Failed to parse YAML")?;
    import_export_data(export_data, force, verbose)
}
pub fn import_from_toml(input: &PathBuf, force: bool, verbose: bool) -> Result<()> {
    let content = std::fs::read_to_string(input).context("Failed to read input file")?;
    let manifest: ProjectManifest = toml::from_str(&content)
        .context("Failed to parse TOML")?;
    let export_data = ExportData {
        manifest,
        source_files: std::collections::HashMap::new(),
        dependencies: None,
        metadata: ExportMetadata {
            exported_at: chrono::Utc::now().to_rfc3339(),
            format_version: "1.0".to_string(),
            tool_version: env!("CARGO_PKG_VERSION").to_string(),
        },
    };
    import_export_data(export_data, force, verbose)
}
pub fn import_export_data(
    export_data: ExportData,
    force: bool,
    verbose: bool,
) -> Result<()> {
    let project_dir = std::env::current_dir()
        .context("Failed to get current directory")?;
    let manifest_path = project_dir.join("project.hlx");
    if manifest_path.exists() && !force {
        return Err(anyhow::anyhow!("Project already exists. Use --force to overwrite."));
    }
    std::fs::create_dir_all(project_dir.join("src"))
        .context("Failed to create src directory")?;
    let manifest_content = toml::to_string_pretty(&export_data.manifest)
        .context("Failed to serialize manifest")?;
    std::fs::write(&manifest_path, manifest_content)
        .context("Failed to write manifest")?;
    let source_files_count = export_data.source_files.len();
    for (filename, content) in export_data.source_files {
        let file_path = project_dir.join("src").join(filename);
        std::fs::write(&file_path, content).context("Failed to write source file")?;
    }
    if verbose {
        println!("  ✅ Imported {} source files", source_files_count);
    }
    Ok(())
}
#[derive(Debug, Serialize, Deserialize)]
struct ExportData {
    manifest: ProjectManifest,
    source_files: std::collections::HashMap<String, String>,
    dependencies: Option<std::collections::HashMap<String, String>>,
    metadata: ExportMetadata,
}
#[derive(Debug, Serialize, Deserialize)]
struct ExportMetadata {
    exported_at: String,
    format_version: String,
    tool_version: String,
}
pub fn read_project_manifest(
    project_dir: &PathBuf,
) -> Result<ProjectManifest> {
    let manifest_path = project_dir.join("project.hlx");
    if !manifest_path.exists() {
        return Err(
            anyhow::anyhow!(
                "No project.hlx found. Run 'helix init' first to create a project."
            ),
        );
    }
    let content = std::fs::read_to_string(&manifest_path)
        .context("Failed to read project.hlx")?;
    let project_name = extract_project_name(&content)?;
    let version = extract_project_version(&content)?;
    let manifest = ProjectManifest {
        name: project_name,
        version,
        description: Some("HELIX project".to_string()),
        author: Some("HELIX Developer".to_string()),
        license: Some("MIT".to_string()),
        repository: None,
        created: Some(chrono::Utc::now().format("%Y-%m-%d").to_string()),
    };
    Ok(manifest)
}
pub fn collect_source_files(
    project_dir: &PathBuf,
) -> Result<std::collections::HashMap<String, String>> {
    let mut files = std::collections::HashMap::new();
    let src_dir = project_dir.join("src");
    if src_dir.exists() {
        collect_helix_files(&src_dir, &mut files)?;
    }
    Ok(files)
}
pub fn collect_helix_files(
    dir: &PathBuf,
    files: &mut std::collections::HashMap<String, String>,
) -> Result<()> {
    let entries = std::fs::read_dir(dir).context("Failed to read directory")?;
    for entry in entries {
        let entry = entry.context("Failed to read directory entry")?;
        let path = entry.path();
        if path.is_file() {
            if let Some(extension) = path.extension() {
                if extension == "hlx" {
                    let filename = path
                        .file_name()
                        .and_then(|n| n.to_str())
                        .ok_or_else(|| anyhow::anyhow!("Invalid filename"))?;
                    let content = std::fs::read_to_string(&path)
                        .context("Failed to read file")?;
                    files.insert(filename.to_string(), content);
                }
            }
        } else if path.is_dir() {
            collect_helix_files(&path, files)?;
        }
    }
    Ok(())
}
pub fn collect_dependencies(
    _project_dir: &PathBuf,
) -> Result<std::collections::HashMap<String, String>> {
    Ok(std::collections::HashMap::new())
}
pub fn extract_project_name(content: &str) -> Result<String> {
    for line in content.lines() {
        let trimmed = line.trim();
        if trimmed.starts_with("project \"") {
            if let Some(start) = trimmed.find('"') {
                if let Some(end) = trimmed[start + 1..].find('"') {
                    return Ok(trimmed[start + 1..start + 1 + end].to_string());
                }
            }
        }
    }
    Err(anyhow::anyhow!("Could not find project name in HELIX file"))
}
pub fn extract_project_version(content: &str) -> Result<String> {
    for line in content.lines() {
        let trimmed = line.trim();
        if trimmed.starts_with("version = \"") {
            if let Some(start) = trimmed.find('"') {
                if let Some(end) = trimmed[start + 1..].find('"') {
                    return Ok(trimmed[start + 1..start + 1 + end].to_string());
                }
            }
        }
    }
    Ok("0.1.0".to_string())
}
pub fn find_project_root() -> Result<PathBuf> {
    let mut current_dir = std::env::current_dir()
        .context("Failed to get current directory")?;
    loop {
        let manifest_path = current_dir.join("project.hlx");
        if manifest_path.exists() {
            return Ok(current_dir);
        }
        if let Some(parent) = current_dir.parent() {
            current_dir = parent.to_path_buf();
        } else {
            break;
        }
    }
    Err(anyhow::anyhow!("No HELIX project found. Run 'helix init' first."))
}