                    "indiana" => Ok(Self::IN),
                    "iowa" => Ok(Self::IA),
                    "kansas" => Ok(Self::KS),
                    "kentucky" => Ok(Self::KY),
                    "louisiana" => Ok(Self::LA),
                    "maine" => Ok(Self::ME),
                    "marshall islands" => Ok(Self::MH),
                    "maryland" => Ok(Self::MD),
                    "massachusetts" => Ok(Self::MA),
                    "michigan" => Ok(Self::MI),
                    "minnesota" => Ok(Self::MN),
                    "mississippi" => Ok(Self::MS),
                    "missouri" => Ok(Self::MO),
                    "montana" => Ok(Self::MT),
                    "nebraska" => Ok(Self::NE),
                    "nevada" => Ok(Self::NV),
                    "new hampshire" => Ok(Self::NH),
                    "new jersey" => Ok(Self::NJ),
                    "new mexico" => Ok(Self::NM),
                    "new york" => Ok(Self::NY),
                    "north carolina" => Ok(Self::NC),
                    "north dakota" => Ok(Self::ND),
                    "northern mariana islands" => Ok(Self::MP),
                    "ohio" => Ok(Self::OH),
                    "oklahoma" => Ok(Self::OK),
                    "oregon" => Ok(Self::OR),
                    "palau" => Ok(Self::PW),
                    "pennsylvania" => Ok(Self::PA),
                    "puerto rico" => Ok(Self::PR),
                    "rhode island" => Ok(Self::RI),
                    "south carolina" => Ok(Self::SC),
                    "south dakota" => Ok(Self::SD),
                    "tennessee" => Ok(Self::TN),
                    "texas" => Ok(Self::TX),
                    "utah" => Ok(Self::UT),
                    "vermont" => Ok(Self::VT),
                    "virgin islands" => Ok(Self::VI),
                    "virginia" => Ok(Self::VA),
                    "washington" => Ok(Self::WA),
                    "west virginia" => Ok(Self::WV),
                    "wisconsin" => Ok(Self::WI),
                    "wyoming" => Ok(Self::WY),
                    _ => Err(errors::ConnectorError::InvalidDataFormat {
                        field_name: "address.state",
                    }
                    .into()),
                }
            }
        }
    }
}

impl ForeignTryFrom<String> for CanadaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.to_uppercase().clone(), "CanadaStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => {
                let binding = value.as_str().to_lowercase();
                let state = binding.as_str();
                match state {
                    "alberta" => Ok(Self::AB),
                    "british columbia" => Ok(Self::BC),
                    "manitoba" => Ok(Self::MB),
                    "new brunswick" => Ok(Self::NB),
                    "newfoundland and labrador" | "newfoundland & labrador" => Ok(Self::NL),
                    "northwest territories" => Ok(Self::NT),
                    "nova scotia" => Ok(Self::NS),
                    "nunavut" => Ok(Self::NU),
                    "ontario" => Ok(Self::ON),
                    "prince edward island" => Ok(Self::PE),
                    "quebec" => Ok(Self::QC),
                    "saskatchewan" => Ok(Self::SK),
                    "yukon" => Ok(Self::YT),
                    _ => Err(errors::ConnectorError::InvalidDataFormat {
                        field_name: "address.state",
                    }
                    .into()),
                }
            }
        }
    }
}

impl ForeignTryFrom<String> for PolandStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "PolandStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Greater Poland" => Ok(Self::GreaterPoland),
                "Holy Cross" => Ok(Self::HolyCross),
                "Kuyavia-Pomerania" => Ok(Self::KuyaviaPomerania),
                "Lesser Poland" => Ok(Self::LesserPoland),
                "Lower Silesia" => Ok(Self::LowerSilesia),
                "Lublin" => Ok(Self::Lublin),
                "Lubusz" => Ok(Self::Lubusz),
                "Łódź" => Ok(Self::Łódź),
                "Mazovia" => Ok(Self::Mazovia),
                "Podlaskie" => Ok(Self::Podlaskie),
                "Pomerania" => Ok(Self::Pomerania),
                "Silesia" => Ok(Self::Silesia),
                "Subcarpathia" => Ok(Self::Subcarpathia),
                "Upper Silesia" => Ok(Self::UpperSilesia),
                "Warmia-Masuria" => Ok(Self::WarmiaMasuria),
                "West Pomerania" => Ok(Self::WestPomerania),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for FranceStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "FranceStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Ain" => Ok(Self::Ain),
                "Aisne" => Ok(Self::Aisne),
                "Allier" => Ok(Self::Allier),
                "Alpes-de-Haute-Provence" => Ok(Self::AlpesDeHauteProvence),
                "Alpes-Maritimes" => Ok(Self::AlpesMaritimes),
                "Alsace" => Ok(Self::Alsace),
                "Ardèche" => Ok(Self::Ardeche),
                "Ardennes" => Ok(Self::Ardennes),
                "Ariège" => Ok(Self::Ariege),
                "Aube" => Ok(Self::Aube),
                "Aude" => Ok(Self::Aude),
                "Auvergne-Rhône-Alpes" => Ok(Self::AuvergneRhoneAlpes),
                "Aveyron" => Ok(Self::Aveyron),
                "Bas-Rhin" => Ok(Self::BasRhin),
                "Bouches-du-Rhône" => Ok(Self::BouchesDuRhone),
                "Bourgogne-Franche-Comté" => Ok(Self::BourgogneFrancheComte),
                "Bretagne" => Ok(Self::Bretagne),
                "Calvados" => Ok(Self::Calvados),
                "Cantal" => Ok(Self::Cantal),
                "Centre-Val de Loire" => Ok(Self::CentreValDeLoire),
                "Charente" => Ok(Self::Charente),
                "Charente-Maritime" => Ok(Self::CharenteMaritime),
                "Cher" => Ok(Self::Cher),
                "Clipperton" => Ok(Self::Clipperton),
                "Corrèze" => Ok(Self::Correze),
                "Corse" => Ok(Self::Corse),
                "Corse-du-Sud" => Ok(Self::CorseDuSud),
                "Côte-d'Or" => Ok(Self::CoteDor),
                "Côtes-d'Armor" => Ok(Self::CotesDarmor),
                "Creuse" => Ok(Self::Creuse),
                "Deux-Sèvres" => Ok(Self::DeuxSevres),
                "Dordogne" => Ok(Self::Dordogne),
                "Doubs" => Ok(Self::Doubs),
                "Drôme" => Ok(Self::Drome),
                "Essonne" => Ok(Self::Essonne),
                "Eure" => Ok(Self::Eure),
                "Eure-et-Loir" => Ok(Self::EureEtLoir),
                "Finistère" => Ok(Self::Finistere),
                "French Guiana" => Ok(Self::FrenchGuiana),
                "French Polynesia" => Ok(Self::FrenchPolynesia),
                "French Southern and Antarctic Lands" => Ok(Self::FrenchSouthernAndAntarcticLands),
                "Gard" => Ok(Self::Gard),
                "Gers" => Ok(Self::Gers),
                "Gironde" => Ok(Self::Gironde),
                "Grand-Est" => Ok(Self::GrandEst),
                "Guadeloupe" => Ok(Self::Guadeloupe),
                "Haut-Rhin" => Ok(Self::HautRhin),
                "Haute-Corse" => Ok(Self::HauteCorse),
                "Haute-Garonne" => Ok(Self::HauteGaronne),
                "Haute-Loire" => Ok(Self::HauteLoire),
                "Haute-Marne" => Ok(Self::HauteMarne),
                "Haute-Saône" => Ok(Self::HauteSaone),
                "Haute-Savoie" => Ok(Self::HauteSavoie),
                "Haute-Vienne" => Ok(Self::HauteVienne),
                "Hautes-Alpes" => Ok(Self::HautesAlpes),
                "Hautes-Pyrénées" => Ok(Self::HautesPyrenees),
                "Hauts-de-France" => Ok(Self::HautsDeFrance),
                "Hauts-de-Seine" => Ok(Self::HautsDeSeine),
                "Hérault" => Ok(Self::Herault),
                "Île-de-France" => Ok(Self::IleDeFrance),
                "Ille-et-Vilaine" => Ok(Self::IlleEtVilaine),
                "Indre" => Ok(Self::Indre),
                "Indre-et-Loire" => Ok(Self::IndreEtLoire),
                "Isère" => Ok(Self::Isere),
                "Jura" => Ok(Self::Jura),
                "La Réunion" => Ok(Self::LaReunion),
                "Landes" => Ok(Self::Landes),
                "Loir-et-Cher" => Ok(Self::LoirEtCher),
                "Loire" => Ok(Self::Loire),
                "Loire-Atlantique" => Ok(Self::LoireAtlantique),
                "Loiret" => Ok(Self::Loiret),
                "Lot" => Ok(Self::Lot),
                "Lot-et-Garonne" => Ok(Self::LotEtGaronne),
                "Lozère" => Ok(Self::Lozere),
                "Maine-et-Loire" => Ok(Self::MaineEtLoire),
                "Manche" => Ok(Self::Manche),
                "Marne" => Ok(Self::Marne),
                "Martinique" => Ok(Self::Martinique),
                "Mayenne" => Ok(Self::Mayenne),
                "Mayotte" => Ok(Self::Mayotte),
                "Métropole de Lyon" => Ok(Self::MetropoleDeLyon),
                "Meurthe-et-Moselle" => Ok(Self::MeurtheEtMoselle),
                "Meuse" => Ok(Self::Meuse),
                "Morbihan" => Ok(Self::Morbihan),
                "Moselle" => Ok(Self::Moselle),
                "Nièvre" => Ok(Self::Nievre),
                "Nord" => Ok(Self::Nord),
                "Normandie" => Ok(Self::Normandie),
                "Nouvelle-Aquitaine" => Ok(Self::NouvelleAquitaine),
                "Occitanie" => Ok(Self::Occitanie),
                "Oise" => Ok(Self::Oise),
                "Orne" => Ok(Self::Orne),
                "Paris" => Ok(Self::Paris),
                "Pas-de-Calais" => Ok(Self::PasDeCalais),
                "Pays-de-la-Loire" => Ok(Self::PaysDeLaLoire),
                "Provence-Alpes-Côte-d'Azur" => Ok(Self::ProvenceAlpesCoteDazur),
                "Puy-de-Dôme" => Ok(Self::PuyDeDome),
                "Pyrénées-Atlantiques" => Ok(Self::PyreneesAtlantiques),
                "Pyrénées-Orientales" => Ok(Self::PyreneesOrientales),
                "Rhône" => Ok(Self::Rhone),
                "Saint Pierre and Miquelon" => Ok(Self::SaintPierreAndMiquelon),
                "Saint-Barthélemy" => Ok(Self::SaintBarthelemy),
                "Saint-Martin" => Ok(Self::SaintMartin),
                "Saône-et-Loire" => Ok(Self::SaoneEtLoire),
                "Sarthe" => Ok(Self::Sarthe),
                "Savoie" => Ok(Self::Savoie),
                "Seine-et-Marne" => Ok(Self::SeineEtMarne),
                "Seine-Maritime" => Ok(Self::SeineMaritime),
                "Seine-Saint-Denis" => Ok(Self::SeineSaintDenis),
                "Somme" => Ok(Self::Somme),
                "Tarn" => Ok(Self::Tarn),
                "Tarn-et-Garonne" => Ok(Self::TarnEtGaronne),
                "Territoire de Belfort" => Ok(Self::TerritoireDeBelfort),
                "Val-d'Oise" => Ok(Self::ValDoise),
                "Val-de-Marne" => Ok(Self::ValDeMarne),
                "Var" => Ok(Self::Var),
                "Vaucluse" => Ok(Self::Vaucluse),
                "Vendée" => Ok(Self::Vendee),
                "Vienne" => Ok(Self::Vienne),
                "Vosges" => Ok(Self::Vosges),
                "Wallis and Futuna" => Ok(Self::WallisAndFutuna),
                "Yonne" => Ok(Self::Yonne),
                "Yvelines" => Ok(Self::Yvelines),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for GermanyStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "GermanyStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Baden-Württemberg" => Ok(Self::BW),
                "Bavaria" => Ok(Self::BY),
                "Berlin" => Ok(Self::BE),
                "Brandenburg" => Ok(Self::BB),
                "Bremen" => Ok(Self::HB),
                "Hamburg" => Ok(Self::HH),
                "Hessen" => Ok(Self::HE),
                "Lower Saxony" => Ok(Self::NI),
                "Mecklenburg-Vorpommern" => Ok(Self::MV),
                "North Rhine-Westphalia" => Ok(Self::NW),
                "Rhineland-Palatinate" => Ok(Self::RP),
                "Saarland" => Ok(Self::SL),
                "Saxony" => Ok(Self::SN),
                "Saxony-Anhalt" => Ok(Self::ST),
                "Schleswig-Holstein" => Ok(Self::SH),
                "Thuringia" => Ok(Self::TH),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for SpainStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "SpainStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "A Coruña Province" => Ok(Self::ACorunaProvince),
                "Albacete Province" => Ok(Self::AlbaceteProvince),
                "Alicante Province" => Ok(Self::AlicanteProvince),
                "Almería Province" => Ok(Self::AlmeriaProvince),
                "Andalusia" => Ok(Self::Andalusia),
                "Araba / Álava" => Ok(Self::ArabaAlava),
                "Aragon" => Ok(Self::Aragon),
                "Badajoz Province" => Ok(Self::BadajozProvince),
                "Balearic Islands" => Ok(Self::BalearicIslands),
                "Barcelona Province" => Ok(Self::BarcelonaProvince),
                "Basque Country" => Ok(Self::BasqueCountry),
                "Biscay" => Ok(Self::Biscay),
                "Burgos Province" => Ok(Self::BurgosProvince),
                "Canary Islands" => Ok(Self::CanaryIslands),
                "Cantabria" => Ok(Self::Cantabria),
                "Castellón Province" => Ok(Self::CastellonProvince),
                "Castile and León" => Ok(Self::CastileAndLeon),
                "Castilla-La Mancha" => Ok(Self::CastileLaMancha),
                "Catalonia" => Ok(Self::Catalonia),
                "Ceuta" => Ok(Self::Ceuta),
                "Ciudad Real Province" => Ok(Self::CiudadRealProvince),
                "Community of Madrid" => Ok(Self::CommunityOfMadrid),
                "Cuenca Province" => Ok(Self::CuencaProvince),
                "Cáceres Province" => Ok(Self::CaceresProvince),
                "Cádiz Province" => Ok(Self::CadizProvince),
                "Córdoba Province" => Ok(Self::CordobaProvince),
                "Extremadura" => Ok(Self::Extremadura),
                "Galicia" => Ok(Self::Galicia),
                "Gipuzkoa" => Ok(Self::Gipuzkoa),
                "Girona Province" => Ok(Self::GironaProvince),
                "Granada Province" => Ok(Self::GranadaProvince),
                "Guadalajara Province" => Ok(Self::GuadalajaraProvince),
                "Huelva Province" => Ok(Self::HuelvaProvince),
                "Huesca Province" => Ok(Self::HuescaProvince),
                "Jaén Province" => Ok(Self::JaenProvince),
                "La Rioja" => Ok(Self::LaRioja),
                "Las Palmas Province" => Ok(Self::LasPalmasProvince),
                "León Province" => Ok(Self::LeonProvince),
                "Lleida Province" => Ok(Self::LleidaProvince),
                "Lugo Province" => Ok(Self::LugoProvince),
                "Madrid Province" => Ok(Self::MadridProvince),
                "Melilla" => Ok(Self::Melilla),
                "Murcia Province" => Ok(Self::MurciaProvince),
                "Málaga Province" => Ok(Self::MalagaProvince),
                "Navarre" => Ok(Self::Navarre),
                "Ourense Province" => Ok(Self::OurenseProvince),
                "Palencia Province" => Ok(Self::PalenciaProvince),
                "Pontevedra Province" => Ok(Self::PontevedraProvince),
                "Province of Asturias" => Ok(Self::ProvinceOfAsturias),
                "Province of Ávila" => Ok(Self::ProvinceOfAvila),
                "Region of Murcia" => Ok(Self::RegionOfMurcia),
                "Salamanca Province" => Ok(Self::SalamancaProvince),
                "Santa Cruz de Tenerife Province" => Ok(Self::SantaCruzDeTenerifeProvince),
                "Segovia Province" => Ok(Self::SegoviaProvince),
                "Seville Province" => Ok(Self::SevilleProvince),
                "Soria Province" => Ok(Self::SoriaProvince),
                "Tarragona Province" => Ok(Self::TarragonaProvince),
                "Teruel Province" => Ok(Self::TeruelProvince),
                "Toledo Province" => Ok(Self::ToledoProvince),
                "Valencia Province" => Ok(Self::ValenciaProvince),
                "Valencian Community" => Ok(Self::ValencianCommunity),
                "Valladolid Province" => Ok(Self::ValladolidProvince),
                "Zamora Province" => Ok(Self::ZamoraProvince),
                "Zaragoza Province" => Ok(Self::ZaragozaProvince),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for ItalyStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "ItalyStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Abruzzo" => Ok(Self::Abruzzo),
                "Aosta Valley" => Ok(Self::AostaValley),
                "Apulia" => Ok(Self::Apulia),
                "Basilicata" => Ok(Self::Basilicata),
                "Benevento Province" => Ok(Self::BeneventoProvince),
                "Calabria" => Ok(Self::Calabria),
                "Campania" => Ok(Self::Campania),
                "Emilia-Romagna" => Ok(Self::EmiliaRomagna),
                "Friuli–Venezia Giulia" => Ok(Self::FriuliVeneziaGiulia),
                "Lazio" => Ok(Self::Lazio),
                "Liguria" => Ok(Self::Liguria),
                "Lombardy" => Ok(Self::Lombardy),
                "Marche" => Ok(Self::Marche),
                "Molise" => Ok(Self::Molise),
                "Piedmont" => Ok(Self::Piedmont),
                "Sardinia" => Ok(Self::Sardinia),
                "Sicily" => Ok(Self::Sicily),
                "Trentino-South Tyrol" => Ok(Self::TrentinoSouthTyrol),
                "Tuscany" => Ok(Self::Tuscany),
                "Umbria" => Ok(Self::Umbria),
                "Veneto" => Ok(Self::Veneto),
                "Libero consorzio comunale di Agrigento" => Ok(Self::Agrigento),
                "Libero consorzio comunale di Caltanissetta" => Ok(Self::Caltanissetta),
                "Libero consorzio comunale di Enna" => Ok(Self::Enna),
                "Libero consorzio comunale di Ragusa" => Ok(Self::Ragusa),
                "Libero consorzio comunale di Siracusa" => Ok(Self::Siracusa),
                "Libero consorzio comunale di Trapani" => Ok(Self::Trapani),
                "Metropolitan City of Bari" => Ok(Self::Bari),
                "Metropolitan City of Bologna" => Ok(Self::Bologna),
                "Metropolitan City of Cagliari" => Ok(Self::Cagliari),
                "Metropolitan City of Catania" => Ok(Self::Catania),
                "Metropolitan City of Florence" => Ok(Self::Florence),
                "Metropolitan City of Genoa" => Ok(Self::Genoa),
                "Metropolitan City of Messina" => Ok(Self::Messina),
                "Metropolitan City of Milan" => Ok(Self::Milan),
                "Metropolitan City of Naples" => Ok(Self::Naples),
                "Metropolitan City of Palermo" => Ok(Self::Palermo),
                "Metropolitan City of Reggio Calabria" => Ok(Self::ReggioCalabria),
                "Metropolitan City of Rome" => Ok(Self::Rome),
                "Metropolitan City of Turin" => Ok(Self::Turin),
                "Metropolitan City of Venice" => Ok(Self::Venice),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for NorwayStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "NorwayStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Akershus" => Ok(Self::Akershus),
                "Buskerud" => Ok(Self::Buskerud),
                "Finnmark" => Ok(Self::Finnmark),
                "Hedmark" => Ok(Self::Hedmark),
                "Hordaland" => Ok(Self::Hordaland),
                "Jan Mayen" => Ok(Self::JanMayen),
                "Møre og Romsdal" => Ok(Self::MoreOgRomsdal),
                "Nord-Trøndelag" => Ok(Self::NordTrondelag),
                "Nordland" => Ok(Self::Nordland),
                "Oppland" => Ok(Self::Oppland),
                "Oslo" => Ok(Self::Oslo),
                "Rogaland" => Ok(Self::Rogaland),
                "Sogn og Fjordane" => Ok(Self::SognOgFjordane),
                "Svalbard" => Ok(Self::Svalbard),
                "Sør-Trøndelag" => Ok(Self::SorTrondelag),
                "Telemark" => Ok(Self::Telemark),
                "Troms" => Ok(Self::Troms),
                "Trøndelag" => Ok(Self::Trondelag),
                "Vest-Agder" => Ok(Self::VestAgder),
                "Vestfold" => Ok(Self::Vestfold),
                "Østfold" => Ok(Self::Ostfold),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for AlbaniaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "AlbaniaStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Berat" => Ok(Self::Berat),
                "Dibër" => Ok(Self::Diber),
                "Durrës" => Ok(Self::Durres),
                "Elbasan" => Ok(Self::Elbasan),
                "Fier" => Ok(Self::Fier),
                "Gjirokastër" => Ok(Self::Gjirokaster),
                "Korçë" => Ok(Self::Korce),
                "Kukës" => Ok(Self::Kukes),
                "Lezhë" => Ok(Self::Lezhe),
                "Shkodër" => Ok(Self::Shkoder),
                "Tiranë" => Ok(Self::Tirane),
                "Vlorë" => Ok(Self::Vlore),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for AndorraStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "AndorraStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Andorra la Vella" => Ok(Self::AndorraLaVella),
                "Canillo" => Ok(Self::Canillo),
                "Encamp" => Ok(Self::Encamp),
                "Escaldes-Engordany" => Ok(Self::EscaldesEngordany),
                "La Massana" => Ok(Self::LaMassana),
                "Ordino" => Ok(Self::Ordino),
                "Sant Julià de Lòria" => Ok(Self::SantJuliaDeLoria),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for AustriaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "AustriaStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Burgenland" => Ok(Self::Burgenland),
                "Carinthia" => Ok(Self::Carinthia),
                "Lower Austria" => Ok(Self::LowerAustria),
                "Salzburg" => Ok(Self::Salzburg),
                "Styria" => Ok(Self::Styria),
                "Tyrol" => Ok(Self::Tyrol),
                "Upper Austria" => Ok(Self::UpperAustria),
                "Vienna" => Ok(Self::Vienna),
                "Vorarlberg" => Ok(Self::Vorarlberg),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for RomaniaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "RomaniaStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Alba" => Ok(Self::Alba),
                "Arad County" => Ok(Self::AradCounty),
                "Argeș" => Ok(Self::Arges),
                "Bacău County" => Ok(Self::BacauCounty),
                "Bihor County" => Ok(Self::BihorCounty),
                "Bistrița-Năsăud County" => Ok(Self::BistritaNasaudCounty),
                "Botoșani County" => Ok(Self::BotosaniCounty),
                "Brăila" => Ok(Self::Braila),
                "Brașov County" => Ok(Self::BrasovCounty),
                "Bucharest" => Ok(Self::Bucharest),
                "Buzău County" => Ok(Self::BuzauCounty),
                "Caraș-Severin County" => Ok(Self::CarasSeverinCounty),
                "Cluj County" => Ok(Self::ClujCounty),
                "Constanța County" => Ok(Self::ConstantaCounty),
                "Covasna County" => Ok(Self::CovasnaCounty),
                "Călărași County" => Ok(Self::CalarasiCounty),
                "Dolj County" => Ok(Self::DoljCounty),
                "Dâmbovița County" => Ok(Self::DambovitaCounty),
                "Galați County" => Ok(Self::GalatiCounty),
                "Giurgiu County" => Ok(Self::GiurgiuCounty),
                "Gorj County" => Ok(Self::GorjCounty),
                "Harghita County" => Ok(Self::HarghitaCounty),
                "Hunedoara County" => Ok(Self::HunedoaraCounty),
                "Ialomița County" => Ok(Self::IalomitaCounty),
                "Iași County" => Ok(Self::IasiCounty),
                "Ilfov County" => Ok(Self::IlfovCounty),
                "Mehedinți County" => Ok(Self::MehedintiCounty),
                "Mureș County" => Ok(Self::MuresCounty),
                "Neamț County" => Ok(Self::NeamtCounty),
                "Olt County" => Ok(Self::OltCounty),
                "Prahova County" => Ok(Self::PrahovaCounty),
                "Satu Mare County" => Ok(Self::SatuMareCounty),
                "Sibiu County" => Ok(Self::SibiuCounty),
                "Suceava County" => Ok(Self::SuceavaCounty),
                "Sălaj County" => Ok(Self::SalajCounty),
                "Teleorman County" => Ok(Self::TeleormanCounty),
                "Timiș County" => Ok(Self::TimisCounty),
                "Tulcea County" => Ok(Self::TulceaCounty),
                "Vaslui County" => Ok(Self::VasluiCounty),
                "Vrancea County" => Ok(Self::VranceaCounty),
                "Vâlcea County" => Ok(Self::ValceaCounty),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for PortugalStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "PortugalStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Aveiro District" => Ok(Self::AveiroDistrict),
                "Azores" => Ok(Self::Azores),
                "Beja District" => Ok(Self::BejaDistrict),
                "Braga District" => Ok(Self::BragaDistrict),
                "Bragança District" => Ok(Self::BragancaDistrict),
                "Castelo Branco District" => Ok(Self::CasteloBrancoDistrict),
                "Coimbra District" => Ok(Self::CoimbraDistrict),
                "Faro District" => Ok(Self::FaroDistrict),
                "Guarda District" => Ok(Self::GuardaDistrict),
                "Leiria District" => Ok(Self::LeiriaDistrict),
                "Lisbon District" => Ok(Self::LisbonDistrict),
                "Madeira" => Ok(Self::Madeira),
                "Portalegre District" => Ok(Self::PortalegreDistrict),
                "Porto District" => Ok(Self::PortoDistrict),
                "Santarém District" => Ok(Self::SantaremDistrict),
                "Setúbal District" => Ok(Self::SetubalDistrict),
                "Viana do Castelo District" => Ok(Self::VianaDoCasteloDistrict),
                "Vila Real District" => Ok(Self::VilaRealDistrict),
                "Viseu District" => Ok(Self::ViseuDistrict),
                "Évora District" => Ok(Self::EvoraDistrict),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for SwitzerlandStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "SwitzerlandStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Aargau" => Ok(Self::Aargau),


/// This struct represents the cryptogram data for Apple Pay transactions
pub struct ApplePayCryptogramData {
    /// The online payment cryptogram
    #[schema(value_type = String, example = "A1B2C3D4E5F6G7H8")]
    pub online_payment_cryptogram: Secret<String>,
    /// The ECI (Electronic Commerce Indicator) value
    #[schema(value_type = String, example = "05")]
    pub eci_indicator: Option<String>,
}


impl api::Refund for Adyen {}


pub async fn store_payout_method_data_in_locker(
        state: &routes::SessionState,
        token_id: Option<String>,
        payout_method: &api::PayoutMethodData,
        customer_id: Option<id_type::CustomerId>,
        merchant_key_store: &domain::MerchantKeyStore,
    ) -> RouterResult<String> {
        let value1 = payout_method
            .get_value1(customer_id.clone())
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Error getting Value1 for locker")?;

        let value2 = payout_method
            .get_value2(customer_id)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Error getting Value2 for locker")?;

        let lookup_key =
            token_id.unwrap_or_else(|| generate_id_with_default_len("temporary_token"));

        let lookup_key = create_tokenize(
            state,
            value1,
            Some(value2),
            lookup_key,
            merchant_key_store.key.get_inner(),
        )
        .await?;
        // add_delete_tokenized_data_task(&*state.store, &lookup_key, pm).await?;
        // scheduler_metrics::TOKENIZED_DATA_COUNT.add(1, &[]);
        Ok(lookup_key)
    }


pub struct CardDetails {
    last_digits: String,
}


pub struct NmiMerchantDefinedField {
    #[serde(flatten)]
    inner: std::collections::BTreeMap<String, Secret<String>>,
}


impl GetPaymentMethodType for WalletData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::AliPayQr(_) | Self::AliPayRedirect(_) => api_enums::PaymentMethodType::AliPay,
            Self::AliPayHkRedirect(_) => api_enums::PaymentMethodType::AliPayHk,
            Self::AmazonPayRedirect(_) => api_enums::PaymentMethodType::AmazonPay,
            Self::Skrill(_) => api_enums::PaymentMethodType::Skrill,
            Self::Paysera(_) => api_enums::PaymentMethodType::Paysera,
            Self::MomoRedirect(_) => api_enums::PaymentMethodType::Momo,
            Self::KakaoPayRedirect(_) => api_enums::PaymentMethodType::KakaoPay,
            Self::GoPayRedirect(_) => api_enums::PaymentMethodType::GoPay,
            Self::GcashRedirect(_) => api_enums::PaymentMethodType::Gcash,
            Self::AmazonPay(_) => api_enums::PaymentMethodType::AmazonPay,
            Self::ApplePay(_) | Self::ApplePayRedirect(_) | Self::ApplePayThirdPartySdk(_) => {
                api_enums::PaymentMethodType::ApplePay
            }
            Self::DanaRedirect {} => api_enums::PaymentMethodType::Dana,
            Self::GooglePay(_) | Self::GooglePayRedirect(_) | Self::GooglePayThirdPartySdk(_) => {
                api_enums::PaymentMethodType::GooglePay
            }
            Self::BluecodeRedirect {} => api_enums::PaymentMethodType::Bluecode,
            Self::MbWayRedirect(_) => api_enums::PaymentMethodType::MbWay,
            Self::MobilePayRedirect(_) => api_enums::PaymentMethodType::MobilePay,
            Self::PaypalRedirect(_) | Self::PaypalSdk(_) => api_enums::PaymentMethodType::Paypal,
            Self::Paze(_) => api_enums::PaymentMethodType::Paze,
            Self::SamsungPay(_) => api_enums::PaymentMethodType::SamsungPay,
            Self::TwintRedirect {} => api_enums::PaymentMethodType::Twint,
            Self::VippsRedirect {} => api_enums::PaymentMethodType::Vipps,
            Self::TouchNGoRedirect(_) => api_enums::PaymentMethodType::TouchNGo,
            Self::WeChatPayRedirect(_) | Self::WeChatPayQr(_) => {
                api_enums::PaymentMethodType::WeChatPay
            }
            Self::CashappQr(_) => api_enums::PaymentMethodType::Cashapp,
            Self::SwishQr(_) => api_enums::PaymentMethodType::Swish,
            Self::Mifinity(_) => api_enums::PaymentMethodType::Mifinity,
            Self::RevolutPay(_) => api_enums::PaymentMethodType::RevolutPay,
        }
    }
}

impl GetPaymentMethodType for for WalletData


impl api::PaymentVoid for Paybox {}


OpenAPI Block Path: components.schemas.ToggleKVResponse
{
  "type": "object",
  "required": [
    "merchant_id",
    "kv_enabled"
  ],
  "properties": {
    "merchant_id": {
      "type": "string",
      "description": "The identifier for the Merchant Account",
      "example": "y3oqhf46pyzuxjbcn2giaqnb44",
      "maxLength": 255
    },
    "kv_enabled": {
      "type": "boolean",
      "description": "Status of KV for the specific merchant",
      "example": true
    }
  }
}


pub async fn get_recon_token(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::ReconTokenRequest;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        (),
        |state, user, _, _| recon::generate_recon_token(state, user),
        &authentication::JWTAuth {
            permission: Permission::MerchantReconTokenRead,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct NexinetsAsyncDetails {
    pub success_url: Option<String>,
    pub cancel_url: Option<String>,
    pub failure_url: Option<String>,
}


pub async fn profile_update(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::ProfileId>,
    json_payload: web::Json<api_models::admin::ProfileUpdate>,
) -> HttpResponse {
    let flow = Flow::ProfileUpdate;
    let profile_id = path.into_inner();
    let payload = json_payload.into_inner();
    if let Err(api_error) = payload
        .webhook_details
        .as_ref()
        .map(|details| {
            details
                .validate()
                .map_err(|message| errors::ApiErrorResponse::InvalidRequestData { message })
        })
        .transpose()
    {
        return api::log_and_return_error_response(api_error.into());
    }

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, auth::AuthenticationDataWithoutProfile { key_store, .. }, req, _| {
            update_profile(state, &profile_id, key_store, req)
        },
        auth::auth_type(
            &auth::AdminApiAuthWithMerchantIdFromHeader,
            &auth::JWTAuthMerchantFromHeader {
                required_permission: permissions::Permission::MerchantAccountWrite,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


impl Responder {
        let flow = AnalyticsFlow::GenerateRefundReport;
        Box::pin(api::server_wrap(
            flow,
            state.clone(),
            &req,
            json_payload.into_inner(),
            |state, (auth, user_id): auth::AuthenticationDataWithUserId, payload, _| async move {
                let user = UserInterface::find_user_by_id(&*state.global_store, &user_id)
                    .await
                    .change_context(AnalyticsError::UnknownError)?;

                let user_email = UserEmail::from_pii_email(user.email)
                    .change_context(AnalyticsError::UnknownError)?
                    .get_secret();

                let org_id = auth.merchant_account.get_org_id();
                let merchant_id = auth.merchant_account.get_id();
                let lambda_req = GenerateReportRequest {
                    request: payload,
                    merchant_id: Some(merchant_id.clone()),
                    auth: AuthInfo::MerchantLevel {
                        org_id: org_id.clone(),
                        merchant_ids: vec![merchant_id.clone()],
                    },
                    email: user_email,
                };

                let json_bytes =
                    serde_json::to_vec(&lambda_req).map_err(|_| AnalyticsError::UnknownError)?;
                invoke_lambda(
                    &state.conf.report_download_config.refund_function,
                    &state.conf.report_download_config.region,
                    &json_bytes,
                )
                .await
                .map(ApplicationResponse::Json)
            },
            &auth::JWTAuth {
                permission: Permission::MerchantReportRead,
            },
            api_locking::LockAction::NotApplicable,
        ))
        .await
    }


pub struct SantanderPSyncBoletoRequest {
    payer_document_number: Secret<i64>,
}


impl Default for Server {
    fn default() -> Self {
        Self {
            host: "127.0.0.1".to_string(),
            port: 8080,
            workers: 1,
        }
    }
}


impl api::ConnectorAccessToken for Worldline {}

impl api::ConnectorAccessToken for for Worldline


pub enum NmiStatus {
    Abandoned,
    Cancelled,
    Pendingsettlement,
    Pending,
    Failed,
    Complete,
    InProgress,
    Unknown,
}

impl<F, T> TryFrom<ResponseRouterData<F, SyncResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<F, SyncResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        match item.response.transaction {
            Some(trn) => Ok(Self {
                status: AttemptStatus::from(NmiStatus::from(trn.condition)),
                response: Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::ConnectorTransactionId(trn.transaction_id),
                    redirection_data: Box::new(None),
                    mandate_reference: Box::new(None),
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: None,
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                ..item.data
            }),
            None => Ok(Self { ..item.data }), //when there is empty connector response i.e. response we get in psync when payment status is in authentication_pending
        }
    }
}

impl TryFrom<Vec<u8>> for SyncResponse {
    type Error = Error;
    fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
        let query_response = String::from_utf8(bytes)
            .change_context(ConnectorError::ResponseDeserializationFailed)?;
        query_response
            .parse_xml::<Self>()
            .change_context(ConnectorError::ResponseDeserializationFailed)
    }
}

impl TryFrom<Vec<u8>> for NmiRefundSyncResponse {
    type Error = Error;
    fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
        let query_response = String::from_utf8(bytes)
            .change_context(ConnectorError::ResponseDeserializationFailed)?;
        query_response
            .parse_xml::<Self>()
            .change_context(ConnectorError::ResponseDeserializationFailed)
    }
}

impl From<NmiStatus> for AttemptStatus {
    fn from(item: NmiStatus) -> Self {
        match item {
            NmiStatus::Abandoned => Self::AuthenticationFailed,
            NmiStatus::Cancelled => Self::Voided,
            NmiStatus::Pending => Self::Authorized,
            NmiStatus::Pendingsettlement | NmiStatus::Complete => Self::Charged,
            NmiStatus::InProgress => Self::AuthenticationPending,
            NmiStatus::Failed | NmiStatus::Unknown => Self::Failure,
        }
    }
}

// REFUND :
#[derive(Debug, Serialize)]
pub struct NmiRefundRequest {
    #[serde(rename = "type")]
    transaction_type: TransactionType,
    security_key: Secret<String>,
    transactionid: String,
    orderid: String,
    amount: FloatMajorUnit,
}

impl<F> TryFrom<&NmiRouterData<&RefundsRouterData<F>>> for NmiRefundRequest {
    type Error = Error;
    fn try_from(item: &NmiRouterData<&RefundsRouterData<F>>) -> Result<Self, Self::Error> {
        let auth_type: NmiAuthType = (&item.router_data.connector_auth_type).try_into()?;
        Ok(Self {
            transaction_type: TransactionType::Refund,
            security_key: auth_type.api_key,
            transactionid: item.router_data.request.connector_transaction_id.clone(),
            orderid: item.router_data.request.refund_id.clone(),
            amount: item.amount,
        })
    }
}

impl TryFrom<RefundsResponseRouterData<Execute, StandardResponse>> for RefundsRouterData<Execute> {
    type Error = Error;
    fn try_from(
        item: RefundsResponseRouterData<Execute, StandardResponse>,
    ) -> Result<Self, Self::Error> {
        let refund_status = RefundStatus::from(item.response.response);
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.orderid,
                refund_status,
            }),
            ..item.data
        })
    }
}

impl TryFrom<RefundsResponseRouterData<Capture, StandardResponse>> for RefundsRouterData<Capture> {
    type Error = Error;
    fn try_from(
        item: RefundsResponseRouterData<Capture, StandardResponse>,
    ) -> Result<Self, Self::Error> {
        let refund_status = RefundStatus::from(item.response.response);
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.transactionid,
                refund_status,
            }),
            ..item.data
        })
    }
}

impl From<Response> for RefundStatus {
    fn from(item: Response) -> Self {
        match item {
            Response::Approved => Self::Success,
            Response::Declined | Response::Error => Self::Failure,
        }
    }
}

impl TryFrom<&RefundSyncRouterData> for NmiSyncRequest {
    type Error = Error;
    fn try_from(item: &RefundSyncRouterData) -> Result<Self, Self::Error> {
        let auth = NmiAuthType::try_from(&item.connector_auth_type)?;

        Ok(Self {
            security_key: auth.api_key,
            order_id: item
                .request
                .connector_refund_id
                .clone()
                .ok_or(ConnectorError::MissingConnectorRefundID)?,
        })
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, NmiRefundSyncResponse>> for RefundsRouterData<RSync> {
    type Error = Report<ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<RSync, NmiRefundSyncResponse>,
    ) -> Result<Self, Self::Error> {
        let refund_status =
            RefundStatus::from(NmiStatus::from(item.response.transaction.condition));
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.transaction.order_id,
                refund_status,
            }),
            ..item.data
        })
    }
}

impl From<NmiStatus> for RefundStatus {
    fn from(item: NmiStatus) -> Self {
        match item {
            NmiStatus::Abandoned
            | NmiStatus::Cancelled
            | NmiStatus::Failed
            | NmiStatus::Unknown => Self::Failure,
            NmiStatus::Pending | NmiStatus::InProgress => Self::Pending,
            NmiStatus::Pendingsettlement | NmiStatus::Complete => Self::Success,
        }
    }
}

impl From<String> for NmiStatus {
    fn from(value: String) -> Self {
        match value.as_str() {
            "abandoned" => Self::Abandoned,
            "canceled" => Self::Cancelled,
            "in_progress" => Self::InProgress,
            "pendingsettlement" => Self::Pendingsettlement,
            "complete" => Self::Complete,
            "failed" => Self::Failed,
            "unknown" => Self::Unknown,
            // Other than above values only pending is possible, since value is a string handling this as default
            _ => Self::Pending,
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct SyncTransactionResponse {
    pub transaction_id: String,
    pub condition: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct SyncResponse {
    pub transaction: Option<SyncTransactionResponse>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RefundSyncBody {
    order_id: String,
    condition: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct NmiRefundSyncResponse {
    transaction: RefundSyncBody,
}

#[derive(Debug, Deserialize)]
pub struct NmiWebhookObjectReference {
    pub event_body: NmiReferenceBody,
}

#[derive(Debug, Deserialize)]
pub struct NmiReferenceBody {
    pub order_id: String,
    pub action: NmiActionBody,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct NmiActionBody {
    pub action_type: NmiActionType,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum NmiActionType {
    Auth,
    Capture,
    Credit,
    Refund,
    Sale,
    Void,
}

#[derive(Debug, Deserialize)]
pub struct NmiWebhookEventBody {
    pub event_type: NmiWebhookEventType,
}

#[derive(Debug, Deserialize, Serialize)]
pub enum NmiWebhookEventType {
    #[serde(rename = "transaction.sale.success")]
    SaleSuccess,
    #[serde(rename = "transaction.sale.failure")]
    SaleFailure,
    #[serde(rename = "transaction.sale.unknown")]
    SaleUnknown,
    #[serde(rename = "transaction.auth.success")]
    AuthSuccess,
    #[serde(rename = "transaction.auth.failure")]
    AuthFailure,
    #[serde(rename = "transaction.auth.unknown")]
    AuthUnknown,
    #[serde(rename = "transaction.refund.success")]
    RefundSuccess,
    #[serde(rename = "transaction.refund.failure")]
    RefundFailure,
    #[serde(rename = "transaction.refund.unknown")]
    RefundUnknown,
    #[serde(rename = "transaction.void.success")]
    VoidSuccess,
    #[serde(rename = "transaction.void.failure")]
    VoidFailure,
    #[serde(rename = "transaction.void.unknown")]
    VoidUnknown,
    #[serde(rename = "transaction.capture.success")]
    CaptureSuccess,
    #[serde(rename = "transaction.capture.failure")]
    CaptureFailure,
    #[serde(rename = "transaction.capture.unknown")]
    CaptureUnknown,
}

pub fn get_nmi_webhook_event(status: NmiWebhookEventType) -> IncomingWebhookEvent {
    match status {
        NmiWebhookEventType::SaleSuccess => IncomingWebhookEvent::PaymentIntentSuccess,
        NmiWebhookEventType::SaleFailure => IncomingWebhookEvent::PaymentIntentFailure,
        NmiWebhookEventType::RefundSuccess => IncomingWebhookEvent::RefundSuccess,
        NmiWebhookEventType::RefundFailure => IncomingWebhookEvent::RefundFailure,
        NmiWebhookEventType::VoidSuccess => IncomingWebhookEvent::PaymentIntentCancelled,
        NmiWebhookEventType::AuthSuccess => IncomingWebhookEvent::PaymentIntentAuthorizationSuccess,
        NmiWebhookEventType::CaptureSuccess => IncomingWebhookEvent::PaymentIntentCaptureSuccess,
        NmiWebhookEventType::AuthFailure => IncomingWebhookEvent::PaymentIntentAuthorizationFailure,
        NmiWebhookEventType::CaptureFailure => IncomingWebhookEvent::PaymentIntentCaptureFailure,
        NmiWebhookEventType::VoidFailure => IncomingWebhookEvent::PaymentIntentCancelFailure,
        NmiWebhookEventType::SaleUnknown
        | NmiWebhookEventType::RefundUnknown
        | NmiWebhookEventType::AuthUnknown
        | NmiWebhookEventType::VoidUnknown
        | NmiWebhookEventType::CaptureUnknown => IncomingWebhookEvent::EventNotSupported,
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct NmiWebhookBody {
    pub event_body: NmiWebhookObject,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct NmiWebhookObject {
    pub transaction_id: String,
    pub order_id: String,
    pub condition: String,
    pub action: NmiActionBody,
}

impl TryFrom<&NmiWebhookBody> for SyncResponse {
    type Error = Error;
    fn try_from(item: &NmiWebhookBody) -> Result<Self, Self::Error> {
        let transaction = Some(SyncTransactionResponse {
            transaction_id: item.event_body.transaction_id.to_owned(),
            condition: item.event_body.condition.to_owned(),
        });

        Ok(Self { transaction })
    }
}


pub async fn find_by_merchant_id_connector_refund_id_connector(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_refund_id: &str,
        connector: &str,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::connector_refund_id.eq(connector_refund_id.to_owned()))
                .and(dsl::connector.eq(connector.to_owned())),
        )
        .await
    }


pub struct RequestExtendedAuthorizationBool(bool);


pub async fn delete_tokenized_data_api() {}


pub fn get_viz_digraph_string(&self) -> String {
            let mut ctx = PrinterContext::default();
            let digraph = self.get_viz_digraph();
            digraph.print(&mut ctx)
        }


impl ConnectorCommon for Celero {
    fn id(&self) -> &'static str {
        "celero"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Minor
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.celero.base_url.as_ref()
    }

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let auth = celero::CeleroAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        Ok(vec![(
            headers::AUTHORIZATION.to_string(),
            auth.api_key.expose().into_masked(),
        )])
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: celero::CeleroErrorResponse = res
            .response
            .parse_struct("CeleroErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        // Extract error details from the response
        let error_details = celero::CeleroErrorDetails::from(response);

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: error_details
                .error_code
                .unwrap_or_else(|| "UNKNOWN_ERROR".to_string()),
            message: error_details.error_message,
            reason: error_details.decline_reason,
            attempt_status: None,
            connector_transaction_id: None,
            network_decline_code: error_details.processor_response_code.clone(),
            network_advice_code: None,
            network_error_message: error_details.processor_response_code,
            connector_metadata: None,
        })
    }
}


    Ok(match config {
        Ok(conf) => Some(
            serde_json::from_str::<Vec<storage_enums::PaymentMethodType>>(&conf.config)
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("skip_save_wallet_at_connector config parsing failed")?,
        ),
        Err(error) => {
            logger::error!(?error);
            None
        }
    })
}

#[cfg(feature = "v1")]
pub async fn override_setup_future_usage_to_on_session<F, D>(
    db: &dyn StorageInterface,
    payment_data: &mut D,
) -> CustomResult<(), errors::ApiErrorResponse>
where
    F: Clone,
    D: payments::OperationSessionGetters<F> + payments::OperationSessionSetters<F> + Send,
{
    if payment_data.get_payment_intent().setup_future_usage == Some(enums::FutureUsage::OffSession)
    {
        let skip_saving_wallet_at_connector_optional = config_skip_saving_wallet_at_connector(
            db,
            &payment_data.get_payment_intent().merchant_id,
        )
        .await?;

        if let Some(skip_saving_wallet_at_connector) = skip_saving_wallet_at_connector_optional {
            if let Some(payment_method_type) =
                payment_data.get_payment_attempt().get_payment_method_type()
            {
                if skip_saving_wallet_at_connector.contains(&payment_method_type) {
                    logger::debug!("Override setup_future_usage from off_session to on_session based on the merchant's skip_saving_wallet_at_connector configuration to avoid creating a connector mandate.");
                    payment_data
                        .set_setup_future_usage_in_payment_intent(enums::FutureUsage::OnSession);
                }
            }
        };
    };
    Ok(())
}

pub async fn validate_routing_id_with_profile_id(
    db: &dyn StorageInterface,
    routing_id: &id_type::RoutingId,
    profile_id: &id_type::ProfileId,
) -> CustomResult<(), errors::ApiErrorResponse> {
    let _routing_id = db
        .find_routing_algorithm_metadata_by_algorithm_id_profile_id(routing_id, profile_id)
        .await
        .map_err(|err| {
            if err.current_context().is_db_not_found() {
                logger::warn!(
                    "Routing id not found for routing id - {:?} and profile id - {:?}",
                    routing_id,
                    profile_id
                );
                err.change_context(errors::ApiErrorResponse::InvalidDataFormat {
                    field_name: "routing_algorithm_id".to_string(),
                    expected_format: "A valid routing_id that belongs to the business_profile"
                        .to_string(),
                })
            } else {
                err.change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to validate routing id")
            }
        })?;
    Ok(())
}

#[cfg(feature = "v1")]
pub async fn validate_merchant_connector_ids_in_connector_mandate_details(
    state: &SessionState,
    key_store: &domain::MerchantKeyStore,
    connector_mandate_details: &api_models::payment_methods::CommonMandateReference,
    merchant_id: &id_type::MerchantId,
    card_network: Option<api_enums::CardNetwork>,
) -> CustomResult<(), errors::ApiErrorResponse> {
    let db = &*state.store;
    let merchant_connector_account_list = db
        .find_merchant_connector_account_by_merchant_id_and_disabled_list(
            &state.into(),
            merchant_id,
            true,
            key_store,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::InternalServerError)?;

    let merchant_connector_account_details_hash_map: std::collections::HashMap<
        id_type::MerchantConnectorAccountId,
        domain::MerchantConnectorAccount,
    > = merchant_connector_account_list
        .iter()
        .map(|merchant_connector_account| {
            (
                merchant_connector_account.get_id(),
                merchant_connector_account.clone(),
            )
        })
        .collect();

    if let Some(payment_mandate_reference) = &connector_mandate_details.payments {
        let payments_map = payment_mandate_reference.0.clone();
        for (migrating_merchant_connector_id, migrating_connector_mandate_details) in payments_map {
            match (
                card_network.clone(),
                merchant_connector_account_details_hash_map.get(&migrating_merchant_connector_id),
            ) {
                (Some(enums::CardNetwork::Discover), Some(merchant_connector_account_details)) => {
                    if let ("cybersource", None) = (
                        merchant_connector_account_details.connector_name.as_str(),
                        migrating_connector_mandate_details
                            .original_payment_authorized_amount
                            .zip(
                                migrating_connector_mandate_details
                                    .original_payment_authorized_currency,
                            ),
                    ) {
                        Err(errors::ApiErrorResponse::MissingRequiredFields {
                            field_names: vec![
                                "original_payment_authorized_currency",
                                "original_payment_authorized_amount",
                            ],
                        })
                        .attach_printable(format!(
                            "Invalid connector_mandate_details provided for connector {migrating_merchant_connector_id:?}",

                        ))?
                    }
                }
                (_, Some(_)) => (),
                (_, None) => Err(errors::ApiErrorResponse::InvalidDataValue {
                    field_name: "merchant_connector_id",
                })
                .attach_printable_lazy(|| {
                    format!(
                        "{migrating_merchant_connector_id:?} invalid merchant connector id in connector_mandate_details",

                    )
                })?,
            }
        }
    } else {
        router_env::logger::error!("payment mandate reference not found");
    }
    Ok(())
}

pub fn validate_platform_request_for_marketplace(
    amount: api::Amount,
    split_payments: Option<common_types::payments::SplitPaymentsRequest>,
) -> Result<(), errors::ApiErrorResponse> {
    match split_payments {
        Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
            stripe_split_payment,
        )) => match amount {
            api::Amount::Zero => {
                if stripe_split_payment
                    .application_fees
                    .as_ref()
                    .map_or(MinorUnit::zero(), |amount| *amount)
                    != MinorUnit::zero()
                {
                    return Err(errors::ApiErrorResponse::InvalidDataValue {
                        field_name: "split_payments.stripe_split_payment.application_fees",
                    });
                }
            }
            api::Amount::Value(amount) => {
                if stripe_split_payment
                    .application_fees
                    .as_ref()
                    .map_or(MinorUnit::zero(), |amount| *amount)
                    > amount.into()
                {
                    return Err(errors::ApiErrorResponse::InvalidDataValue {
                        field_name: "split_payments.stripe_split_payment.application_fees",
                    });
                }
            }
        },
        Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
            adyen_split_payment,
        )) => {
            let total_split_amount: i64 = adyen_split_payment
                .split_items
                .iter()
                .map(|split_item| {
                    split_item
                        .amount
                        .unwrap_or(MinorUnit::new(0))
                        .get_amount_as_i64()
                })
                .sum();

            match amount {
                api::Amount::Zero => {
                    if total_split_amount != 0 {
                        return Err(errors::ApiErrorResponse::InvalidDataValue {
                            field_name: "Sum of split amounts should be equal to the total amount",
                        });
                    }
                }
                api::Amount::Value(amount) => {
                    let i64_amount: i64 = amount.into();
                    if !adyen_split_payment.split_items.is_empty()
                        && i64_amount != total_split_amount
                    {
                        return Err(errors::ApiErrorResponse::PreconditionFailed {
                            message: "Sum of split amounts should be equal to the total amount"
                                .to_string(),
                        });
                    }
                }
            };
            adyen_split_payment
                .split_items
                .iter()
                .try_for_each(|split_item| {
                    match split_item.split_type {
                        common_enums::AdyenSplitType::BalanceAccount => {
                            if split_item.account.is_none() {
                                return Err(errors::ApiErrorResponse::MissingRequiredField {
                                    field_name:
                                        "split_payments.adyen_split_payment.split_items.account",
                                });
                            }
                        }
                        common_enums::AdyenSplitType::Commission
                        | enums::AdyenSplitType::Vat
                        | enums::AdyenSplitType::TopUp => {
                            if split_item.amount.is_none() {
                                return Err(errors::ApiErrorResponse::MissingRequiredField {
                                    field_name:
                                        "split_payments.adyen_split_payment.split_items.amount",
                                });
                            }
                            if let enums::AdyenSplitType::TopUp = split_item.split_type {
                                if split_item.account.is_none() {
                                    return Err(errors::ApiErrorResponse::MissingRequiredField {
                                        field_name:
                                            "split_payments.adyen_split_payment.split_items.account",
                                    });
                                }
                                if adyen_split_payment.store.is_some() {
                                    return Err(errors::ApiErrorResponse::PreconditionFailed {
                                        message: "Topup split payment is not available via Adyen Platform"
                                            .to_string(),
                                    });
                                }
                            }
                        }
                        enums::AdyenSplitType::AcquiringFees
                        | enums::AdyenSplitType::PaymentFee
                        | enums::AdyenSplitType::AdyenFees
                        | enums::AdyenSplitType::AdyenCommission
                        | enums::AdyenSplitType::AdyenMarkup
                        | enums::AdyenSplitType::Interchange
                        | enums::AdyenSplitType::SchemeFee => {}
                    };
                    Ok(())
                })?;
        }
        Some(common_types::payments::SplitPaymentsRequest::XenditSplitPayment(
            xendit_split_payment,
        )) => match xendit_split_payment {
            common_types::payments::XenditSplitRequest::MultipleSplits(
                xendit_multiple_split_payment,
            ) => {
                match amount {
                    api::Amount::Zero => {
                        let total_split_amount: i64 = xendit_multiple_split_payment
                            .routes
                            .iter()
                            .map(|route| {
                                route
                                    .flat_amount
                                    .unwrap_or(MinorUnit::new(0))
                                    .get_amount_as_i64()
                            })
                            .sum();

                        if total_split_amount != 0 {
                            return Err(errors::ApiErrorResponse::InvalidDataValue {
                                field_name:
                                    "Sum of split amounts should be equal to the total amount",
                            });
                        }
                    }
                    api::Amount::Value(amount) => {
                        let total_payment_amount: i64 = amount.into();
                        let total_split_amount: i64 = xendit_multiple_split_payment
                    .routes
                    .into_iter()
                    .map(|route| {
                        if route.flat_amount.is_none() && route.percent_amount.is_none() {
                            Err(errors::ApiErrorResponse::InvalidRequestData {
                                message: "Expected either split_payments.xendit_split_payment.routes.flat_amount or split_payments.xendit_split_payment.routes.percent_amount to be provided".to_string(),
                            })
                        } else if route.flat_amount.is_some() && route.percent_amount.is_some(){
                            Err(errors::ApiErrorResponse::InvalidRequestData {
                                message: "Expected either split_payments.xendit_split_payment.routes.flat_amount or split_payments.xendit_split_payment.routes.percent_amount, but not both".to_string(),
                            })
                        } else {
                            Ok(route
                                .flat_amount
                                .map(|amount| amount.get_amount_as_i64())
                                .or(route.percent_amount.map(|percentage| (percentage * total_payment_amount) / 100))
                                .unwrap_or(0))
                            }
                            })
                            .collect::<Result<Vec<i64>, _>>()?
                            .into_iter()
                            .sum();

                        if total_payment_amount < total_split_amount {
                            return Err(errors::ApiErrorResponse::PreconditionFailed {
                                message:
                                    "The sum of split amounts should not exceed the total amount"
                                        .to_string(),
                            });
                        }
                    }
                };
            }
            common_types::payments::XenditSplitRequest::SingleSplit(_) => (),
        },
        None => (),
    }
    Ok(())
}

pub async fn is_merchant_eligible_authentication_service(
    merchant_id: &id_type::MerchantId,
    state: &SessionState,
) -> RouterResult<bool> {
    let merchants_eligible_for_authentication_service = state
        .store
        .as_ref()
        .find_config_by_key_unwrap_or(
            consts::AUTHENTICATION_SERVICE_ELIGIBLE_CONFIG,
            Some("[]".to_string()),
        )
        .await;

    let auth_eligible_array: Vec<String> = match merchants_eligible_for_authentication_service {
        Ok(config) => serde_json::from_str(&config.config)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("unable to parse authentication service config")?,
        Err(err) => {
            logger::error!(
                "Error fetching authentication service enabled merchant config {:?}",
                err
            );
            Vec::new()
        }
    };

    Ok(auth_eligible_array.contains(&merchant_id.get_string_repr().to_owned()))
}

#[cfg(feature = "v1")]
pub async fn validate_allowed_payment_method_types_request(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    merchant_context: &domain::MerchantContext,
    allowed_payment_method_types: Option<Vec<common_enums::PaymentMethodType>>,
) -> CustomResult<(), errors::ApiErrorResponse> {
    if let Some(allowed_payment_method_types) = allowed_payment_method_types {
        let db = &*state.store;
        let all_connector_accounts = db
            .find_merchant_connector_account_by_merchant_id_and_disabled_list(
                &state.into(),
                merchant_context.get_merchant_account().get_id(),
                false,
                merchant_context.get_merchant_key_store(),
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to fetch merchant connector account for given merchant id")?;

        let filtered_connector_accounts = all_connector_accounts
            .filter_based_on_profile_and_connector_type(
                profile_id,
                ConnectorType::PaymentProcessor,
            );

        let supporting_payment_method_types: HashSet<_> = filtered_connector_accounts
            .iter()
            .flat_map(|connector_account| {
                connector_account
                    .payment_methods_enabled
                    .clone()
                    .unwrap_or_default()
                    .into_iter()
                    .map(|payment_methods_enabled| {
                        payment_methods_enabled
                            .parse_value::<api_models::admin::PaymentMethodsEnabled>(
                                "payment_methods_enabled",
                            )
                    })
                    .filter_map(|parsed_payment_method_result| {
                        parsed_payment_method_result
                            .inspect_err(|err| {
                                logger::error!(
                                    "Unable to deserialize payment methods enabled: {:?}",
                                    err
                                );
                            })
                            .ok()
                    })
                    .flat_map(|parsed_payment_methods_enabled| {
                        parsed_payment_methods_enabled
                            .payment_method_types
                            .unwrap_or_default()
                            .into_iter()
                            .map(|payment_method_type| payment_method_type.payment_method_type)
                    })
            })
            .collect();

        let unsupported_payment_methods: Vec<_> = allowed_payment_method_types
            .iter()
            .filter(|allowed_pmt| !supporting_payment_method_types.contains(allowed_pmt))
            .collect();

        if !unsupported_payment_methods.is_empty() {
            metrics::PAYMENT_METHOD_TYPES_MISCONFIGURATION_METRIC.add(
                1,
                router_env::metric_attributes!((
                    "merchant_id",
                    merchant_context.get_merchant_account().get_id().clone()
                )),
            );
        }

        fp_utils::when(
            unsupported_payment_methods.len() == allowed_payment_method_types.len(),
            || {
                Err(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration)
                    .attach_printable(format!(
                        "None of the allowed payment method types {allowed_payment_method_types:?} are configured for this merchant connector account.",

                    ))
            },
        )?;
    }

    Ok(())
}

async fn get_payment_update_enabled_for_client_auth(
    merchant_id: &id_type::MerchantId,
    state: &SessionState,
) -> bool {
    let key = merchant_id.get_payment_update_enabled_for_client_auth_key();
    let db = &*state.store;
    let update_enabled = db.find_config_by_key(key.as_str()).await;

    match update_enabled {
        Ok(conf) => conf.config.to_lowercase() == "true",
        Err(error) => {
            logger::error!(?error);
            false
        }
    }
}

pub async fn allow_payment_update_enabled_for_client_auth(
    merchant_id: &id_type::MerchantId,
    state: &SessionState,
    auth_flow: services::AuthFlow,
) -> Result<(), error_stack::Report<errors::ApiErrorResponse>> {
    match auth_flow {
        services::AuthFlow::Client => {
            if get_payment_update_enabled_for_client_auth(merchant_id, state).await {
                Ok(())
            } else {
                Err(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Client auth for payment update is not enabled.")
            }
        }
        services::AuthFlow::Merchant => Ok(()),
    }
}

#[cfg(feature = "v2")]
#[instrument(skip_all)]
pub async fn get_merchant_connector_account_v2(
    state: &SessionState,
    key_store: &domain::MerchantKeyStore,
    merchant_connector_id: Option<&id_type::MerchantConnectorAccountId>,
) -> RouterResult<domain::MerchantConnectorAccount> {
    let db = &*state.store;
    match merchant_connector_id {
        Some(merchant_connector_id) => db
            .find_merchant_connector_account_by_id(&state.into(), merchant_connector_id, key_store)
            .await
            .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
                id: merchant_connector_id.get_string_repr().to_string(),
            }),
        None => Err(errors::ApiErrorResponse::MissingRequiredField {
            field_name: "merchant_connector_id",
        })
        .attach_printable("merchant_connector_id is not provided"),
    }
}