use base64::{engine::general_purpose::STANDARD, Engine as _};
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::OnceLock;

use crate::types::{LicensePayload, LicensingProfiles, Profile};

const PROFILES_JSON: &str = include_str!("../../licensing_profiles.json");

static ACTIVE_PROFILE: OnceLock<Profile> = OnceLock::new();

pub fn get_active_profile() -> &'static Profile {
  ACTIVE_PROFILE.get_or_init(|| {
    let profiles: LicensingProfiles = serde_json::from_str(PROFILES_JSON)
      .expect("Failed to parse compile-time licensing_profiles.json");

    if cfg!(test) {
      profiles.testing
    } else if cfg!(debug_assertions) {
      profiles.development
    } else {
      profiles.production
    }
  })
}

static PUBLIC_KEY_CACHE: OnceLock<[u8; 32]> = OnceLock::new();

pub fn decode_public_key_hex(hex: &str) -> [u8; 32] {
  let hex = hex.trim();

  if hex.len() != 64 {
    panic!("Hex public key must be exactly 64 characters");
  }

  let mut bytes = [0u8; 32];

  for i in 0..32 {
    let byte_str = &hex[i * 2..i * 2 + 2];
    bytes[i] = u8::from_str_radix(byte_str, 16).expect("Invalid hex in public key");
  }

  bytes
}

pub fn get_public_key_bytes() -> [u8; 32] {
  if let Some(cached) = PUBLIC_KEY_CACHE.get() {
    return *cached;
  }

  let bytes = decode_public_key_hex(&get_active_profile().public_key_hex);
  let _ = PUBLIC_KEY_CACHE.set(bytes);

  bytes
}

pub fn get_all_valid_key_bytes() -> Vec<[u8; 32]> {
  let profile = get_active_profile();
  let mut keys = vec![decode_public_key_hex(&profile.public_key_hex)];

  for hex in &profile.deprecated_public_keys {
    keys.push(decode_public_key_hex(hex));
  }

  keys
}

pub fn get_activation_url() -> &'static str {
  &get_active_profile().activation_url
}

static LICENSE_ACTIVE: AtomicBool = AtomicBool::new(false);

pub fn set_license_active(active: bool) {
  LICENSE_ACTIVE.store(active, Ordering::Relaxed);
  log::info!("License active cache set to {}", active);
}

pub fn is_license_active() -> bool {
  LICENSE_ACTIVE.load(Ordering::Relaxed)
}

pub fn verify_license_with_key(
  license_token: &str,
  public_key_bytes: &[u8],
  current_hwid: &str,
) -> Result<LicensePayload, String> {
  let parts: Vec<&str> = license_token.trim().split('.').collect();

  if parts.len() != 2 {
    return Err("Invalid license token format. Expected PAYLOAD.SIGNATURE".to_string());
  }

  let payload_b64 = parts[0];
  let signature_b64 = parts[1];

  let payload_bytes = STANDARD
    .decode(payload_b64)
    .map_err(|e| format!("Failed to decode payload: {}", e))?;

  let payload_str =
    String::from_utf8(payload_bytes).map_err(|e| format!("Invalid UTF-8 in payload: {}", e))?;

  let payload: LicensePayload = serde_json::from_str(&payload_str)
    .map_err(|e| format!("Failed to parse payload JSON: {}", e))?;

  let signature_bytes = STANDARD
    .decode(signature_b64)
    .map_err(|e| format!("Failed to decode signature: {}", e))?;

  if signature_bytes.len() != 64 {
    return Err("Signature must be 64 bytes".to_string());
  }

  let sig_arr: [u8; 64] = signature_bytes
    .try_into()
    .map_err(|_| "Signature convert failed".to_string())?;

  let signature = Signature::from_bytes(&sig_arr);

  let pub_key_arr: [u8; 32] = public_key_bytes
    .try_into()
    .map_err(|_| "Invalid public key length".to_string())?;

  let verifying_key =
    VerifyingKey::from_bytes(&pub_key_arr).map_err(|e| format!("Invalid verifying key: {}", e))?;

  verifying_key
    .verify(payload_b64.as_bytes(), &signature)
    .map_err(|e| format!("Signature verification failed: {}", e))?;

  if payload.hwid != current_hwid {
    return Err("License does not match this machine's Hardware ID".to_string());
  }

  if payload.product_id != "cleancopy" {
    return Err("License is not valid for this product".to_string());
  }

  Ok(payload)
}

pub fn verify_license_with_any_key(
  license_token: &str,
  public_keys: &[[u8; 32]],
  current_hwid: &str,
) -> Result<LicensePayload, String> {
  let mut last_err = String::new();

  for key in public_keys {
    match verify_license_with_key(license_token, key, current_hwid) {
      Ok(payload) => return Ok(payload),
      Err(e) => last_err = e,
    }
  }

  Err(last_err)
}

#[cfg(test)]
mod tests {
  use super::*;
  use base64::{engine::general_purpose::STANDARD, Engine as _};
  use ed25519_dalek::Signer;

  #[test]
  fn test_offline_validation() {
    let secret = [42u8; 32];
    let signing_key = ed25519_dalek::SigningKey::from_bytes(&secret);
    let verifying_key = signing_key.verifying_key();
    let pub_key_bytes = verifying_key.to_bytes();

    let dummy_hwid = "test-machine-hwid-abc-123".to_string();
    let payload = LicensePayload {
      product_id: "cleancopy".to_string(),
      license_key: "pi_12345".to_string(),
      hwid: dummy_hwid.clone(),
      max_devices: None,
      expires_at: None,
      device_count: None,
    };

    let payload_str = serde_json::to_string(&payload).unwrap();
    let payload_b64 = STANDARD.encode(payload_str.as_bytes());

    let signature = signing_key.sign(payload_b64.as_bytes());
    let signature_b64 = STANDARD.encode(signature.to_bytes());

    let license_token = format!("{}.{}", payload_b64, signature_b64);

    let verify_res = verify_license_with_key(&license_token, &pub_key_bytes, &dummy_hwid);
    assert!(verify_res.is_ok());

    let verify_res_wrong_hwid =
      verify_license_with_key(&license_token, &pub_key_bytes, "other-machine-hwid");
    assert!(verify_res_wrong_hwid.is_err());

    let tampered_license = format!("{}.{}", payload_b64, STANDARD.encode([0u8; 64]));
    let verify_res_tampered =
      verify_license_with_key(&tampered_license, &pub_key_bytes, &dummy_hwid);
    assert!(verify_res_tampered.is_err());

    let wrong_payload = LicensePayload {
      product_id: "other_app".to_string(),
      license_key: "pi_12345".to_string(),
      hwid: dummy_hwid.clone(),
      max_devices: None,
      expires_at: None,
      device_count: None,
    };
    let wrong_payload_str = serde_json::to_string(&wrong_payload).unwrap();
    let wrong_payload_b64 = STANDARD.encode(wrong_payload_str.as_bytes());
    let wrong_signature = signing_key.sign(wrong_payload_b64.as_bytes());
    let wrong_signature_b64 = STANDARD.encode(wrong_signature.to_bytes());
    let wrong_token = format!("{}.{}", wrong_payload_b64, wrong_signature_b64);

    let verify_res_wrong_product =
      verify_license_with_key(&wrong_token, &pub_key_bytes, &dummy_hwid);
    assert!(verify_res_wrong_product.is_err());
  }

  #[test]
  fn test_profile_configuration_loading() {
    let active = get_active_profile();
    assert!(!active.activation_url.is_empty());
    assert_eq!(active.public_key_hex.len(), 64);

    let bytes = get_public_key_bytes();
    assert_eq!(bytes.len(), 32);
  }

  #[test]
  fn test_deprecated_key_verification() {
    let old_secret = [11u8; 32];
    let new_secret = [22u8; 32];
    let old_signing_key = ed25519_dalek::SigningKey::from_bytes(&old_secret);
    let new_signing_key = ed25519_dalek::SigningKey::from_bytes(&new_secret);
    let old_pub_key = old_signing_key.verifying_key().to_bytes();
    let new_pub_key = new_signing_key.verifying_key().to_bytes();

    let dummy_hwid = "test-machine-hwid-deprecated".to_string();
    let payload = LicensePayload {
      product_id: "cleancopy".to_string(),
      license_key: "pi_99999".to_string(),
      hwid: dummy_hwid.clone(),
      max_devices: None,
      expires_at: None,
      device_count: None,
    };

    let payload_str = serde_json::to_string(&payload).unwrap();
    let payload_b64 = STANDARD.encode(payload_str.as_bytes());

    let signature = old_signing_key.sign(payload_b64.as_bytes());
    let signature_b64 = STANDARD.encode(signature.to_bytes());
    let token = format!("{}.{}", payload_b64, signature_b64);

    let keys_only_new = vec![new_pub_key];
    assert!(
      verify_license_with_any_key(&token, &keys_only_new, &dummy_hwid).is_err(),
      "Should fail when only new key is available"
    );

    let keys_with_old = vec![new_pub_key, old_pub_key];
    assert!(
      verify_license_with_any_key(&token, &keys_with_old, &dummy_hwid).is_ok(),
      "Should succeed when deprecated key is in the list"
    );
  }

  #[test]
  fn test_offline_token_format_verification() {
    let secret = [77u8; 32];
    let signing_key = ed25519_dalek::SigningKey::from_bytes(&secret);
    let verifying_key = signing_key.verifying_key();
    let pub_key_bytes = verifying_key.to_bytes();

    let dummy_hwid = "test-offline-token-hwid".to_string();
    let payload = LicensePayload {
      product_id: "cleancopy".to_string(),
      license_key: "manual_activation".to_string(),
      hwid: dummy_hwid.clone(),
      max_devices: None,
      expires_at: None,
      device_count: None,
    };

    let payload_str = serde_json::to_string(&payload).unwrap();
    let payload_b64 = STANDARD.encode(payload_str.as_bytes());
    let signature = signing_key.sign(payload_b64.as_bytes());
    let signature_b64 = STANDARD.encode(signature.to_bytes());
    let token = format!("{}.{}", payload_b64, signature_b64);

    assert!(token.contains('.'), "Token must contain period separator");

    let keys = vec![pub_key_bytes];
    let result = verify_license_with_any_key(&token, &keys, &dummy_hwid);
    assert!(result.is_ok(), "Offline token should verify successfully");

    let result_wrong_hwid = verify_license_with_any_key(&token, &keys, "wrong-hwid");
    assert!(
      result_wrong_hwid.is_err(),
      "Offline token should reject wrong HWID"
    );
  }
}
