/**
 * 认证核心逻辑
 * 实现OAuth2授权码模式的完整流程
 */

import {EventType, RouterInfo, SDKConfig, UserInfo} from '../types';
import {TokenManager} from './token';
import {HttpClient} from './http';
import {Storage} from '../utils/storage';
import {buildQueryParams, isCallbackUrl, parseQueryParams} from '../utils/url';

/**
 * 认证核心类
 */
export class Auth {
  private config: SDKConfig | null = null;
  private tokenManager!: TokenManager;
  private httpClient: HttpClient;
  private readonly storage: Storage;
  private eventHandlers: Record<EventType, Function[]> = {
    login: [],
    logout: [],
    tokenExpired: []
  };
  private userInfoCache: UserInfo | null = null;

  /**
   * 构造函数
   * @param storage 存储实例
   */
  constructor(storage: Storage) {
    this.storage = storage;
    // 创建带有基础配置的HttpClient
    this.httpClient = new HttpClient({
      timeout: 15000,
      withCredentials: true
    });
  }

  /**
   * 初始化SDK配置
   * @param config SDK配置选项
   */
  init(config: SDKConfig): void {
    this.config = config;
    
    // 更新HTTP客户端配置
    this.httpClient.updateConfig({
      baseURL: config.basepath || '',
      tenantId: config.tenantId
    });
    
    // 创建TokenManager
    this.tokenManager = new TokenManager(this.storage, this.config.clientId);
    
    // 设置Token获取函数
    this.httpClient.setTokenGetter(() => this.getToken());
  }

  getToken():string | null{
    return this.tokenManager.getToken()
  }

  /**
   * 触发登录流程
   * @param redirectUri 可选的重定向URL，覆盖初始化时的配置
   */
  async login(redirectUri?: string): Promise<void> {
    if (!this.config) {
      throw new Error('SDK not initialized');
    }
    const registrationId = this.config.registrationId || 'idp'
    const path = `/oauth2/authorization/${registrationId}`
    const tokenResponse = await this.httpClient.get(path,{needAuth:false})
    const redirect = tokenResponse.data.redirect_url
    const params = parseQueryParams(redirect)
    
    // 安全存储当前页面URL用于回调后重定向
    if (params.state) {
      // 确保存储的URL是有效的
      const currentUrl = redirectUri || window.location.href;
      const safeUrl = currentUrl && typeof currentUrl === 'string' ? currentUrl : '/';
      this.storage.set(params.state, safeUrl);
      console.log('💾 存储重定向状态:', params.state, '->', safeUrl);
    }
    
    window.location.href = redirect
  }

  /**
   * 退出登录
   */
  async logout(): Promise<void> {
    if (!this.config) {
      throw new Error('SDK not initialized');
    }
    // 清除本地存储的Token和用户信息缓存
    this.tokenManager.clearToken();
    this.userInfoCache = null;
    await this.httpClient.post(`/logout`,null,{needAuth:true})
    // 触发退出事件
    this.emit('logout');
    window.location.href = this.config.idpLogoutUrl+'?redirect='+this.config.homePage;
  }

  /**
   * 处理授权回调
   * @returns Promise<UserInfo> 用户信息
   */
  async handleCallback(): Promise<void> {
    if (!this.config) {
      throw new Error('SDK not initialized');
    }

    const params = parseQueryParams();
    
    // 检查是否有错误
    if (params.error) {
      throw new Error(`Authorization error: ${params.error} - ${params.error_description || ''}`);
    }

    // 检查是否有授权码
    if (!params.code) {
      throw new Error('Authorization code not found');
    }

      const registrationId = this.config.registrationId || 'idp'
      const callback = `/login/oauth2/code/${registrationId}${buildQueryParams(params)}`
      const tokenResponse = await this.httpClient.get(callback,{
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        needAuth: false
      })
      // 触发登录事件
      this.emit('login');
      // 缓存用户信息
      this.userInfoCache = tokenResponse.data.data;
      this.tokenManager.saveToken(tokenResponse.headers['authorization']||tokenResponse.headers['Authorization'])
      // 安全处理重定向URL
      let redirectUrl = this.config.homePage || '/';
      
      if (params.state) {
        const storedUrl = this.storage.get(params.state);
        if (storedUrl && typeof storedUrl === 'string') {
          redirectUrl = storedUrl;
        }
        this.storage.remove(params.state);
      }
      
      // 确保URL格式正确
      if (!redirectUrl.startsWith('http') && !redirectUrl.startsWith('/')) {
        redirectUrl = '/' + redirectUrl;
      }
      
      console.log('🔄 重定向到:', redirectUrl);
      window.location.href = redirectUrl;

  }

  async getRoutes(): Promise<RouterInfo> {
    if (!this.config) {
      throw new Error('SDK not initialized');
    }
    const tokenResponse = await this.httpClient.get(`/idp/routes`,{needAuth:true})
    if(tokenResponse.status===401){
      await this.logout()
    }
    return tokenResponse.data.data

  }
  /**
   * 刷新用户信息缓存
   * @returns Promise<UserInfo> 更新后的用户信息
   */
  async refreshUserInfo(): Promise<UserInfo> {
    console.log('🔄 刷新用户信息缓存...');
    this.userInfoCache = null; // 清除缓存
    return await this.getUserInfo(); // 重新获取
  }

  /**
   * 获取用户信息
   * @returns UserInfo 用户信息
   */
  async getUserInfo(): Promise<UserInfo> {
    // 首先检查缓存
    if (this.userInfoCache) {
      console.log('📋 从缓存获取用户信息');
      return this.userInfoCache;
    }
    
    // 检查是否已认证
    if (!this.isAuthenticated()) {
      throw new Error('User not authenticated');
    }
    
    try {
      // 从后端接口获取用户信息
      console.log('🌐 从后端获取用户信息...');
      const response = await this.httpClient.get('/idp/getUserInfo', { needAuth: true });
      this.userInfoCache = response.data;
      console.log('✅ 用户信息获取成功');
      return this.userInfoCache!;
    } catch (error) {
      console.error('❌ 获取用户信息失败:', error);
      throw error;
    }
  }




  /**
   * 检查用户是否有指定角色
   * @param role 角色编码或角色编码列表
   * @returns Promise<boolean> 是否有指定角色
   */
  async hasRole(role: string | string[]): Promise<boolean> {
    if (!this.isAuthenticated()) {
      return false;
    }

    const userInfo = await this.getUserInfo();
    const roleCodes = userInfo.roles||[];

    if (Array.isArray(role)) {
      // 检查是否有任一角色
      return role.some(r => roleCodes.includes(r));
    }

    // 检查是否有单个角色
    return roleCodes.includes(role);
  }

  /**
   * 检查用户是否有所有指定角色
   * @param roles 角色编码列表
   * @returns Promise<boolean> 是否有所有指定角色
   */
  async hasAllRoles(roles: string[]): Promise<boolean> {
    if (!this.isAuthenticated()) {
      return false;
    }

    const userInfo = await this.getUserInfo();
    const roleCodes = userInfo.roles||[];
    // 检查是否有所有角色
    return roles.every(r => roleCodes.includes(r));
  }

  /**
   * 检查用户是否有指定权限
   * @param permission 权限标识或权限标识列表
   * @returns Promise<boolean> 是否有指定权限
   */
  async hasPermission(permission: string | string[]): Promise<boolean> {
    if (!this.isAuthenticated()) {
      return false;
    }

    const userInfo = await this.getUserInfo();
    const permissions = userInfo.permissions||[];

    if (Array.isArray(permission)) {
      // 检查是否有任一权限
      return permission.some(p => permissions.includes(p));
    }

    // 检查是否有单个权限
    return permissions.includes(permission);
  }

  /**
   * 检查用户是否有所有指定权限
   * @param permissions 权限标识列表
   * @returns Promise<boolean> 是否有所有指定权限
   */
  async hasAllPermissions(permissions: string[]): Promise<boolean> {
    if (!this.isAuthenticated()) {
      return false;
    }

    const userInfo = await this.getUserInfo();
    const userPermissions = userInfo.permissions||[];

    // 检查是否有所有权限
    return permissions.every(p => userPermissions.includes(p));
  }

  /**
   * 检查用户是否已认证
   * @returns boolean 是否已认证
   */
  isAuthenticated(): boolean {
    // 检查Token是否存在且未过期
    return !!this.tokenManager.getToken();
  }

  /**
   * 事件监听
   * @param event 事件类型
   * @param callback 回调函数
   */
  on(event: EventType, callback: Function): void {
    this.eventHandlers[event].push(callback);
  }

  /**
   * 移除事件监听
   * @param event 事件类型
   * @param callback 回调函数
   */
  off(event: EventType, callback: Function): void {
    this.eventHandlers[event] = this.eventHandlers[event].filter(handler => handler !== callback);
  }

  /**
   * 触发事件
   * @param event 事件类型
   * @param data 事件数据
   */
  private emit(event: EventType, data?: any): void {
    this.eventHandlers[event].forEach(handler => {
      try {
        handler(data);
      } catch (error) {
        console.error(`Error in ${event} event handler:`, error);
      }
    });
  }

  /**
   * 检查当前URL是否为授权回调
   * @returns boolean 是否为授权回调
   */
  isCallback(): boolean {
    return isCallbackUrl();
  }
}
