import { z } from 'zod';
import type { AuthorizationRequest, TokenRequest, OIDCClient } from '../types';

/**
 * OIDC验证工具类
 */
export class ValidationUtils {
    /**
     * 验证重定向URI
     */
    static isValidRedirectUri(uri: string): boolean {
        try {
            const url = new URL(uri);
            // 不允许fragment
            if (url.hash) {
                return false;
            }
            // 必须是HTTPS（除了localhost）
            if (url.protocol !== 'https:' && url.hostname !== 'localhost' && url.hostname !== '127.0.0.1') {
                return false;
            }
            return true;
        } catch {
            return false;
        }
    }

    /**
     * 验证作用域
     */
    static isValidScope(scope: string, supportedScopes: string[]): boolean {
        if (!scope || typeof scope !== 'string') {
            return false;
        }

        const requestedScopes = scope.split(' ').filter(s => s.length > 0);

        // 必须包含openid作用域
        if (!requestedScopes.includes('openid')) {
            return false;
        }

        // 检查所有请求的作用域是否都被支持
        return requestedScopes.every(s => supportedScopes.includes(s));
    }

    /**
     * 验证响应类型
     */
    static isValidResponseType(responseType: string, supportedTypes: string[]): boolean {
        if (!responseType || typeof responseType !== 'string') {
            return false;
        }

        return supportedTypes.includes(responseType);
    }

    /**
     * 验证授权类型
     */
    static isValidGrantType(grantType: string, supportedTypes: string[]): boolean {
        if (!grantType || typeof grantType !== 'string') {
            return false;
        }

        return supportedTypes.includes(grantType);
    }

    /**
     * 验证客户端ID格式
     */
    static isValidClientId(clientId: string): boolean {
        if (!clientId || typeof clientId !== 'string') {
            return false;
        }

        // 客户端ID应该是非空字符串，长度在3-128之间
        return clientId.length >= 3 && clientId.length <= 128;
    }

    /**
     * 验证状态参数
     */
    static isValidState(state: string): boolean {
        if (!state || typeof state !== 'string') {
            return false;
        }

        // 状态参数应该是非空字符串，长度不超过512
        return state.length > 0 && state.length <= 512;
    }

    /**
     * 验证随机数
     */
    static isValidNonce(nonce: string): boolean {
        if (!nonce || typeof nonce !== 'string') {
            return false;
        }

        // 随机数应该是非空字符串，长度不超过512
        return nonce.length > 0 && nonce.length <= 512;
    }

    /**
     * 验证授权请求
     */
    static validateAuthorizationRequest(
        request: Partial<AuthorizationRequest>,
        client: OIDCClient,
        supportedScopes: string[],
        supportedResponseTypes: string[]
    ): { valid: boolean; errors: string[] } {
        const errors: string[] = [];

        // 验证响应类型
        if (!request.response_type) {
            errors.push('Missing response_type parameter');
        } else if (!ValidationUtils.isValidResponseType(request.response_type, supportedResponseTypes)) {
            errors.push('Invalid or unsupported response_type');
        } else if (!client.response_types.includes(request.response_type)) {
            errors.push('Response type not allowed for this client');
        }

        // 验证客户端ID
        if (!request.client_id) {
            errors.push('Missing client_id parameter');
        } else if (request.client_id !== client.client_id) {
            errors.push('Invalid client_id');
        }

        // 验证重定向URI
        if (!request.redirect_uri) {
            errors.push('Missing redirect_uri parameter');
        } else if (!ValidationUtils.isValidRedirectUri(request.redirect_uri)) {
            errors.push('Invalid redirect_uri format');
        } else if (!client.redirect_uris.includes(request.redirect_uri)) {
            errors.push('Redirect URI not registered for this client');
        }

        // 验证作用域
        if (!request.scope) {
            errors.push('Missing scope parameter');
        } else if (!ValidationUtils.isValidScope(request.scope, supportedScopes)) {
            errors.push('Invalid or unsupported scope');
        } else {
            const requestedScopes = request.scope.split(' ');
            const allowedScopes = client.scopes;
            if (!requestedScopes.every(s => allowedScopes.includes(s))) {
                errors.push('Scope not allowed for this client');
            }
        }

        // 验证状态（可选）
        if (request.state && !ValidationUtils.isValidState(request.state)) {
            errors.push('Invalid state parameter');
        }

        // 验证随机数（可选）
        if (request.nonce && !ValidationUtils.isValidNonce(request.nonce)) {
            errors.push('Invalid nonce parameter');
        }

        // 验证PKCE参数（如果提供）
        if (request.code_challenge) {
            if (!request.code_challenge_method) {
                errors.push('Missing code_challenge_method when code_challenge is provided');
            } else if (!['plain', 'S256'].includes(request.code_challenge_method)) {
                errors.push('Unsupported code_challenge_method');
            }
        }

        return {
            valid: errors.length === 0,
            errors,
        };
    }

    /**
     * 验证令牌请求
     */
    static validateTokenRequest(
        request: Partial<TokenRequest>,
        client: OIDCClient,
        supportedGrantTypes: string[]
    ): { valid: boolean; errors: string[] } {
        const errors: string[] = [];

        // 验证授权类型
        if (!request.grant_type) {
            errors.push('Missing grant_type parameter');
        } else if (!ValidationUtils.isValidGrantType(request.grant_type, supportedGrantTypes)) {
            errors.push('Invalid or unsupported grant_type');
        } else if (!client.grant_types.includes(request.grant_type)) {
            errors.push('Grant type not allowed for this client');
        }

        // 验证客户端ID
        if (!request.client_id) {
            errors.push('Missing client_id parameter');
        } else if (request.client_id !== client.client_id) {
            errors.push('Invalid client_id');
        }

        // 根据授权类型进行特定验证
        if (request.grant_type === 'authorization_code') {
            if (!request.code) {
                errors.push('Missing code parameter for authorization_code grant');
            }
            if (!request.redirect_uri) {
                errors.push('Missing redirect_uri parameter for authorization_code grant');
            }
        } else if (request.grant_type === 'refresh_token') {
            if (!request.refresh_token) {
                errors.push('Missing refresh_token parameter for refresh_token grant');
            }
        }

        return {
            valid: errors.length === 0,
            errors,
        };
    }

    /**
     * 验证用户信息请求的访问令牌
     */
    static validateBearerToken(authorizationHeader: string | undefined): string | null {
        if (!authorizationHeader) {
            return null;
        }

        const parts = authorizationHeader.split(' ');
        if (parts.length !== 2 || parts[0]?.toLowerCase() !== 'bearer') {
            return null;
        }

        const token = parts[1];
        if (!token || token.length === 0) {
            return null;
        }

        return token;
    }

    /**
     * 验证邮箱格式
     */
    static isValidEmail(email: string): boolean {
        const emailSchema = z.string().email();
        try {
            emailSchema.parse(email);
            return true;
        } catch {
            return false;
        }
    }

    /**
     * 验证URL格式
     */
    static isValidUrl(url: string): boolean {
        try {
            new URL(url);
            return true;
        } catch {
            return false;
        }
    }

    /**
     * 验证电话号码格式（简单验证）
     */
    static isValidPhoneNumber(phone: string): boolean {
        // 简单的电话号码验证，支持国际格式
        const phoneRegex = /^\+?[1-9]\d{1,14}$/;
        return phoneRegex.test(phone);
    }

    /**
     * 验证日期格式（YYYY-MM-DD）
     */
    static isValidBirthdate(birthdate: string): boolean {
        const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
        if (!dateRegex.test(birthdate)) {
            return false;
        }

        const date = new Date(birthdate);
        return !isNaN(date.getTime());
    }

    /**
     * 验证时区格式
     */
    static isValidZoneinfo(zoneinfo: string): boolean {
        try {
            // 尝试使用Intl.DateTimeFormat验证时区
            Intl.DateTimeFormat(undefined, { timeZone: zoneinfo });
            return true;
        } catch {
            return false;
        }
    }

    /**
     * 验证语言标签格式
     */
    static isValidLocale(locale: string): boolean {
        // 简单的语言标签验证（如：en, en-US, zh-CN）
        const localeRegex = /^[a-z]{2,3}(-[A-Z]{2})?$/;
        return localeRegex.test(locale);
    }
} 