//! Share reconstruction utilities.

use crate::shamir::Share;
use crate::polynomial::lagrange_interpolate;

/// Reconstruct a secret from Shamir shares using full Lagrange interpolation.
pub fn reconstruct_secret(shares: &[Share]) -> u64 {
    let points: Vec<(u64, u64)> = shares.iter().map(|s| (s.x, s.y)).collect();
    lagrange_interpolate(&points, 0)
}

/// Reconstruct the polynomial value at a specific point (not just x=0).
pub fn reconstruct_at_point(shares: &[Share], x: u64) -> u64 {
    let points: Vec<(u64, u64)> = shares.iter().map(|s| (s.x, s.y)).collect();
    lagrange_interpolate(&points, x)
}

/// Check if a set of shares is consistent by verifying that
/// different subsets give the same reconstruction.
pub fn check_consistency(shares: &[Share], threshold: usize) -> bool {
    if shares.len() < threshold + threshold - 1 {
        return true; // Not enough shares for a meaningful check
    }

    let first: Vec<(u64, u64)> = shares[..threshold]
        .iter().map(|s| (s.x, s.y)).collect();
    let second: Vec<(u64, u64)> = shares[threshold..(2 * threshold)]
        .iter().map(|s| (s.x, s.y)).collect();

    // Both subsets should reconstruct the same secret only if shares are valid
    let secret1 = crate::polynomial::lagrange_interpolate_zero(&first);
    let secret2 = crate::polynomial::lagrange_interpolate_zero(&second);
    secret1 == secret2
}

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

    #[test]
    fn test_reconstruct_at_zero() {
        let sss = ShamirSecretSharing::new(3, 5);
        let shares = sss.split(42u64);
        let reconstructed = reconstruct_secret(&shares[..3]);
        assert_eq!(reconstructed, 42);
    }

    #[test]
    fn test_reconstruct_at_point() {
        let sss = ShamirSecretSharing::new(2, 4);
        let shares = sss.split(100u64);
        // Reconstruct at x=10 should give the polynomial value at x=10
        // which equals the share at x=10 if we had one
        let _val = reconstruct_at_point(&shares[..2], 10);
        // Just check it doesn't panic
    }

    #[test]
    fn test_consistency_check_valid() {
        let sss = ShamirSecretSharing::new(2, 6);
        let shares = sss.split(1234u64);
        assert!(check_consistency(&shares, 2));
    }

    #[test]
    fn test_consistency_check_corrupted() {
        let sss = ShamirSecretSharing::new(2, 6);
        let mut shares = sss.split(1234u64);
        // Corrupt one share
        shares[0].y ^= 0xFF;
        // With corrupted shares, consistency check should fail
        assert!(!check_consistency(&shares, 2));
    }
}
