// Test code legitimately uses unwrap/expect/panic for assertions and
// fixture setup; the library-level lints are too strict for tests.
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]

//! Parity tests: every doctest from the original Python
//! `slugify_camel_iso` is reproduced here as a Rust unit test.
//!
//! These tests use `slugify_camel_iso_with_year` so the "current year"
//! is pinned to `2019`, matching the doctests' implicit assumption that
//! 2-digit years like `27` parse as 2027 (+10-year rule) and `75` parses
//! as 1975.
//!
//! Tests use `SlugOpts { separator: '_', case: Capitalize }` to match the
//! original Python output exactly.

use fren_date::SlugOpts;
use slug_preserve::CaseMode;

fn legacy_python_opts() -> SlugOpts {
    SlugOpts {
        separator: '_',
        case: CaseMode::Capitalize,
        // Python always split CamelCase. Match that behavior in the
        // parity tests; the new default in Rust is `false` (see the
        // separate test file `camel_case_default.rs`).
        split_camel: true,
    }
}

fn slug(input: &str) -> String {
    fren_date::slugify_camel_iso_with_year(input, &legacy_python_opts(), 2019)
}

// One test per Python doctest line, named after the input shape.

#[test]

fn doctest_basic_iso_year() {
    assert_eq!(
        slug("some name Here 2017_12_30"),
        "Some_Name_Here_2017-12-30"
    );
}

#[test]

fn doctest_dont_pay_bill() {
    assert_eq!(
        slug("DONT_PAY_this-bill-10-05-2015"),
        "Dont_Pay_This_Bill_2015-05-10"
    );
}

#[test]

fn doctest_normal_date_no_dashes() {
    assert_eq!(
        slug("normal DATE 01012019 with no DASHES"),
        "Normal_Date_2019-01-01_With_No_Dashes"
    );
}

#[test]

fn doctest_normal_date_underscores() {
    assert_eq!(
        slug("normal DATE 23_05_2019 with underscores"),
        "Normal_Date_2019-05-23_With_Underscores"
    );
}

#[test]

fn doctest_inverted_date_no_dashes() {
    assert_eq!(
        slug("inverted DATE 20191020 with no DASHES"),
        "Inverted_Date_2019-10-20_With_No_Dashes"
    );
}

#[test]

fn doctest_unicode_scream() {
    assert_eq!(
        slug("blablabla-SCREAM LOUD AGAIN - XXX UTILIZAÇÃO 27.11.17"),
        "Blablabla_Scream_Loud_Again_Xxx_Utilizacao_2017-11-27"
    );
}

#[test]

fn doctest_ata_aug_2_digit_year() {
    assert_eq!(
        slug("something-614 ATA AUG IN 25-04-17"),
        "Something_614_Ata_Aug_In_2017-04-25"
    );
}

#[test]

fn doctest_inverted_datetime() {
    assert_eq!(
        slug("inverted 2017_12_30_10_44_56 bla"),
        "Inverted_2017-12-30T10-44-56_Bla"
    );
}

#[test]

fn doctest_normal_datetime() {
    assert_eq!(
        slug("normal 30.12.2017_10_44_56 bla"),
        "Normal_2017-12-30T10-44-56_Bla"
    );
}

#[test]

fn doctest_no_day_inverted() {
    assert_eq!(slug(" no day inverted 1975 08 "), "No_Day_Inverted_1975-08");
}

#[test]

fn doctest_no_day_normal() {
    assert_eq!(slug(" no day normal 08 1975 "), "No_Day_Normal_1975-08");
}

#[test]

fn doctest_camel_pascal_json_whatsapp() {
    assert_eq!(
        slug(" CamelCase pascalCase JSONfile WhatsApp"),
        "Camel_Case_Pascal_Case_Jsonfile_Whats_App"
    );
}

#[test]

fn doctest_keep_formatted_iso_datetime() {
    assert_eq!(
        slug(" 2019-08-22T16-01-22 keep formatted times "),
        "2019-08-22T16-01-22_Keep_Formatted_Times"
    );
}

#[test]

fn doctest_whatsapp_ptt_at() {
    assert_eq!(
        slug("WhatsApp Ptt 2019-08-21 at 14.24.19"),
        "Whats_App_Ptt_2019-08-21T14-24-19"
    );
}

#[test]

fn doctest_whatsapp_image_already_slugged() {
    assert_eq!(
        slug("Whats_App_Image_2019-08-23_At_12_34_55 fix times on whatsapp files"),
        "Whats_App_Image_2019-08-23T12-34-55_Fix_Times_On_Whatsapp_Files"
    );
}

#[test]

fn doctest_whatsapp_zip() {
    assert_eq!(
        slug("Whats_App_Zip_2019-08-23_At_13_23.36"),
        "Whats_App_Zip_2019-08-23T13-23-36"
    );
}

#[test]

fn doctest_fwd_consulta() {
    assert_eq!(slug("fwdConsultaCognicao"), "Fwd_Consulta_Cognicao");
}

#[test]

fn doctest_unicode_bancarios() {
    assert_eq!(
        slug("bla Bancários - Atenção ble"),
        "Bla_Bancarios_Atencao_Ble"
    );
}

#[test]

fn doctest_two_digit_years_pair() {
    assert_eq!(
        slug(" 240819 human day month year 290875 "),
        "2019-08-24_Human_Day_Month_Year_1975-08-29"
    );
}

#[test]

fn doctest_iso_glued_to_words() {
    assert_eq!(
        slug("2019-08-23T12-48-26words with numbers"),
        "2019-08-23T12-48-26_Words_With_Numbers"
    );
}

#[test]

fn doctest_some_yyyymmdd_underscore_hhmmss() {
    assert_eq!(
        slug("some 20180726_224001 thing"),
        "Some_2018-07-26T22-40-01_Thing"
    );
}

#[test]

fn doctest_glued_ddmmyyyy() {
    assert_eq!(slug("glued14092019"), "Glued_2019-09-14");
}

#[test]

fn doctest_glued_iso_datetime() {
    assert_eq!(
        slug("glued2019-08-23T12-48-26"),
        "Glued_2019-08-23T12-48-26"
    );
}

#[test]

fn doctest_yeah_yyyy_mm() {
    assert_eq!(slug("yeah-1975-08"), "Yeah_1975-08");
}

#[test]

fn doctest_visa_yyyy_mm() {
    assert_eq!(slug("xxx visa-2013-07 yyy"), "Xxx_Visa_2013-07_Yyy");
}

#[test]

fn doctest_date_without_seconds() {
    assert_eq!(
        slug("date without seconds 101020191830 "),
        "Date_Without_Seconds_2019-10-10T18-30-00"
    );
}

#[test]

fn doctest_p2p_b2b_1on1() {
    assert_eq!(
        slug(" p2p b2b 1on1 P2P B2B 1ON1 "),
        "P2p_B2b_1on1_P2p_B2b_1on1"
    );
}

// New format: YYYY_MM_DD_HH_mm (minute precision with separators, no seconds).
// Output should be DateTime with zero seconds appended.
#[test]
fn datetime_iso_minute_only_dashed() {
    assert_eq!(
        slug("note 2026-05-03-18-57 minute only"),
        "Note_2026-05-03T18-57-00_Minute_Only"
    );
}

#[test]
fn datetime_iso_minute_only_human() {
    assert_eq!(
        slug("scan 03-05-2026-18-57 human minute only"),
        "Scan_2026-05-03T18-57-00_Human_Minute_Only"
    );
}

// IMG camera filename: YYYYMMDDHHmmss followed by a sequence number.
// The sequence number must not be consumed as part of the datetime.
#[test]
fn img_datetime_with_sequence_suffix() {
    assert_eq!(
        slug("IMG-20260406-225315-810"),
        "Img_2026-04-06T22-53-15_810"
    );
}

#[test]
fn img_datetime_with_sequence_suffix_variants() {
    assert_eq!(
        slug("IMG-20260409-205656-612"),
        "Img_2026-04-09T20-56-56_612"
    );
    assert_eq!(
        slug("IMG-20260410-212844-572"),
        "Img_2026-04-10T21-28-44_572"
    );
    assert_eq!(
        slug("IMG-20260417-151234-795"),
        "Img_2026-04-17T15-12-34_795"
    );
    assert_eq!(
        slug("IMG-20260422-235305-329"),
        "Img_2026-04-22T23-53-05_329"
    );
}

// Unpadded ISO dates: single-digit month and/or day should be zero-padded.
#[test]
fn unpadded_iso_single_digit_month_and_day() {
    assert_eq!(slug("2026-6-3-RG"), "2026-06-03_Rg");
}

#[test]
fn unpadded_iso_single_digit_month_only() {
    assert_eq!(slug("2026-6-03-RG"), "2026-06-03_Rg");
}

#[test]
fn unpadded_iso_single_digit_day_only() {
    assert_eq!(slug("2026-06-3-RG"), "2026-06-03_Rg");
}

// Unpadded human-ordered dates: DD_M_YYYY, D_M_YYYY, D_MM_YYYY.
// Dashes in source are normalized to underscores by the slug pipeline before date detection.
#[test]
fn unpadded_human_single_digit_month() {
    assert_eq!(slug("blablabla_29_5_2026"), "Blablabla_2026-05-29");
}

#[test]
fn unpadded_human_dashes_single_digit_month() {
    assert_eq!(
        slug("AJDHASKJDHASJK-29-5-2026"),
        "Ajdhaskjdhasjk_2026-05-29"
    );
}

#[test]
fn unpadded_human_single_digit_day_and_month() {
    assert_eq!(slug("blablabla_3_5_2026"), "Blablabla_2026-05-03");
}

#[test]
fn unpadded_human_single_digit_day_only() {
    assert_eq!(slug("blablabla_3_05_2026"), "Blablabla_2026-05-03");
}

// M/D/Y fallback: when D/M interpretation yields an invalid date, fall back to M/D/Y.
// "13_5_2026" as D/M = day 13, month 5 → valid May 13. Stays D/M.
// "5_13_2026" as D/M = day 5, month 13 → invalid → falls back to M/D/Y = May 13.
#[test]
fn unpadded_human_mdy_fallback_when_dmy_invalid() {
    assert_eq!(slug("doc_5_13_2026"), "Doc_2026-05-13");
}

// Both D/M and M/D interpretations invalid (day 13, month 14 either way) → no date detected.
#[test]
fn unpadded_human_both_interpretations_invalid() {
    assert_eq!(slug("doc_13_14_2026"), "Doc_13_14_2026");
}

// Date preceded by an extra numeric token (e.g. "B3" slug → "b3" → "b_3" after
// camel split, but without camel split the "3" bleeds into the date regex match).
// The window scan must find the valid date sub-span within the larger match.
#[test]
fn date_with_leading_numeric_token() {
    assert_eq!(
        slug("XPINC-NOTA-NEGOCIACAO-B3-29-5-2026"),
        "Xpinc_Nota_Negociacao_B_3_2026-05-29"
    );
}

#[test]
fn date_surrounded_by_numeric_tokens() {
    assert_eq!(
        slug("123-456-29-5-2026-111-234"),
        "123_456_2026-05-29_111_234"
    );
}

// Smoke test that runs even without Capitalize: just verify the function
// produces *something* (no panic, no empty string for non-empty input).
#[test]
fn smoke_function_runs_on_basic_input() {
    let out = fren_date::slugify_camel_iso_with_year(
        "Hello World 2024-01-15.txt",
        &SlugOpts::default(),
        2024,
    );
    assert!(!out.is_empty(), "output should not be empty: got {out:?}");
}
