// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use anyhow::Result;
use jsonwebtoken as jwt;
use rand::prelude::RngCore;
use ring::{digest, pbkdf2};
use serde::{Deserialize, Serialize};
use std::num;
use std::vec;

use teaclave_types::{UserAuthClaims, UserRole};

const SALT_LEN: usize = 16;
const PASSWORD_DIGEST_LEN: usize = digest::SHA512_OUTPUT_LEN;
const PBKDF2_ITERATIONS: u32 = 100_000;
static PBKDF2_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA512;

pub(crate) const ISSUER_NAME: &str = "Teaclave";
pub(crate) static JWT_ALG: jwt::Algorithm = jwt::Algorithm::HS512;
pub(crate) const JWT_SECRET_LEN: usize = 512;

#[derive(Default, Clone, Serialize, Deserialize, Debug)]
pub(crate) struct UserInfo {
    pub id: String,
    pub role: UserRole,
    pub salt: Vec<u8>,
    pub salted_password_hash: Vec<u8>,
}

impl UserInfo {
    pub(crate) fn new(id: &str, password: &str, role: UserRole) -> Self {
        let mut rng = rand::thread_rng();
        let mut salt = vec![0u8; SALT_LEN];
        rng.fill_bytes(&mut salt);
        let mut salted_password_hash = vec![0u8; PASSWORD_DIGEST_LEN];
        let pbkdf2_iterations = num::NonZeroU32::new(PBKDF2_ITERATIONS).unwrap();
        pbkdf2::derive(
            PBKDF2_ALG,
            pbkdf2_iterations,
            &salt,
            password.as_bytes(),
            &mut salted_password_hash,
        );
        Self {
            id: id.to_string(),
            role,
            salt,
            salted_password_hash,
        }
    }

    pub(crate) fn verify_password(&self, password: &str) -> bool {
        let pbkdf2_iterations = num::NonZeroU32::new(PBKDF2_ITERATIONS).unwrap();
        pbkdf2::verify(
            PBKDF2_ALG,
            pbkdf2_iterations,
            &self.salt,
            password.as_bytes(),
            &self.salted_password_hash,
        )
        .is_ok()
    }

    pub(crate) fn get_token(&self, exp: u64, secret: &[u8]) -> Result<String> {
        let iss = ISSUER_NAME.to_string();
        let claims = UserAuthClaims {
            sub: self.id.to_string(),
            role: self.role.to_string(),
            iss,
            exp,
        };
        let header = jwt::Header {
            alg: JWT_ALG,
            ..Default::default()
        };
        let secret = jwt::EncodingKey::from_secret(secret);
        let token = jwt::encode(&header, &claims, &secret)?;
        Ok(token)
    }

    pub(crate) fn validate_token(&self, secret: &[u8], token: &str) -> Result<UserAuthClaims> {
        let iss = ISSUER_NAME.to_string();
        let mut validation = jwt::Validation::new(JWT_ALG);
        validation.iss = Some(iss);
        validation.sub = Some(self.id.to_string());
        let secret = jwt::DecodingKey::from_secret(secret);
        Ok(jwt::decode::<UserAuthClaims>(token, &secret, &validation)?.claims)
    }

    pub(crate) fn has_attribute(&self, attribute: &str) -> bool {
        match self.role {
            UserRole::DataOwner(ref a) => a == attribute,
            _ => false,
        }
    }
}
