############################ Copyrights and license ############################
#                                                                              #
# Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net>                 #
# Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net>                 #
# Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com>          #
# Copyright 2018 Wan Liuyang <tsfdye@gmail.com>                                #
# Copyright 2018 sfdye <tsfdye@gmail.com>                                      #
# Copyright 2019 Steve Kowalik <steven@wedontsleep.org>                        #
# Copyright 2019 TechnicalPirate <35609336+TechnicalPirate@users.noreply.github.com>#
# Copyright 2019 Wan Liuyang <tsfdye@gmail.com>                                #
# Copyright 2020 Steve Kowalik <steven@wedontsleep.org>                        #
# Copyright 2023 Enrico Minack <github@enrico.minack.dev>                      #
# Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com>        #
# Copyright 2024 Enrico Minack <github@enrico.minack.dev>                      #
# Copyright 2025 Enrico Minack <github@enrico.minack.dev>                      #
#                                                                              #
# This file is part of PyGithub.                                               #
# http://pygithub.readthedocs.io/                                              #
#                                                                              #
# PyGithub is free software: you can redistribute it and/or modify it under    #
# the terms of the GNU Lesser General Public License as published by the Free  #
# Software Foundation, either version 3 of the License, or (at your option)    #
# any later version.                                                           #
#                                                                              #
# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY  #
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    #
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
# details.                                                                     #
#                                                                              #
# You should have received a copy of the GNU Lesser General Public License     #
# along with PyGithub. If not, see <http://www.gnu.org/licenses/>.             #
#                                                                              #
################################################################################

import github.GithubObject

from . import Framework


class ExposeAllAttributes(Framework.TestCase):
    def testAllClasses(self):
        authenticatedUser = self.g.get_user()
        namedUser = self.g.get_user("nvie")
        repository = authenticatedUser.get_repo("PyGithub")
        organization = self.g.get_organization("BeaverSoftware")
        plan = authenticatedUser.plan
        branch = repository.get_branch("master")
        commit = repository.get_commit("1292bf0e22c796e91cc3d6e24b544aece8c21f2a")
        commitStats = commit.stats
        commitStatus = commit.get_statuses()[0]
        milestone = repository.get_milestone(17)
        gist = self.g.get_gist("149016")
        gistComment = gist.get_comment(4565)
        gistFile = gist.files[".gitignore"]
        gistHistoryState = gist.history[0]
        gitCommit = repository.get_git_commit("be37b8a7f3a68631c32672dcd84d9eba27438ee6")
        gitAuthor = gitCommit.author
        gitTree = repository.get_git_tree("6f7c2d8c66d78863f7b91792deaead619799a1ce")
        gitTreeElement = gitTree.tree[0]
        gitBlob = repository.get_git_blob("681fb61f1761743a02f5c790f1c762cbfe8cfad1")
        gitRef = repository.get_git_ref("tags/v1.17.0")
        gitObject = gitRef.object
        issue = repository.get_issue(188)
        issueComment = issue.get_comment(22686536)
        issueEvent = issue.get_events()[0]
        issuePullRequest = issue.pull_request
        gitignoreTemplate = self.g.get_gitignore_template("Python")
        team = organization.get_team(141487)
        label = repository.get_label("Bug")
        pullRequest = repository.get_pull(31)
        pullRequestComment = pullRequest.get_review_comment(1580134)
        pullRequestPart = pullRequest.base
        file = pullRequest.get_files()[0]
        commitComment = repository.get_comment(3630301)
        rateLimit = self.g.get_rate_limit()
        hook = repository.get_hooks()[0]
        hookResponse = hook.last_response
        hookDescription = self.g.get_hooks()[0]
        comparison = repository.compare("master", "develop")
        contentFile = repository.get_contents("README.rst")
        permissions = repository.permissions
        event = repository.get_events()[0]
        notification = authenticatedUser.get_notification("8406712")
        notificationSubject = notification.subject

        missingAttributes = self.gatherMissingAttributes(
            [
                authenticatedUser,
                # authorization,  # Security issue if put as-is in ReplayData
                # authorizationApplication,  # Security issue if put as-is in ReplayData
                branch,
                commit,
                commitComment,
                commitStats,
                commitStatus,
                comparison,
                contentFile,
                # download,  # Deprecated: https://github.com/blog/1302-goodbye-uploads
                event,
                file,
                gist,
                gistComment,
                gistFile,
                gistHistoryState,
                gitAuthor,
                gitBlob,
                gitCommit,
                gitignoreTemplate,
                gitObject,
                gitRef,
                # gitTag,
                gitTree,
                gitTreeElement,
                hook,
                hookDescription,
                hookResponse,
                issue,
                issueComment,
                issueEvent,
                issuePullRequest,
                label,
                milestone,
                namedUser,
                notification,
                notificationSubject,
                organization,
                permissions,
                plan,
                pullRequest,
                pullRequestComment,
                # pullRequestMergeStatus,  # Only obtained when merging a pull request through the API
                pullRequestPart,
                rateLimit,
                repository,
                # repositoryKey,  # Security issue if put as-is in ReplayData
                # tag,
                team,
                # userKey,  # Security issue if put as-is in ReplayData
            ]
        )

        for className, attributesMissingInClass in sorted(missingAttributes.items()):
            for attrName, value in sorted(attributesMissingInClass.items()):
                print(className, attrName, "->", repr(value))

        self.assertEqual(sum(len(attrs) for attrs in missingAttributes.values()), 0)

    def findMissingAttributes(self, obj):
        if isinstance(obj, github.GithubObject.CompletableGithubObject):
            obj.update()
        className = obj.__class__.__name__
        missingAttributes = {}
        for attribute in obj.raw_data:
            if attribute != "_links":
                if not hasattr(obj, attribute):
                    missingAttributes[attribute] = obj.raw_data[attribute]
        return (className, missingAttributes)

    def gatherMissingAttributes(self, objs):
        allMissingAttributes = dict()

        for obj in objs:
            className, attributesMissingInClass = self.findMissingAttributes(obj)
            if len(attributesMissingInClass) > 0:
                if className not in allMissingAttributes:
                    allMissingAttributes[className] = dict()
                allMissingAttributes[className].update(attributesMissingInClass)

        return allMissingAttributes
