export enum MediaPermission {
  VIEW = "view",
  UPLOAD = "upload",
  EDIT = "edit",
  DELETE = "delete",
  MANAGE_PERMISSIONS = "manage_permissions",
  DOWNLOAD = "download",
  SHARE = "share",
}

export enum MediaRole {
  ADMIN = "admin",
  EDITOR = "editor",
  AUTHOR = "author",
  CONTRIBUTOR = "contributor",
  SUBSCRIBER = "subscriber",
  GUEST = "guest",
}

export interface MediaUser {
  id: string;
  role: MediaRole;
  permissions?: MediaPermission[];
  folders?: string[]; // 접근 가능한 폴더 ID 목록
}

export interface MediaFolder {
  id: string;
  name: string;
  parentId?: string;
  ownerId: string;
  permissions: MediaFolderPermission[];
  inheritParentPermissions: boolean;
  isPublic: boolean;
  createdAt: Date;
  updatedAt: Date;
}

export interface MediaFolderPermission {
  id: string;
  folderId: string;
  userId?: string;
  roleId?: MediaRole;
  permissions: MediaPermission[];
  allowInheritance: boolean;
  createdAt: Date;
}

export interface MediaCollection {
  id: string;
  name: string;
  description?: string;
  ownerId: string;
  permissions: MediaCollectionPermission[];
  isPublic: boolean;
  tags: string[];
  createdAt: Date;
  updatedAt: Date;
}

export interface MediaCollectionPermission {
  id: string;
  collectionId: string;
  userId?: string;
  roleId?: MediaRole;
  permissions: MediaPermission[];
  createdAt: Date;
}

// 기본 역할별 권한 매핑
export const DEFAULT_ROLE_PERMISSIONS: Record<MediaRole, MediaPermission[]> = {
  [MediaRole.ADMIN]: [
    MediaPermission.VIEW,
    MediaPermission.UPLOAD,
    MediaPermission.EDIT,
    MediaPermission.DELETE,
    MediaPermission.MANAGE_PERMISSIONS,
    MediaPermission.DOWNLOAD,
    MediaPermission.SHARE,
  ],
  [MediaRole.EDITOR]: [
    MediaPermission.VIEW,
    MediaPermission.UPLOAD,
    MediaPermission.EDIT,
    MediaPermission.DELETE,
    MediaPermission.DOWNLOAD,
    MediaPermission.SHARE,
  ],
  [MediaRole.AUTHOR]: [
    MediaPermission.VIEW,
    MediaPermission.UPLOAD,
    MediaPermission.EDIT,
    MediaPermission.DOWNLOAD,
    MediaPermission.SHARE,
  ],
  [MediaRole.CONTRIBUTOR]: [
    MediaPermission.VIEW,
    MediaPermission.UPLOAD,
    MediaPermission.DOWNLOAD,
  ],
  [MediaRole.SUBSCRIBER]: [MediaPermission.VIEW, MediaPermission.DOWNLOAD],
  [MediaRole.GUEST]: [MediaPermission.VIEW],
};

export class MediaPermissionService {
  /**
   * 사용자가 특정 작업을 수행할 권한이 있는지 확인
   */
  hasPermission(
    user: MediaUser,
    permission: MediaPermission,
    context?: {
      folderId?: string;
      collectionId?: string;
      fileId?: string;
      ownerId?: string;
    }
  ): boolean {
    // 관리자는 모든 권한 보유
    if (user.role === MediaRole.ADMIN) {
      return true;
    }

    // 소유자는 MANAGE_PERMISSIONS를 제외한 모든 권한 보유
    if (
      context?.ownerId === user.id &&
      permission !== MediaPermission.MANAGE_PERMISSIONS
    ) {
      return true;
    }

    // 사용자별 직접 권한 확인
    if (user.permissions?.includes(permission)) {
      return true;
    }

    // 역할 기반 기본 권한 확인
    const rolePermissions = DEFAULT_ROLE_PERMISSIONS[user.role];
    if (rolePermissions.includes(permission)) {
      return true;
    }

    // 폴더별 권한 확인
    if (context?.folderId) {
      return this.hasFolderPermission(user, permission, context.folderId);
    }

    // 컬렉션별 권한 확인
    if (context?.collectionId) {
      return this.hasCollectionPermission(
        user,
        permission,
        context.collectionId
      );
    }

    return false;
  }

  /**
   * 폴더별 권한 확인 (상속 포함)
   */
  private hasFolderPermission(
    _user: MediaUser,
    _permission: MediaPermission,
    _folderId: string
  ): boolean {
    // 실제 구현에서는 데이터베이스에서 폴더 권한 조회
    // 여기서는 Mock 구현
    return true;
  }

  /**
   * 컬렉션별 권한 확인
   */
  private hasCollectionPermission(
    _user: MediaUser,
    _permission: MediaPermission,
    _collectionId: string
  ): boolean {
    // 실제 구현에서는 데이터베이스에서 컬렉션 권한 조회
    // 여기서는 Mock 구현
    return true;
  }

  /**
   * 사용자가 접근 가능한 폴더 목록 반환
   */
  async getAccessibleFolders(_user: MediaUser): Promise<MediaFolder[]> {
    // 실제 구현에서는 데이터베이스에서 조회
    return [];
  }

  /**
   * 사용자가 접근 가능한 컬렉션 목록 반환
   */
  async getAccessibleCollections(_user: MediaUser): Promise<MediaCollection[]> {
    // 실제 구현에서는 데이터베이스에서 조회
    return [];
  }

  /**
   * 폴더에 사용자 권한 추가
   */
  async addFolderPermission(
    folderId: string,
    userId: string,
    permissions: MediaPermission[],
    grantedBy: string
  ): Promise<MediaFolderPermission> {
    // 실제 구현에서는 데이터베이스에 저장
    const permission: MediaFolderPermission = {
      id: `perm_${Date.now()}`,
      folderId,
      userId,
      permissions,
      allowInheritance: true,
      createdAt: new Date(),
    };

    // 감사 로그 기록
    await this.logPermissionChange({
      action: "add_folder_permission",
      resourceType: "folder",
      resourceId: folderId,
      targetUserId: userId,
      permissions,
      grantedBy,
    });

    return permission;
  }

  /**
   * 컬렉션에 사용자 권한 추가
   */
  async addCollectionPermission(
    collectionId: string,
    userId: string,
    permissions: MediaPermission[],
    grantedBy: string
  ): Promise<MediaCollectionPermission> {
    // 실제 구현에서는 데이터베이스에 저장
    const permission: MediaCollectionPermission = {
      id: `perm_${Date.now()}`,
      collectionId,
      userId,
      permissions,
      createdAt: new Date(),
    };

    // 감사 로그 기록
    await this.logPermissionChange({
      action: "add_collection_permission",
      resourceType: "collection",
      resourceId: collectionId,
      targetUserId: userId,
      permissions,
      grantedBy,
    });

    return permission;
  }

  /**
   * 권한 변경 사항 로깅
   */
  private async logPermissionChange(data: {
    action: string;
    resourceType: string;
    resourceId: string;
    targetUserId: string;
    permissions: MediaPermission[];
    grantedBy: string;
  }): Promise<void> {
    // 감사 로그 서비스에 기록
    console.log("Permission change logged:", data);
  }

  /**
   * 폴더 권한 상속 처리
   */
  async inheritFolderPermissions(
    _parentFolderId: string,
    _childFolderId: string
  ): Promise<void> {
    // 부모 폴더의 권한을 자식 폴더에 상속
    // 실제 구현에서는 데이터베이스 작업
  }

  /**
   * 사용자 권한 검증 미들웨어
   */
  createPermissionMiddleware(requiredPermission: MediaPermission) {
    return (user: MediaUser, context?: Record<string, unknown>) => {
      return this.hasPermission(user, requiredPermission, context);
    };
  }
}

// 싱글톤 인스턴스
let permissionServiceInstance: MediaPermissionService | null = null;

export function getMediaPermissionService(): MediaPermissionService {
  if (!permissionServiceInstance) {
    permissionServiceInstance = new MediaPermissionService();
  }
  return permissionServiceInstance;
}
