use serde::{Deserialize, Serialize};

use crate::types::TagCategory;

/// Tag types, formerly genres within MangaDex.
#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, PartialOrd, Serialize)]
#[serde(from = "u8")]
#[repr(u8)]
pub enum Tag {
    /// 4-koma manga present four panels per comic strip that traditionally are the same size
    /// and stack on top of each other vertically. These titles are usually gag manga, with a
    /// single joke or self-contained story in each strip, and little to no continuity between the
    /// strips. (Source: Anime-Planet)
    _4Koma = 1,
    /// Action is about conflict. Whether with guns, blades, fists, or mysterious powers,
    /// these manga feature characters in combat - either to protect themselves or the things
    /// or people they value, or simply as a way of life. (Source: Anime-Planet)
    Action = 2,
    /// In these manga, characters embark on a journey to explore the world or to search for
    /// something. These wanderers travel to many places and meet new people, often encountering
    /// hardships along the way, or discovering strengths and weaknesses about themselves that are
    /// revealed throughout the adventure. (Source: Anime-Planet)
    Adventure = 3,
    AwardWinning = 4,
    /// These manga aim to make you laugh through satire, parody, humorous observations, slapstick
    /// scenarios, or absurd antics. Bonus points for spitting your drink all over your screen!
    /// (Source: Anime-Planet)
    Comedy = 5,
    /// Cooking is the focus of these food-themed manga, whether the characters within attend a
    /// Culinary School, work in a Restaurant or are simply passionate home cooks. These manga may
    /// offer step-by-step Recipes for various dishes or plating techniques. (Source: Anime-Planet)
    Cooking = 6,
    /// Doujin are a popular type of independently produced and distributed magazine, generally
    /// made in small print runs and often written by fans of manga and/or anime, including
    /// fan-fiction based on pre-existing characters from other authors. (Source: Anime-Planet)
    Doujinshi = 7,
    /// Drama manga heavily emphasize their characters' emotional development. Whether by
    /// experiencing the protagonist’s emotional turmoil, viewing heated character interactions,
    /// or exploring a passionate romance, any manga that humanizes its characters through
    /// emphasizing their flaws qualifies as a Drama. (Source: Anime-Planet)
    Drama = 8,
    /// Constant panty shots, bouncing breasts and dubious camera angles are hallmarks of an
    /// Ecchi title. These titles are usually sexualized and designed to titillate, depicting
    /// perverted themes and focusing heavily on the female body. Nosebleeds, suspicious hand
    /// positions, faceplanting into bosoms, expressive and exaggerated body parts and other
    /// tropes characterize this genre. Ecchi is all about fanservice, while Borderline H and
    /// Smut titles focus more on sexual content. (Source: Anime-Planet)
    Ecchi = 9,
    /// Fantasy manga take place in a broad range of settings influenced by mythologies, legends,
    /// or popular and defining works of the genre such as The Lord of the Rings. They are
    /// generally characterized by a low level of technological development, though fantasy
    /// stories can just as easily take place in our modern world, or in a Post-apocalyptic
    /// society where technology was buried alongside the old world. These manga also tend to
    /// feature magic or other extraordinary abilities, strange or mysterious creatures, or
    /// humanoid races which coexist with humanity or inhabit their own lands removed from ours.
    /// (Source: Anime-Planet)
    Fantasy = 10,
    Gyaru = 11,
    /// A harem includes three or more characters who potentially show romantic interest in a
    /// male protagonist. The sex, gender, or orientation of the harem members is irrelevant as
    /// long as they exclusively, or at least primarily, are vying for the affections of the same
    /// individual - who may or may not reciprocate towards one, several, or none of these
    /// romantic rivals. (Source: Anime-Planet)
    Harem = 12,
    /// The setting of a historical manga takes place at some point in Earth's past. The level of
    /// dedication to portraying the lifestyles, societies, and technologies of past periods and
    /// peoples accurately or believably can vary greatly between different works.
    Historical = 13,
    /// Horror manga create an atmosphere of unease. Like Mystery manga, they encourage viewers
    /// to learn more about their world... but there may be secrets that are better left
    /// unexplored. Through eerie music and sounds, visceral or disturbing imagery, or startling
    /// moments, works of Horror make you worry about what gruesome thing is coming next.
    /// (Source: Anime-Planet)
    Horror = 14,
    MartialArts = 16,
    /// Mecha are self-propelling machines that are modeled after humans; some can change into
    /// multiple, non-humanoid formats as well. They're usually controlled by an internal pilot
    /// or by remote, but are sometimes sentient beings that move autonomously. A mecha's size
    /// ranges from bulky, wearable armor to a massive, towering contraption and beyond. While
    /// mecha have a wide range of applications, such as making manual labor easier, they are
    /// most commonly portrayed as heavily-armed war machines. (Source: Anime-Planet)
    Mecha = 17,
    /// These manga feature medical professionals such as doctors, surgeons and other staff, as
    /// they perform their medical duties at hospitals, clinics, or other locations.
    /// (Source: Anime-Planet)
    Medical = 18,
    /// These manga are all about the appreciation or performance of music, no matter the genre,
    /// or the skill level any musicians involved. Music lives in the soul of these characters!
    Music = 19,
    /// Mystery manga focus on unresolved questions, and the efforts of characters to discover
    /// the answers to them. Whether curious and deadly events are afoot, or some part of the
    /// world itself is strange or inexplicable, or someone's past or identity seems strangely
    /// shrouded, these characters are set on learning the truth. (Source: Anime-Planet)
    Mystery = 20,
    Oneshot = 21,
    /// Psychological manga delve into mental or emotional states of a character in the midst of
    /// a difficult situation, letting you observe them change as tension increases. Internal
    /// monologues are a key feature, allowing narration to delve into a character's mind,
    /// revealing their innermost ideas and motivations - even as they may be driven to the brink
    /// of sanity. (Source: Anime-Planet)
    Psychological = 22,
    /// These manga showcase the joys and hardships of falling in love, whether a schoolgirl has
    /// an unrequited crush on her senpai, a Love Triangle occurs within a group of friends, or
    /// rivals become lovers through competition or their intense passion for each other.
    /// (Source: Anime-Planet)
    Romance = 23,
    SchoolLife = 24,
    SciFi = 25,
    ShoujoAi = 28,
    ShounenAi = 30,
    SliceOfLife = 31,
    /// Smut manga are typically written by women, for women, for genres like Shoujo, Josei, and
    /// Yaoi. There's a strong focus on seduction, characters being swept off their feet, and
    /// other buildups to having sex that make you feel hot and bothered. Smutty manga
    /// frequently, but not always, includes explicit sexual content. (Source: Anime-Planet)
    Smut = 32,
    Sports = 33,
    /// Also called paranormal, supernatural events are those modern science has difficulty
    /// explaining. Supernaturally oriented titles are often steeped in folklore, myth, or Urban
    /// Legend. They may involve strange or inexplicable phenomena, Psychic Powers or emanations,
    /// and/or ghosts or other fantastic creatures. Supernatural events are those that lie at the
    /// edge of our understanding - they are easy to believe in, but difficult to prove.
    /// (Source: Anime-Planet)
    Supernatural = 34,
    Tragedy = 35,
    LongStrip = 36,
    /// Yaoi, also known as Boys' Love or BL in Japan, is a genre mostly written by women, for
    /// women, that depicts homosexual relationships between men. Japan typically uses this
    /// single category for all forms of these relationships, sexual or not. In the West, the
    /// term Shounen-ai categorizes stories that focus on emotional aspects of relationships,
    /// while Yaoi categorizes more of the sexual aspects, such as Smut, or explicit content. As
    /// Anime-Planet's audience is mostly based in the West, we use the Western definition for
    /// both Yaoi and Shounen-ai. See BL for a list of both titles. (Source: Anime-Planet)
    Yaoi = 37,
    /// Yuri is a genre that depicts homosexual relationships between women. Japan typically uses
    /// this single category for all forms of these relationships, sexual or not. In the West,
    /// the term Shoujo-ai categorizes stories that focus on the emotional aspects of the
    /// relationships, while Yuri categorizes more of the sexual aspects and explicit content. As
    /// Anime-Planet's audience is mostly based in the West, we use the Western definition for
    /// both Yuri and Shoujo-ai. (Source: Anime-Planet)
    Yuri = 38,
    VideoGames = 40,
    Isekai = 41,
    Adaptation = 42,
    Anthology = 43,
    WebComic = 44,
    FullColor = 45,
    UserCreated = 46,
    OfficialColored = 47,
    FanColored = 48,
    Gore = 49,
    SexualViolence = 50,
    Crime = 51,
    MagicalGirls = 52,
    Philosophical = 53,
    Superhero = 54,
    Thriller = 55,
    Wuxia = 56,
    Aliens = 57,
    Animals = 58,
    Crossdressing = 59,
    Demons = 60,
    Delinquents = 61,
    Genderswap = 62,
    Ghosts = 63,
    MonsterGirls = 64,
    Loli = 65,
    Magic = 66,
    Military = 67,
    Monsters = 68,
    Ninja = 69,
    OfficeWorkers = 70,
    Police = 71,
    PostApocalyptic = 72,
    Reincarnation = 73,
    ReverseHarem = 74,
    Samurai = 75,
    Shota = 76,
    Survival = 77,
    TimeTravel = 78,
    Vampires = 79,
    TraditionalGames = 80,
    VirtualReality = 81,
    Zombies = 82,
    Incest = 83,
    Mafia = 84,
    /// Originating from the term Villainous Noble Lady, the Villainess does nothing but cause
    /// trouble, or sometimes even tries to kill, the Heroine. At least, that would be the case
    /// if the story followed its original course, but due to time leaps, reincarnations,
    /// transmigrations, or other circumstances, in almost all cases the villainess is no longer
    /// the same person she was meant to be. This in turn causes changes to the original story,
    /// whether they try to follow the original course of events, or break them completely.
    Villainess = 85,
    #[serde(other)]
    Unknown = 0,
}

impl Tag {
    pub fn category(&self) -> TagCategory {
        match self {
            Self::_4Koma => TagCategory::Format,
            Self::Action => TagCategory::Genre,
            Self::Adventure => TagCategory::Genre,
            Self::AwardWinning => TagCategory::Format,
            Self::Comedy => TagCategory::Genre,
            Self::Cooking => TagCategory::Theme,
            Self::Doujinshi => TagCategory::Format,
            Self::Drama => TagCategory::Genre,
            Self::Ecchi => TagCategory::Content,
            Self::Fantasy => TagCategory::Genre,
            Self::Gyaru => TagCategory::Theme,
            Self::Harem => TagCategory::Theme,
            Self::Historical => TagCategory::Genre,
            Self::Horror => TagCategory::Genre,
            Self::MartialArts => TagCategory::Theme,
            Self::Mecha => TagCategory::Genre,
            Self::Medical => TagCategory::Genre,
            Self::Music => TagCategory::Theme,
            Self::Mystery => TagCategory::Genre,
            Self::Oneshot => TagCategory::Format,
            Self::Psychological => TagCategory::Genre,
            Self::Romance => TagCategory::Genre,
            Self::SchoolLife => TagCategory::Theme,
            Self::SciFi => TagCategory::Genre,
            Self::ShoujoAi => TagCategory::Genre,
            Self::ShounenAi => TagCategory::Genre,
            Self::SliceOfLife => TagCategory::Genre,
            Self::Smut => TagCategory::Content,
            Self::Sports => TagCategory::Genre,
            Self::Supernatural => TagCategory::Theme,
            Self::Tragedy => TagCategory::Genre,
            Self::LongStrip => TagCategory::Format,
            Self::Yaoi => TagCategory::Genre,
            Self::Yuri => TagCategory::Genre,
            Self::VideoGames => TagCategory::Theme,
            Self::Isekai => TagCategory::Genre,
            Self::Adaptation => TagCategory::Format,
            Self::Anthology => TagCategory::Format,
            Self::WebComic => TagCategory::Format,
            Self::FullColor => TagCategory::Format,
            Self::UserCreated => TagCategory::Format,
            Self::OfficialColored => TagCategory::Format,
            Self::FanColored => TagCategory::Format,
            Self::Gore => TagCategory::Content,
            Self::SexualViolence => TagCategory::Content,
            Self::Crime => TagCategory::Genre,
            Self::MagicalGirls => TagCategory::Genre,
            Self::Philosophical => TagCategory::Genre,
            Self::Superhero => TagCategory::Genre,
            Self::Thriller => TagCategory::Genre,
            Self::Wuxia => TagCategory::Genre,
            Self::Aliens => TagCategory::Theme,
            Self::Animals => TagCategory::Theme,
            Self::Crossdressing => TagCategory::Theme,
            Self::Demons => TagCategory::Theme,
            Self::Delinquents => TagCategory::Theme,
            Self::Genderswap => TagCategory::Theme,
            Self::Ghosts => TagCategory::Theme,
            Self::MonsterGirls => TagCategory::Theme,
            Self::Loli => TagCategory::Theme,
            Self::Magic => TagCategory::Theme,
            Self::Military => TagCategory::Theme,
            Self::Monsters => TagCategory::Theme,
            Self::Ninja => TagCategory::Theme,
            Self::OfficeWorkers => TagCategory::Theme,
            Self::Police => TagCategory::Theme,
            Self::PostApocalyptic => TagCategory::Theme,
            Self::Reincarnation => TagCategory::Theme,
            Self::ReverseHarem => TagCategory::Theme,
            Self::Samurai => TagCategory::Theme,
            Self::Shota => TagCategory::Theme,
            Self::Survival => TagCategory::Theme,
            Self::TimeTravel => TagCategory::Theme,
            Self::Vampires => TagCategory::Theme,
            Self::TraditionalGames => TagCategory::Theme,
            Self::VirtualReality => TagCategory::Theme,
            Self::Zombies => TagCategory::Theme,
            Self::Incest => TagCategory::Theme,
            Self::Mafia => TagCategory::Theme,
            Self::Villainess => TagCategory::Theme,
            Self::Unknown => TagCategory::Unknown,
        }
    }
}

impl Default for Tag {
    fn default() -> Self {
        0u8.into()
    }
}

impl std::fmt::Display for Tag {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        let name = match self {
            Self::_4Koma => "4-Koma",
            Self::Action => "Action",
            Self::Adventure => "Adventure",
            Self::AwardWinning => "Award Winning",
            Self::Comedy => "Comedy",
            Self::Cooking => "Cooking",
            Self::Doujinshi => "Doujinshi",
            Self::Drama => "Drama",
            Self::Ecchi => "Ecchi",
            Self::Fantasy => "Fantasy",
            Self::Gyaru => "Gyaru",
            Self::Harem => "Harem",
            Self::Historical => "Historical",
            Self::Horror => "Horror",
            Self::MartialArts => "Martial Arts",
            Self::Mecha => "Mecha",
            Self::Medical => "Medical",
            Self::Music => "Music",
            Self::Mystery => "Mystery",
            Self::Oneshot => "Oneshot",
            Self::Psychological => "Psychological",
            Self::Romance => "Romance",
            Self::SchoolLife => "School Life",
            Self::SciFi => "Sci-Fi",
            Self::ShoujoAi => "Shoujo Ai",
            Self::ShounenAi => "Shounen Ai",
            Self::SliceOfLife => "Slice of Life",
            Self::Smut => "Smut",
            Self::Sports => "Sports",
            Self::Supernatural => "Supernatural",
            Self::Tragedy => "Tragedy",
            Self::LongStrip => "Long Strip",
            Self::Yaoi => "Yaoi",
            Self::Yuri => "Yuri",
            Self::VideoGames => "Video Games",
            Self::Isekai => "Isekai",
            Self::Adaptation => "Adaptation",
            Self::Anthology => "Anthology",
            Self::WebComic => "Web Comic",
            Self::FullColor => "Full Colour",
            Self::UserCreated => "User Created",
            Self::OfficialColored => "Official Coloured",
            Self::FanColored => "Fan Coloured",
            Self::Gore => "Gore",
            Self::SexualViolence => "Sexual Violence",
            Self::Crime => "Crime",
            Self::MagicalGirls => "Magical Girls",
            Self::Philosophical => "Philosophical",
            Self::Superhero => "Superhero",
            Self::Thriller => "Thriller",
            Self::Wuxia => "Wuxia",
            Self::Aliens => "Aliens",
            Self::Animals => "Animals",
            Self::Crossdressing => "Crossdressing",
            Self::Demons => "Demons",
            Self::Delinquents => "Delinquents",
            Self::Genderswap => "Genderswap",
            Self::Ghosts => "Ghosts",
            Self::MonsterGirls => "Monster Girls",
            Self::Loli => "Loli",
            Self::Magic => "Magic",
            Self::Military => "Military",
            Self::Monsters => "Monsters",
            Self::Ninja => "Ninja",
            Self::OfficeWorkers => "Office Workers",
            Self::Police => "Police",
            Self::PostApocalyptic => "Post Apocalyptic",
            Self::Reincarnation => "Reincarnation",
            Self::ReverseHarem => "Reverse Harem",
            Self::Samurai => "Samurai",
            Self::Shota => "Shota",
            Self::Survival => "Survival",
            Self::TimeTravel => "Time Travel",
            Self::Vampires => "Vampires",
            Self::TraditionalGames => "Traditional Games",
            Self::VirtualReality => "Virtual Reality",
            Self::Zombies => "Zombies",
            Self::Incest => "Incest",
            Self::Mafia => "Mafia",
            Self::Villainess => "Villainess",
            Self::Unknown => "Unknown",
        };
        fmt.write_str(name)
    }
}

impl From<u8> for Tag {
    fn from(value: u8) -> Self {
        match value {
            1 => Self::_4Koma,
            2 => Self::Action,
            3 => Self::Adventure,
            4 => Self::AwardWinning,
            5 => Self::Comedy,
            6 => Self::Cooking,
            7 => Self::Doujinshi,
            8 => Self::Drama,
            9 => Self::Ecchi,
            10 => Self::Fantasy,
            11 => Self::Gyaru,
            12 => Self::Harem,
            13 => Self::Historical,
            14 => Self::Horror,
            16 => Self::MartialArts,
            17 => Self::Mecha,
            18 => Self::Medical,
            19 => Self::Music,
            20 => Self::Mystery,
            21 => Self::Oneshot,
            22 => Self::Psychological,
            23 => Self::Romance,
            24 => Self::SchoolLife,
            25 => Self::SciFi,
            28 => Self::ShoujoAi,
            30 => Self::ShounenAi,
            31 => Self::SliceOfLife,
            32 => Self::Smut,
            33 => Self::Sports,
            34 => Self::Supernatural,
            35 => Self::Tragedy,
            36 => Self::LongStrip,
            37 => Self::Yaoi,
            38 => Self::Yuri,
            40 => Self::VideoGames,
            41 => Self::Isekai,
            42 => Self::Adaptation,
            43 => Self::Anthology,
            44 => Self::WebComic,
            45 => Self::FullColor,
            46 => Self::UserCreated,
            47 => Self::OfficialColored,
            48 => Self::FanColored,
            49 => Self::Gore,
            50 => Self::SexualViolence,
            51 => Self::Crime,
            52 => Self::MagicalGirls,
            53 => Self::Philosophical,
            54 => Self::Superhero,
            55 => Self::Thriller,
            56 => Self::Wuxia,
            57 => Self::Aliens,
            58 => Self::Animals,
            59 => Self::Crossdressing,
            60 => Self::Demons,
            61 => Self::Delinquents,
            62 => Self::Genderswap,
            63 => Self::Ghosts,
            64 => Self::MonsterGirls,
            65 => Self::Loli,
            66 => Self::Magic,
            67 => Self::Military,
            68 => Self::Monsters,
            69 => Self::Ninja,
            70 => Self::OfficeWorkers,
            71 => Self::Police,
            72 => Self::PostApocalyptic,
            73 => Self::Reincarnation,
            74 => Self::ReverseHarem,
            75 => Self::Samurai,
            76 => Self::Shota,
            77 => Self::Survival,
            78 => Self::TimeTravel,
            79 => Self::Vampires,
            80 => Self::TraditionalGames,
            81 => Self::VirtualReality,
            82 => Self::Zombies,
            83 => Self::Incest,
            84 => Self::Mafia,
            85 => Self::Villainess,
            _ => Self::Unknown,
        }
    }
}

impl From<u16> for Tag {
    fn from(value: u16) -> Self {
        match value {
            1 => Self::_4Koma,
            2 => Self::Action,
            3 => Self::Adventure,
            4 => Self::AwardWinning,
            5 => Self::Comedy,
            6 => Self::Cooking,
            7 => Self::Doujinshi,
            8 => Self::Drama,
            9 => Self::Ecchi,
            10 => Self::Fantasy,
            11 => Self::Gyaru,
            12 => Self::Harem,
            13 => Self::Historical,
            14 => Self::Horror,
            16 => Self::MartialArts,
            17 => Self::Mecha,
            18 => Self::Medical,
            19 => Self::Music,
            20 => Self::Mystery,
            21 => Self::Oneshot,
            22 => Self::Psychological,
            23 => Self::Romance,
            24 => Self::SchoolLife,
            25 => Self::SciFi,
            28 => Self::ShoujoAi,
            30 => Self::ShounenAi,
            31 => Self::SliceOfLife,
            32 => Self::Smut,
            33 => Self::Sports,
            34 => Self::Supernatural,
            35 => Self::Tragedy,
            36 => Self::LongStrip,
            37 => Self::Yaoi,
            38 => Self::Yuri,
            40 => Self::VideoGames,
            41 => Self::Isekai,
            42 => Self::Adaptation,
            43 => Self::Anthology,
            44 => Self::WebComic,
            45 => Self::FullColor,
            46 => Self::UserCreated,
            47 => Self::OfficialColored,
            48 => Self::FanColored,
            49 => Self::Gore,
            50 => Self::SexualViolence,
            51 => Self::Crime,
            52 => Self::MagicalGirls,
            53 => Self::Philosophical,
            54 => Self::Superhero,
            55 => Self::Thriller,
            56 => Self::Wuxia,
            57 => Self::Aliens,
            58 => Self::Animals,
            59 => Self::Crossdressing,
            60 => Self::Demons,
            61 => Self::Delinquents,
            62 => Self::Genderswap,
            63 => Self::Ghosts,
            64 => Self::MonsterGirls,
            65 => Self::Loli,
            66 => Self::Magic,
            67 => Self::Military,
            68 => Self::Monsters,
            69 => Self::Ninja,
            70 => Self::OfficeWorkers,
            71 => Self::Police,
            72 => Self::PostApocalyptic,
            73 => Self::Reincarnation,
            74 => Self::ReverseHarem,
            75 => Self::Samurai,
            76 => Self::Shota,
            77 => Self::Survival,
            78 => Self::TimeTravel,
            79 => Self::Vampires,
            80 => Self::TraditionalGames,
            81 => Self::VirtualReality,
            82 => Self::Zombies,
            83 => Self::Incest,
            84 => Self::Mafia,
            85 => Self::Villainess,
            _ => Self::Unknown,
        }
    }
}

impl From<u32> for Tag {
    fn from(value: u32) -> Self {
        match value {
            1 => Self::_4Koma,
            2 => Self::Action,
            3 => Self::Adventure,
            4 => Self::AwardWinning,
            5 => Self::Comedy,
            6 => Self::Cooking,
            7 => Self::Doujinshi,
            8 => Self::Drama,
            9 => Self::Ecchi,
            10 => Self::Fantasy,
            11 => Self::Gyaru,
            12 => Self::Harem,
            13 => Self::Historical,
            14 => Self::Horror,
            16 => Self::MartialArts,
            17 => Self::Mecha,
            18 => Self::Medical,
            19 => Self::Music,
            20 => Self::Mystery,
            21 => Self::Oneshot,
            22 => Self::Psychological,
            23 => Self::Romance,
            24 => Self::SchoolLife,
            25 => Self::SciFi,
            28 => Self::ShoujoAi,
            30 => Self::ShounenAi,
            31 => Self::SliceOfLife,
            32 => Self::Smut,
            33 => Self::Sports,
            34 => Self::Supernatural,
            35 => Self::Tragedy,
            36 => Self::LongStrip,
            37 => Self::Yaoi,
            38 => Self::Yuri,
            40 => Self::VideoGames,
            41 => Self::Isekai,
            42 => Self::Adaptation,
            43 => Self::Anthology,
            44 => Self::WebComic,
            45 => Self::FullColor,
            46 => Self::UserCreated,
            47 => Self::OfficialColored,
            48 => Self::FanColored,
            49 => Self::Gore,
            50 => Self::SexualViolence,
            51 => Self::Crime,
            52 => Self::MagicalGirls,
            53 => Self::Philosophical,
            54 => Self::Superhero,
            55 => Self::Thriller,
            56 => Self::Wuxia,
            57 => Self::Aliens,
            58 => Self::Animals,
            59 => Self::Crossdressing,
            60 => Self::Demons,
            61 => Self::Delinquents,
            62 => Self::Genderswap,
            63 => Self::Ghosts,
            64 => Self::MonsterGirls,
            65 => Self::Loli,
            66 => Self::Magic,
            67 => Self::Military,
            68 => Self::Monsters,
            69 => Self::Ninja,
            70 => Self::OfficeWorkers,
            71 => Self::Police,
            72 => Self::PostApocalyptic,
            73 => Self::Reincarnation,
            74 => Self::ReverseHarem,
            75 => Self::Samurai,
            76 => Self::Shota,
            77 => Self::Survival,
            78 => Self::TimeTravel,
            79 => Self::Vampires,
            80 => Self::TraditionalGames,
            81 => Self::VirtualReality,
            82 => Self::Zombies,
            83 => Self::Incest,
            84 => Self::Mafia,
            85 => Self::Villainess,
            _ => Self::Unknown,
        }
    }
}

impl From<u64> for Tag {
    fn from(value: u64) -> Self {
        match value {
            1 => Self::_4Koma,
            2 => Self::Action,
            3 => Self::Adventure,
            4 => Self::AwardWinning,
            5 => Self::Comedy,
            6 => Self::Cooking,
            7 => Self::Doujinshi,
            8 => Self::Drama,
            9 => Self::Ecchi,
            10 => Self::Fantasy,
            11 => Self::Gyaru,
            12 => Self::Harem,
            13 => Self::Historical,
            14 => Self::Horror,
            16 => Self::MartialArts,
            17 => Self::Mecha,
            18 => Self::Medical,
            19 => Self::Music,
            20 => Self::Mystery,
            21 => Self::Oneshot,
            22 => Self::Psychological,
            23 => Self::Romance,
            24 => Self::SchoolLife,
            25 => Self::SciFi,
            28 => Self::ShoujoAi,
            30 => Self::ShounenAi,
            31 => Self::SliceOfLife,
            32 => Self::Smut,
            33 => Self::Sports,
            34 => Self::Supernatural,
            35 => Self::Tragedy,
            36 => Self::LongStrip,
            37 => Self::Yaoi,
            38 => Self::Yuri,
            40 => Self::VideoGames,
            41 => Self::Isekai,
            42 => Self::Adaptation,
            43 => Self::Anthology,
            44 => Self::WebComic,
            45 => Self::FullColor,
            46 => Self::UserCreated,
            47 => Self::OfficialColored,
            48 => Self::FanColored,
            49 => Self::Gore,
            50 => Self::SexualViolence,
            51 => Self::Crime,
            52 => Self::MagicalGirls,
            53 => Self::Philosophical,
            54 => Self::Superhero,
            55 => Self::Thriller,
            56 => Self::Wuxia,
            57 => Self::Aliens,
            58 => Self::Animals,
            59 => Self::Crossdressing,
            60 => Self::Demons,
            61 => Self::Delinquents,
            62 => Self::Genderswap,
            63 => Self::Ghosts,
            64 => Self::MonsterGirls,
            65 => Self::Loli,
            66 => Self::Magic,
            67 => Self::Military,
            68 => Self::Monsters,
            69 => Self::Ninja,
            70 => Self::OfficeWorkers,
            71 => Self::Police,
            72 => Self::PostApocalyptic,
            73 => Self::Reincarnation,
            74 => Self::ReverseHarem,
            75 => Self::Samurai,
            76 => Self::Shota,
            77 => Self::Survival,
            78 => Self::TimeTravel,
            79 => Self::Vampires,
            80 => Self::TraditionalGames,
            81 => Self::VirtualReality,
            82 => Self::Zombies,
            83 => Self::Incest,
            84 => Self::Mafia,
            85 => Self::Villainess,
            _ => Self::Unknown,
        }
    }
}

impl From<&str> for Tag {
    fn from(value: &str) -> Self {
        // Ordered by ID, not alphabetical.
        match value.to_lowercase().as_str() {
            "4-koma" => Self::_4Koma,
            "action" => Self::Action,
            "adventure" => Self::Adventure,
            "award winning" => Self::AwardWinning,
            "comedy" => Self::Comedy,
            "cooking" => Self::Cooking,
            "doujinshi" => Self::Doujinshi,
            "drama" => Self::Drama,
            "ecchi" => Self::Ecchi,
            "fantasy" => Self::Fantasy,
            "gyaru" => Self::Gyaru,
            "harem" => Self::Harem,
            "historical" => Self::Historical,
            "horror" => Self::Horror,
            "martial arts" => Self::MartialArts,
            "mecha" => Self::Mecha,
            "medical" => Self::Medical,
            "music" => Self::Music,
            "mystery" => Self::Mystery,
            "oneshot" => Self::Oneshot,
            "psychological" => Self::Psychological,
            "romance" => Self::Romance,
            "school life" => Self::SchoolLife,
            "sci-fi" => Self::SciFi,
            "shoujo ai" => Self::ShoujoAi,
            "shounen ai" => Self::ShounenAi,
            "slice of life" => Self::SliceOfLife,
            "smut" => Self::Smut,
            "sports" => Self::Sports,
            "supernatural" => Self::Supernatural,
            "tragedy" => Self::Tragedy,
            "long strip" => Self::LongStrip,
            "yaoi" => Self::Yaoi,
            "yuri" => Self::Yuri,
            "video games" => Self::VideoGames,
            "isekai" => Self::Isekai,
            "adaptation" => Self::Adaptation,
            "anthology" => Self::Anthology,
            "web comic" => Self::WebComic,
            "full color" => Self::FullColor,
            "user created" => Self::UserCreated,
            "official colored" => Self::OfficialColored,
            "fan colored" => Self::FanColored,
            "gore" => Self::Gore,
            "sexual violence" => Self::SexualViolence,
            "crime" => Self::Crime,
            "magical girls" => Self::MagicalGirls,
            "philosophical" => Self::Philosophical,
            "superhero" => Self::Superhero,
            "thriller" => Self::Thriller,
            "wuxia" => Self::Wuxia,
            "aliens" => Self::Aliens,
            "animals" => Self::Animals,
            "crossdressing" => Self::Crossdressing,
            "demons" => Self::Demons,
            "delinquents" => Self::Delinquents,
            "genderswap" => Self::Genderswap,
            "ghosts" => Self::Ghosts,
            "monster girls" => Self::MonsterGirls,
            "loli" => Self::Loli,
            "magic" => Self::Magic,
            "military" => Self::Military,
            "monsters" => Self::Monsters,
            "ninja" => Self::Ninja,
            "office workers" => Self::OfficeWorkers,
            "police" => Self::Police,
            "post-apocalyptic" => Self::PostApocalyptic,
            "reincarnation" => Self::Reincarnation,
            "reverse harem" => Self::ReverseHarem,
            "samurai" => Self::Samurai,
            "shota" => Self::Shota,
            "survival" => Self::Survival,
            "time travel" => Self::TimeTravel,
            "vampires" => Self::Vampires,
            "traditional games" => Self::TraditionalGames,
            "virtual reality" => Self::VirtualReality,
            "zombies" => Self::Zombies,
            "incest" => Self::Incest,
            "mafia" => Self::Mafia,
            "villainess" => Self::Villainess,
            _ => Self::Unknown,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn tag_produces_unknown_from_0() {
        let tag = Tag::from(0u8);
        assert_eq!(tag, Tag::Unknown);
    }

    #[test]
    fn tag_produces_action_from_2() {
        let tag = Tag::from(2u8);
        assert_eq!(tag, Tag::Action);
    }
}
