name: PR Gate

on:
  pull_request_target:
    types: [opened]

jobs:
  check-contributor:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write
      pull-requests: write
    steps:
      - name: Check if contributor is approved
        uses: actions/github-script@v7
        with:
          script: |
            const prAuthor = context.payload.pull_request.user.login;
            const defaultBranch = context.payload.repository.default_branch;

            if (prAuthor.endsWith('[bot]') || prAuthor === 'dependabot[bot]') {
              console.log(`Skipping bot: ${prAuthor}`);
              return;
            }

            async function getPermission(username) {
              try {
                const { data: permissionLevel } = await github.rest.repos.getCollaboratorPermissionLevel({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  username,
                });
                return permissionLevel.permission;
              } catch {
                return null;
              }
            }

            async function getTextFile(path) {
              const { data: fileContent } = await github.rest.repos.getContent({
                owner: context.repo.owner,
                repo: context.repo.repo,
                path,
                ref: defaultBranch,
              });

              if (!('content' in fileContent) || typeof fileContent.content !== 'string') {
                throw new Error(`Expected file content for ${path}`);
              }

              return Buffer.from(fileContent.content, 'base64').toString('utf8');
            }

            async function closePullRequest(message) {
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: context.payload.pull_request.number,
                body: message,
              });

              await github.rest.pulls.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                pull_number: context.payload.pull_request.number,
                state: 'closed',
              });
            }

            const permission = await getPermission(prAuthor);
            if (['admin', 'maintain', 'write'].includes(permission)) {
              console.log(`${prAuthor} is a collaborator with ${permission} access`);
              return;
            }

            const approvedContent = await getTextFile('.github/APPROVED_CONTRIBUTORS');
            const approvedList = approvedContent
              .split('\n')
              .map(line => line.trim().toLowerCase())
              .filter(line => line && !line.startsWith('#'));
            const isApprovedContributor = approvedList.includes(prAuthor.toLowerCase());

            let weekendState = null;
            try {
              weekendState = JSON.parse(await getTextFile('.github/oss-weekend.json'));
            } catch (error) {
              if (!(error && typeof error === 'object' && 'status' in error && error.status === 404)) {
                throw error;
              }
            }

            if (weekendState?.active && isApprovedContributor) {
              console.log(`${prAuthor} is approved, but OSS weekend is active`);

              const reopenDate = weekendState.reopensOnText || weekendState.reopensOn || 'after the weekend';
              const discordUrl = weekendState.discordUrl || 'https://discord.com/invite/3cU7Bz4UPx';
              const message = [
                `Hi @${prAuthor}, thanks for the PR.`,
                '',
                `OSS weekend is active until ${reopenDate}, so external PRs are being paused for now.`,
                '',
                'You are already on the approved contributors list, so you can resubmit this PR after the weekend without reapproval.',
                '',
                `This PR will be closed automatically. For support, join [Discord](${discordUrl}).`,
              ].join('\n');

              await closePullRequest(message);
              return;
            }

            if (isApprovedContributor) {
              console.log(`${prAuthor} is in the approved contributors list`);
              return;
            }

            console.log(`${prAuthor} is not approved, closing PR`);

            const message = [
              `Hi @${prAuthor}, thanks for your interest in contributing!`,
              '',
              'We ask new contributors to open an issue first before submitting a PR. This helps us discuss the approach and avoid wasted effort.',
              '',
              '**Next steps:**',
              '1. Open an issue describing what you want to change and why (keep it concise, write in your human voice, AI slop will be closed)',
              '2. Once a maintainer approves with `lgtm`, you\'ll be added to the approved contributors list',
              '3. Then you can submit your PR',
              '',
              `This PR will be closed automatically. See https://github.com/${context.repo.owner}/${context.repo.repo}/blob/${defaultBranch}/CONTRIBUTING.md for more details.`,
            ].join('\n');

            await closePullRequest(message);
