// Copyright 2024 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
// at your option.

// Unless required by applicable law or agreed to in writing,
// this software is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
// specific language governing permissions and limitations under
// each license.

//! Naive implementation of credential-handling traits for
//! proof-of-concept/testing purposes.
//!
//! The "signature" in this example is simply the CBOR encoding
//! of the `signer_payload` struct. This is really intended to test
//! the signature mechanism, not to be a meaningful signature itself.
//!
//! Not suitable for production use.

use std::fmt::Debug;

use async_trait::async_trait;
use serde::Serialize;

use crate::{
    identity::{
        builder::{AsyncCredentialHolder, CredentialHolder, IdentityBuilderError},
        identity_assertion::signature_verifier::ToCredentialSummary,
        SignatureVerifier, SignerPayload, ValidationError,
    },
    status_tracker::StatusTracker,
};

pub(crate) struct NaiveCredentialHolder {}

impl CredentialHolder for NaiveCredentialHolder {
    fn sig_type(&self) -> &'static str {
        "INVALID.identity.naive_credential"
    }

    fn reserve_size(&self) -> usize {
        1000
    }

    fn sign(&self, signer_payload: &SignerPayload) -> Result<Vec<u8>, IdentityBuilderError> {
        // Naive implementation simply serializes SignerPayload
        // in CBOR format and calls it a "signature."
        let mut result: Vec<u8> = vec![];
        c2pa_cbor::to_writer(&mut result, signer_payload)?;
        Ok(result)
    }
}

#[derive(Debug)]
pub(crate) struct NaiveAsyncCredentialHolder {}

#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl AsyncCredentialHolder for NaiveAsyncCredentialHolder {
    fn sig_type(&self) -> &'static str {
        "INVALID.identity.naive_credential"
    }

    fn reserve_size(&self) -> usize {
        1000
    }

    async fn sign(&self, signer_payload: &SignerPayload) -> Result<Vec<u8>, IdentityBuilderError> {
        // Naive implementation simply serializes SignerPayload
        // in CBOR format and calls it a "signature."
        let mut result: Vec<u8> = vec![];
        c2pa_cbor::to_writer(&mut result, signer_payload)?;
        Ok(result)
    }
}

pub(crate) struct NaiveSignatureVerifier {}

#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl SignatureVerifier for NaiveSignatureVerifier {
    type Error = ();
    type Output = NaiveCredential;

    fn check_signature(
        &self,
        signer_payload: &SignerPayload,
        signature: &[u8],
        _status_tracker: &mut StatusTracker,
    ) -> Result<Self::Output, ValidationError<Self::Error>> {
        let mut signer_payload_cbor: Vec<u8> = vec![];
        c2pa_cbor::to_writer(&mut signer_payload_cbor, signer_payload)
            .map_err(|_| ValidationError::InternalError("CBOR serialization error".to_string()))?;

        if signer_payload_cbor != signature {
            Err(ValidationError::SignatureMismatch)
        } else {
            Ok(NaiveCredential {})
        }
    }

    async fn check_signature_async(
        &self,
        signer_payload: &SignerPayload,
        signature: &[u8],
        status_tracker: &mut StatusTracker,
    ) -> Result<Self::Output, ValidationError<Self::Error>> {
        self.check_signature(signer_payload, signature, status_tracker)
    }
}

pub(crate) struct NaiveCredential {}

impl ToCredentialSummary for NaiveCredential {
    type CredentialSummary = NaiveCredentialSummary;

    fn to_summary(&self) -> Self::CredentialSummary {
        NaiveCredentialSummary {}
    }
}

#[doc(hidden)]
#[derive(Serialize)]
pub struct NaiveCredentialSummary {}
