'use client';

import { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { oidcClient } from '@/lib/auth/oidc-client';
import { TokenManager } from '@/lib/auth/token-manager';
import { useTRPC } from '@fenghuo/client';
import { useQuery } from '@tanstack/react-query';
import {
    SystemPermission,
    PermissionUtils,
    SystemRole,
    SystemRoleConfig,
    type PermissionMeta,
    UserWithRelations,
    userWithRelationsSelect
} from '@fenghuo/common';
import { useToken } from '@/components/providers/token-provider';
import { Prisma, Role } from '@fenghuo/db/index';


// 导出权限相关类型和工具
export {
    SystemPermission,
    PermissionUtils,
    SystemRole,
    SystemRoleConfig,
    type PermissionMeta
} from '@fenghuo/common';

// 扩展用户接口
export interface User extends Omit<UserWithRelations, 'roles'> {
    roles: string[]; // 角色名称数组
    permissions?: SystemPermission[]; // 使用新的权限系统
}

interface AuthProviderProps {
    children: React.ReactNode;
}

interface AuthContextType {
    // 用户状态
    user: User | null;
    isLoading: boolean;
    isAuthenticated: boolean;

    // 权限检查方法
    hasRole: (role: string) => boolean;
    hasPermission: (permission: SystemPermission) => boolean;
    hasAnyRole: (roles: string[]) => boolean;
    hasAnyPermission: (permissions: SystemPermission[]) => boolean;
    hasAllPermissions: (permissions: SystemPermission[]) => boolean;
    isSuperAdmin: () => boolean;
    isAdmin: () => boolean;

    // 认证操作
    login: (username: string, password: string) => Promise<void>;
    register: (userData: Prisma.UserCreateArgs) => Promise<void>;
    logout: () => Promise<void>;
    getAccessToken: () => Promise<string | null>;
    loadUser: () => Promise<void>;
}

const AuthContext = createContext<AuthContextType | null>(null);

export default function AuthProvider({ children }: AuthProviderProps) {
    const { refreshToken, clearTokens } = useToken();
    const [userId, setUserId] = useState<string | null>(null);
    const [user, setUser] = useState<User | null>(null);
    const [isLoading, setIsLoading] = useState(true);
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    const trpc = useTRPC();

    // 修改 tRPC 查询，包含角色权限
    const { data: backendUser, error: userError, isLoading: isUserLoading } = useQuery({
        ...trpc.user.findFirst.queryOptions({
            where: { id: userId! },
            select: userWithRelationsSelect
        }),
        enabled: !!userId,
        retry: false,
    }) as { data: UserWithRelations | null, error: Error | null, isLoading: boolean };

    // 更新用户状态当后端用户数据加载完成时
    useEffect(() => {
        if (backendUser) {
            const userRoles = backendUser.roles?.map(r => r.slug) || [];
            // 传递完整的角色数据给权限计算函数
            const userPermissions = getUserPermissions(backendUser.roles || []);
            const appUser: User = {
                ...backendUser,
                roles: userRoles,
                permissions: userPermissions,
            };
            setUser(appUser);
        } else if (userError) {
            console.error('获取用户数据失败:', userError);
            setUser(null);
            setIsAuthenticated(false);
            TokenManager.clearTokens();
        }
    }, [backendUser, userError]);

    // 加载用户信息
    const loadUser = useCallback(async () => {
        setIsLoading(true);
        try {
            const accessToken = await TokenManager.getValidAccessToken();
            if (accessToken) {
                // 只获取 OIDC 用户信息来获得用户 ID
                const oidcUser = await oidcClient.getUserInfo(accessToken);
                setUserId(oidcUser.sub);
                setIsAuthenticated(true);

                // 触发 QueryProvider 刷新 token
                refreshToken();
            } else {
                setUserId(null);
                setUser(null);
                setIsAuthenticated(false);
                setIsLoading(false);
            }
        } catch (error) {
            console.error('加载用户信息失败:', error);
            setUserId(null);
            setUser(null);
            setIsAuthenticated(false);
            TokenManager.clearTokens();
            setIsLoading(false);
        }
    }, [refreshToken]);

    // 当 tRPC 查询完成时更新 loading 状态
    useEffect(() => {
        if (userId && !isUserLoading) {
            setIsLoading(false);
        }
    }, [userId, isUserLoading]);

    // 初始化时加载用户信息
    useEffect(() => {
        loadUser();
    }, [loadUser]);

    // 登录功能
    const login = useCallback(async (username: string, password: string): Promise<void> => {
        setIsLoading(true);
        try {
            // 调用 OIDC 服务登录
            const tokenResponse = await oidcClient.loginWithPassword(username, password);

            // 保存令牌
            TokenManager.saveTokens(tokenResponse);

            // 获取用户信息并设置 userId，让 tRPC 查询处理剩余逻辑
            const oidcUser = await oidcClient.getUserInfo(tokenResponse.access_token);
            setUserId(oidcUser.sub);
            setIsAuthenticated(true);

            // 登录成功后直接刷新token context
            await refreshToken();
        } catch (error) {
            console.error('登录失败:', error);
            throw error;
        } finally {
            setIsLoading(false);
        }
    }, [refreshToken]);

    // 注册功能
    const register = useCallback(async (userData: Prisma.UserCreateArgs): Promise<void> => {
        setIsLoading(true);
        try {
            await oidcClient.register(userData);
        } catch (error) {
            console.error('注册失败:', error);
            throw error;
        } finally {
            setIsLoading(false);
        }
    }, []);

    // 退出登录功能
    const logout = useCallback(async () => {
        setIsLoading(true);
        try {
            const accessToken = TokenManager.getAccessToken();
            if (accessToken) {
                await oidcClient.logout(accessToken);
            }
        } catch (error) {
            console.error('退出登录失败:', error);
        } finally {
            TokenManager.clearTokens();
            setUserId(null);
            setUser(null);
            setIsAuthenticated(false);
            setIsLoading(false);

            // 退出时清除token
            clearTokens();
        }
    }, [clearTokens]);

    // 获取访问令牌
    const getAccessToken = useCallback(async () => {
        return await TokenManager.getValidAccessToken();
    }, []);

    // 权限检查方法 - 使用新的权限系统
    const hasRole = useCallback((role: string): boolean => {
        return user?.roles.includes(role) || false;
    }, [user]);

    const hasPermission = useCallback((permission: SystemPermission): boolean => {
        if (!user?.permissions) return false;
        return PermissionUtils.hasPermission(user.permissions, permission);
    }, [user]);

    const hasAnyRole = useCallback((roles: string[]): boolean => {
        return roles.some(role => hasRole(role));
    }, [hasRole]);

    const hasAnyPermission = useCallback((permissions: SystemPermission[]): boolean => {
        if (!user?.permissions) return false;
        return PermissionUtils.hasAnyPermission(user.permissions, permissions);
    }, [user]);

    const hasAllPermissions = useCallback((permissions: SystemPermission[]): boolean => {
        if (!user?.permissions) return false;
        return PermissionUtils.hasAllPermissions(user.permissions, permissions);
    }, [user]);

    // 检查是否为超级管理员
    const isSuperAdmin = useCallback((): boolean => {
        return hasPermission(SystemPermission.SUPER_ADMIN);
    }, [hasPermission]);

    // 检查是否为管理员级别
    const isAdmin = useCallback((): boolean => {
        return hasRole(SystemRole.SUPER_ADMIN) || hasRole(SystemRole.ADMIN);
    }, [hasRole]);

    const contextValue: AuthContextType = {
        user,
        isLoading,
        isAuthenticated,
        hasRole,
        hasPermission,
        hasAnyRole,
        hasAnyPermission,
        hasAllPermissions,
        isSuperAdmin,
        isAdmin,
        login,
        register,
        logout,
        getAccessToken,
        loadUser,
    };

    return (
        <AuthContext.Provider value={contextValue}>
            {children}
        </AuthContext.Provider>
    );
}

export function useAuth() {
    const context = useContext(AuthContext);
    if (!context) {
        throw new Error('useAuth must be used within an AuthProvider');
    }
    return context;
}

// 计算用户权限 - 基于数据库角色权限
const getUserPermissions = (roles: Role[]): SystemPermission[] => {
    const permissions = new Set<SystemPermission>();

    roles.forEach((role) => {
        if (!role.permissions || !Array.isArray(role.permissions)) {
            console.warn('角色权限数据格式错误:', role);
            return;
        }

        role.permissions.forEach(permission => {
            if (PermissionUtils.isValidPermission(permission)) {
                permissions.add(permission as SystemPermission);
            } else {
                console.warn('无效的权限代码:', permission);
            }
        });
    });
    return Array.from(permissions);
};

// 权限检查工具函数 - 更新为使用新的权限系统
export const checkPermission = (userPermissions: SystemPermission[], requiredPermissions?: SystemPermission[]): boolean => {
    if (!requiredPermissions || requiredPermissions.length === 0) return true;
    return PermissionUtils.hasAnyPermission(userPermissions, requiredPermissions);
};

// 检查角色权限的工具函数
export const checkRole = (userRoles: string[], requiredRoles?: string[]): boolean => {
    if (!requiredRoles || requiredRoles.length === 0) return true;
    return requiredRoles.some(role => userRoles.includes(role));
};

// 过滤菜单项的工具函数 - 支持角色和权限检查
export const filterMenuItems = <T extends { roles?: string[]; permissions?: SystemPermission[] }>(
    items: T[],
    user: User | null
): T[] => {
    if (!user) return [];

    return items.filter(item => {
        // 检查角色要求
        if (item.roles && !checkRole(user.roles, item.roles)) {
            return false;
        }

        // 检查权限要求
        if (item.permissions && user.permissions && !checkPermission(user.permissions, item.permissions)) {
            return false;
        }

        return true;
    });
};