use rapira::{FromU8, Rapira};
use serde::{Deserialize, Serialize};
use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes};

use crate::{GetType, SimpleEnumType, Typ};

/// Active: 0, Disabled: 1, Deleted: 255
/// deleted - навсегда, disabled - можно потом восстановить.
#[derive(
    PartialOrd,
    Ord,
    Eq,
    PartialEq,
    Clone,
    Copy,
    Hash,
    Serialize,
    Deserialize,
    Debug,
    FromU8,
    Default,
    Rapira,
    IntoBytes,
    TryFromBytes,
    Immutable,
    KnownLayout,
)]
#[cfg_attr(
    feature = "rkyv",
    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts-rs", ts(export, export_to = "record_status.ts"))]
#[repr(u8)]
pub enum RecordStatus {
    /// 0
    #[default]
    Active = 0,
    /// 1
    Disabled = 1,
    /// 255
    Deleted = 255,
}

impl RecordStatus {
    pub const DELETED: u8 = Self::Deleted as u8;
    pub const ACTIVE: u8 = Self::Active as u8;

    /// `[255u8]`
    pub const DELETED_PREFIX: [u8; 1] = [Self::DELETED];
    /// `[0u8]`
    pub const ACTIVE_PREFIX: [u8; 1] = [Self::ACTIVE];

    pub fn is_active(&self) -> bool {
        self == &Self::Active
    }
}

impl GetType for RecordStatus {
    const TYPE: Typ = Typ::SimpleEnum(SimpleEnumType {
        name: "RecordStatus",
        variants: &[(0, "Active"), (1, "Disabled"), (255, "Deleted")],
    });
}

impl PartialEq<RecordStatus> for u8 {
    fn eq(&self, other: &RecordStatus) -> bool {
        *self == *other as u8
    }
}
