use k8s_openapi::api::core::v1::{
    PersistentVolumeClaim, PersistentVolumeClaimSpec, VolumeResourceRequirements,
};
use k8s_openapi::apimachinery::pkg::api::resource::Quantity;
use kube::api::ObjectMeta;
use kube::Resource;

use crate::types::minioinstance::MinioInstance;

pub fn build_minio_pvc(mi: &MinioInstance) -> PersistentVolumeClaim {
    let name = mi.metadata.name.clone().unwrap();
    let ns = mi.metadata.namespace.clone().unwrap();
    let oref = mi.controller_owner_ref(&()).unwrap();

    let mut requests = std::collections::BTreeMap::new();
    requests.insert("storage".to_string(), Quantity(mi.spec.storage_size.clone()));

    PersistentVolumeClaim {
        metadata: ObjectMeta {
            name: Some(format!("{name}-data")),
            namespace: Some(ns),
            owner_references: Some(vec![oref]),
            ..Default::default()
        },
        spec: Some(PersistentVolumeClaimSpec {
            access_modes: Some(vec!["ReadWriteOnce".to_string()]),
            storage_class_name: mi.spec.storage_class_name.clone(),
            resources: Some(VolumeResourceRequirements {
                requests: Some(requests),
                ..Default::default()
            }),
            ..Default::default()
        }),
        ..Default::default()
    }
}

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

    #[test]
    fn pvc_named_correctly() {
        let pvc = build_minio_pvc(&test_minioinstance());
        assert_eq!(pvc.metadata.name.unwrap(), "minio-data");
    }

    #[test]
    fn pvc_has_correct_size() {
        let pvc = build_minio_pvc(&test_minioinstance());
        let spec = pvc.spec.unwrap();
        let requests = spec.resources.unwrap().requests.unwrap();
        assert_eq!(requests["storage"], Quantity("10Gi".to_string()));
    }

    #[test]
    fn pvc_has_storage_class() {
        let pvc = build_minio_pvc(&test_minioinstance());
        let spec = pvc.spec.unwrap();
        assert_eq!(
            spec.storage_class_name.unwrap(),
            "customer-workload-storage"
        );
    }

    #[test]
    fn pvc_has_owner_reference() {
        let pvc = build_minio_pvc(&test_minioinstance());
        let orefs = pvc.metadata.owner_references.unwrap();
        assert_eq!(orefs[0].name, "minio");
    }

    #[test]
    fn pvc_is_read_write_once() {
        let pvc = build_minio_pvc(&test_minioinstance());
        let spec = pvc.spec.unwrap();
        let modes = spec.access_modes.unwrap();
        assert_eq!(modes, vec!["ReadWriteOnce".to_string()]);
    }
}
