/**
 * @file credential-verifier.ts
 * @notice Credential verification for tokenization workflows
 */

import { InstitutionalIdentityService, VerifiableCredential } from './institutional-identity';

export interface CredentialVerificationRequest {
    did: string;
    requiredCredentials: string[];
    requiredTier?: number;
}

export interface CredentialVerificationResult {
    verified: boolean;
    missingCredentials: string[];
    tier: number;
    credentials: VerifiableCredential[];
    error?: string;
}

export class CredentialVerifier {
    private identityService: InstitutionalIdentityService;

    constructor(identityService: InstitutionalIdentityService) {
        this.identityService = identityService;
    }

    /**
     * Verify credentials for tokenization operation
     */
    async verifyForTokenization(
        request: CredentialVerificationRequest
    ): Promise<CredentialVerificationResult> {
        // Get institution credentials
        const credentials = await this.identityService.getInstitutionCredentials(request.did);

        // Verify each credential
        const verifiedCredentials: VerifiableCredential[] = [];
        const missingCredentials: string[] = [];

        for (const requiredType of request.requiredCredentials) {
            const credential = credentials.find((vc: VerifiableCredential) =>
                vc.type.includes(requiredType)
            );

            if (!credential) {
                missingCredentials.push(requiredType);
                continue;
            }

            // Verify credential
            const verification = await this.identityService.verifyCredential(credential);
            if (verification.valid) {
                verifiedCredentials.push(credential);
            } else {
                missingCredentials.push(requiredType);
            }
        }

        // Check tier requirement
        const eligibility = await this.identityService.checkTokenizationEligibility(request.did);
        const tierMet = request.requiredTier
            ? eligibility.tier >= request.requiredTier
            : true;

        return {
            verified: missingCredentials.length === 0 && tierMet,
            missingCredentials,
            tier: eligibility.tier,
            credentials: verifiedCredentials,
            error: missingCredentials.length > 0
                ? `Missing credentials: ${missingCredentials.join(', ')}`
                : !tierMet
                ? `Tier requirement not met: required ${request.requiredTier}, has ${eligibility.tier}`
                : undefined
        };
    }

    /**
     * Verify credentials for specific operation type
     */
    async verifyForOperation(
        did: string,
        operation: 'mint' | 'transfer' | 'redeem' | 'bridge'
    ): Promise<CredentialVerificationResult> {
        const requiredCredentials = this.getRequiredCredentials(operation);
        const requiredTier = this.getRequiredTier(operation);

        return this.verifyForTokenization({
            did,
            requiredCredentials,
            requiredTier
        });
    }

    /**
     * Get required credentials for operation
     */
    private getRequiredCredentials(operation: string): string[] {
        const requirements: Record<string, string[]> = {
            'mint': ['KYC', 'AML', 'RegulatoryApproval'],
            'transfer': ['KYC', 'AML'],
            'redeem': ['KYC', 'AML', 'RegulatoryApproval'],
            'bridge': ['KYC', 'AML']
        };

        return requirements[operation] || ['KYC', 'AML'];
    }

    /**
     * Get required tier for operation
     */
    private getRequiredTier(operation: string): number {
        const tierRequirements: Record<string, number> = {
            'mint': 2, // Tier 2 for minting
            'transfer': 1, // Tier 1 for transfers
            'redeem': 2, // Tier 2 for redemption
            'bridge': 1 // Tier 1 for bridging
        };

        return tierRequirements[operation] || 1;
    }

    /**
     * Check policy-based access control
     */
    async checkPolicyAccess(
        did: string,
        operation: string,
        context: Record<string, any>
    ): Promise<{ allowed: boolean; reason?: string }> {
        const verification = await this.verifyForOperation(did, operation as any);

        if (!verification.verified) {
            return {
                allowed: false,
                reason: verification.error
            };
        }

        // Additional policy checks
        // In production, integrate with SolaceNet policy engine
        if (context.amount && parseFloat(context.amount) > 1000000) {
            // Large amounts require Tier 3
            if (verification.tier < 3) {
                return {
                    allowed: false,
                    reason: 'Large amount requires Tier 3 credentials'
                };
            }
        }

        return { allowed: true };
    }
}
