const {
  BOT_COMMENT_MARKER,
  CODEOWNERS_MARKER,
  TOO_BIG_MARKER,
  DEPRECATED_COMPONENT_MARKER
} = require('./constants');

// Generate review messages
function generateReviewMessages(finalLabels, originalLabelCount, deprecatedInfo, prFiles, totalAdditions, totalDeletions, prAuthor, MAX_LABELS, TOO_BIG_THRESHOLD) {
  const messages = [];

  // Deprecated component message
  if (finalLabels.includes('deprecated-component') && deprecatedInfo && deprecatedInfo.length > 0) {
    let message = `${DEPRECATED_COMPONENT_MARKER}\n### ⚠️ Deprecated Component\n\n`;
    message += `Hey there @${prAuthor},\n`;
    message += `This PR modifies one or more deprecated components. Please be aware:\n\n`;

    for (const info of deprecatedInfo) {
      message += `#### Component: \`${info.component}\`\n`;
      message += `${info.message}\n\n`;
    }

    message += `Consider migrating to the recommended alternative if applicable.`;

    messages.push(message);
  }

  // Too big message
  if (finalLabels.includes('too-big')) {
    const testAdditions = prFiles
      .filter(file => file.filename.startsWith('tests/'))
      .reduce((sum, file) => sum + (file.additions || 0), 0);
    const testDeletions = prFiles
      .filter(file => file.filename.startsWith('tests/'))
      .reduce((sum, file) => sum + (file.deletions || 0), 0);
    const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions);

    const tooManyLabels = originalLabelCount > MAX_LABELS;
    const tooManyChanges = nonTestChanges > TOO_BIG_THRESHOLD;

    let message = `${TOO_BIG_MARKER}\n### 📦 Pull Request Size\n\n`;

    if (tooManyLabels && tooManyChanges) {
      message += `This PR is too large with ${nonTestChanges} line changes (excluding tests) and affects ${originalLabelCount} different components/areas.`;
    } else if (tooManyLabels) {
      message += `This PR affects ${originalLabelCount} different components/areas.`;
    } else {
      message += `This PR is too large with ${nonTestChanges} line changes (excluding tests).`;
    }

    message += ` Please consider breaking it down into smaller, focused PRs to make review easier and reduce the risk of conflicts.\n\n`;
    message += `For guidance on breaking down large PRs, see: https://developers.esphome.io/contributing/submitting-your-work/#how-to-approach-large-submissions`;

    messages.push(message);
  }

  // CODEOWNERS message
  if (finalLabels.includes('needs-codeowners')) {
    const message = `${CODEOWNERS_MARKER}\n### 👥 Code Ownership\n\n` +
      `Hey there @${prAuthor},\n` +
      `Thanks for submitting this pull request! Can you add yourself as a codeowner for this integration? ` +
      `This way we can notify you if a bug report for this integration is reported.\n\n` +
      `In \`__init__.py\` of the integration, please add:\n\n` +
      `\`\`\`python\nCODEOWNERS = ["@${prAuthor}"]\n\`\`\`\n\n` +
      `And run \`script/build_codeowners.py\``;

    messages.push(message);
  }

  return messages;
}

// Handle reviews
async function handleReviews(github, context, finalLabels, originalLabelCount, deprecatedInfo, prFiles, totalAdditions, totalDeletions, MAX_LABELS, TOO_BIG_THRESHOLD) {
  const { owner, repo } = context.repo;
  const pr_number = context.issue.number;
  const prAuthor = context.payload.pull_request.user.login;

  const reviewMessages = generateReviewMessages(finalLabels, originalLabelCount, deprecatedInfo, prFiles, totalAdditions, totalDeletions, prAuthor, MAX_LABELS, TOO_BIG_THRESHOLD);
  const hasReviewableLabels = finalLabels.some(label =>
    ['too-big', 'needs-codeowners', 'deprecated-component'].includes(label)
  );

  const { data: reviews } = await github.rest.pulls.listReviews({
    owner,
    repo,
    pull_number: pr_number
  });

  const botReviews = reviews.filter(review =>
    review.user.type === 'Bot' &&
    review.state === 'CHANGES_REQUESTED' &&
    review.body && review.body.includes(BOT_COMMENT_MARKER)
  );

  if (hasReviewableLabels) {
    const reviewBody = `${BOT_COMMENT_MARKER}\n\n${reviewMessages.join('\n\n---\n\n')}`;

    if (botReviews.length > 0) {
      // Update existing review
      await github.rest.pulls.updateReview({
        owner,
        repo,
        pull_number: pr_number,
        review_id: botReviews[0].id,
        body: reviewBody
      });
      console.log('Updated existing bot review');
    } else {
      // Create new review
      await github.rest.pulls.createReview({
        owner,
        repo,
        pull_number: pr_number,
        body: reviewBody,
        event: 'REQUEST_CHANGES'
      });
      console.log('Created new bot review');
    }
  } else if (botReviews.length > 0) {
    // Dismiss existing reviews
    for (const review of botReviews) {
      try {
        await github.rest.pulls.dismissReview({
          owner,
          repo,
          pull_number: pr_number,
          review_id: review.id,
          message: 'Review dismissed: All requirements have been met'
        });
        console.log(`Dismissed bot review ${review.id}`);
      } catch (error) {
        console.log(`Failed to dismiss review ${review.id}:`, error.message);
      }
    }
  }
}

module.exports = {
  handleReviews
};
