use criterion::{criterion_group, criterion_main, Criterion};
use std::hint::black_box;
use typedialog_core::form_parser::parse_toml;
use typedialog_core::nickel::MetadataParser;

fn benchmark_parse_toml_simple(c: &mut Criterion) {
    let simple_form = r#"
[[fields]]
name = "username"
type = "text"
prompt = "Enter username"

[[fields]]
name = "email"
type = "text"
prompt = "Enter email"
"#;

    c.bench_function("parse_toml_simple", |b| {
        b.iter(|| {
            parse_toml(black_box(simple_form)).unwrap();
        })
    });
}

fn benchmark_parse_toml_complex(c: &mut Criterion) {
    let complex_form = r#"
[[fields]]
name = "username"
type = "text"
prompt = "Enter username"
min = 3
max = 20
required = true

[[fields]]
name = "email"
type = "text"
prompt = "Enter email"
required = true

[[fields]]
name = "password"
type = "password"
prompt = "Enter password"
min = 8
required = true

[[fields]]
name = "role"
type = "select"
prompt = "Select role"
choices = ["Admin", "User", "Guest"]
default = "User"

[[fields]]
name = "permissions"
type = "multiselect"
prompt = "Select permissions"
choices = ["Read", "Write", "Execute", "Delete"]

[[fields]]
name = "bio"
type = "editor"
prompt = "Enter bio"
default = ""

[[fields]]
name = "birthdate"
type = "date"
prompt = "Enter birthdate"

[[fields]]
name = "active"
type = "confirm"
prompt = "Is active?"
default = true
"#;

    c.bench_function("parse_toml_complex", |b| {
        b.iter(|| {
            parse_toml(black_box(complex_form)).unwrap();
        })
    });
}

fn benchmark_parse_toml_nested(c: &mut Criterion) {
    let nested_form = r#"
[[fields]]
name = "server.host"
type = "text"
prompt = "Server hostname"
default = "localhost"

[[fields]]
name = "server.port"
type = "text"
prompt = "Server port"
default = "8080"

[[fields]]
name = "database.host"
type = "text"
prompt = "Database host"

[[fields]]
name = "database.port"
type = "text"
prompt = "Database port"
default = "5432"

[[fields]]
name = "database.name"
type = "text"
prompt = "Database name"
required = true

[[fields]]
name = "tls.enabled"
type = "confirm"
prompt = "Enable TLS?"
default = false

[[fields]]
name = "tls.cert_path"
type = "text"
prompt = "Certificate path"
when = "tls.enabled == true"
"#;

    c.bench_function("parse_toml_nested", |b| {
        b.iter(|| {
            parse_toml(black_box(nested_form)).unwrap();
        })
    });
}

fn benchmark_parse_nickel_simple(c: &mut Criterion) {
    let simple_json = serde_json::json!({
        "username": "alice",
        "email": "alice@example.com"
    });

    c.bench_function("parse_nickel_simple", |b| {
        b.iter(|| {
            MetadataParser::parse(black_box(simple_json.clone())).unwrap();
        })
    });
}

fn benchmark_parse_nickel_complex(c: &mut Criterion) {
    let complex_json = serde_json::json!({
        "user": {
            "name": "Alice",
            "email": "alice@example.com",
            "age": 30
        },
        "settings": {
            "theme": "dark",
            "notifications": true,
            "language": "en"
        },
        "permissions": {
            "read": true,
            "write": true,
            "delete": false
        }
    });

    c.bench_function("parse_nickel_complex", |b| {
        b.iter(|| {
            MetadataParser::parse(black_box(complex_json.clone())).unwrap();
        })
    });
}

fn benchmark_parse_nickel_deeply_nested(c: &mut Criterion) {
    let nested_json = serde_json::json!({
        "server": {
            "http": {
                "host": "localhost",
                "port": 8080,
                "tls": {
                    "enabled": false,
                    "cert_path": "/etc/certs/server.pem",
                    "key_path": "/etc/certs/server.key"
                }
            },
            "database": {
                "primary": {
                    "host": "db1.example.com",
                    "port": 5432,
                    "name": "mydb"
                },
                "replica": {
                    "host": "db2.example.com",
                    "port": 5432,
                    "name": "mydb"
                }
            }
        }
    });

    c.bench_function("parse_nickel_deeply_nested", |b| {
        b.iter(|| {
            MetadataParser::parse(black_box(nested_json.clone())).unwrap();
        })
    });
}

fn benchmark_parse_nickel_with_metadata(c: &mut Criterion) {
    let metadata_json = serde_json::json!({
        "username": {
            "type": "String",
            "doc": "The username for authentication",
            "default": "admin",
            "optional": false
        },
        "email": {
            "type": "String",
            "doc": "Email address",
            "contract": "String | std.string.Email",
            "optional": false
        },
        "age": {
            "type": "Number",
            "doc": "User age",
            "contract": "Number | std.number.between 0 120",
            "optional": true,
            "default": 25
        }
    });

    c.bench_function("parse_nickel_with_metadata", |b| {
        b.iter(|| {
            MetadataParser::parse(black_box(metadata_json.clone())).unwrap();
        })
    });
}

criterion_group!(
    parsing_benches,
    benchmark_parse_toml_simple,
    benchmark_parse_toml_complex,
    benchmark_parse_toml_nested,
    benchmark_parse_nickel_simple,
    benchmark_parse_nickel_complex,
    benchmark_parse_nickel_deeply_nested,
    benchmark_parse_nickel_with_metadata
);

criterion_main!(parsing_benches);
