import axios from 'axios';
import { adfToText } from '../../../dist/utils/adf-converter.js';
import { z } from 'zod';

const CreatePROutputSchema = z.object({
  success: z.boolean(),
  pullRequests: z.array(z.object({
    number: z.number(),
    url: z.string(),
    title: z.string(),
    repo: z.string(),
    branch: z.string(),
    timestamp: z.string()
  })),
  pr: z.object({
    number: z.number(),
    url: z.string(),
    title: z.string(),
    repo: z.string(),
    branch: z.string(),
    timestamp: z.string()
  }).nullable()
});

export const createPRNode = {
  name: 'create_pr',
  outputSchema: CreatePROutputSchema,
  execute: async (state) => {
    console.log('\n🔀 Creating Pull Request(s)...');
    
    const { ticketContext, repos, githubToken } = state;
    const codeImpl = state.implement_code_output?.codeImplementation;
    const tests = state.generate_test_cases_output?.tests;
    
    if (!codeImpl) {
      throw new Error('No code implementation found');
    }
    
    if (!githubToken) {
      console.log('⚠️  No GitHub token found, skipping PR creation');
      return { success: true, pullRequests: [] };
    }
    
    const githubRepos = (repos || []).filter(r => {
      if (r.provider && r.provider !== 'github') return false;
      return r.url?.includes('github.com');
    });
    
    if (githubRepos.length === 0) {
      console.log('⚠️  No GitHub repositories found, skipping PR creation');
      return { success: true, pullRequests: [] };
    }
    
    const committedRepos = new Set(codeImpl.committedRepos || []);
    const prBody = buildPRBody(ticketContext, codeImpl, tests);
    const pullRequests = [];
    const errors = [];
    
    for (const repo of githubRepos) {
      if (committedRepos.size > 0 && !committedRepos.has(repo.name)) {
        console.log(`⏭️ No changes committed in ${repo.name}, skipping PR`);
        continue;
      }
      
      const match = repo.url.match(/github\.com\/([^/]+)\/([^/]+)/);
      if (!match) {
        console.warn(`⚠️ Invalid GitHub URL for ${repo.name}: ${repo.url}`);
        continue;
      }
      
      const [, owner, repoName] = match;
      const cleanRepoName = repoName.replace(/\.git$/, '');
      
      console.log(`📤 Creating PR in ${owner}/${cleanRepoName}...`);
      
      try {
        const response = await axios.post(
          `https://api.github.com/repos/${owner}/${cleanRepoName}/pulls`,
          {
            title: `${ticketContext.ticketKey}: ${ticketContext.summary}`,
            head: codeImpl.branchName,
            base: repo.branch || 'main',
            body: prBody,
            draft: false
          },
          {
            headers: {
              'Authorization': `token ${githubToken}`,
              'Accept': 'application/vnd.github.v3+json',
              'Content-Type': 'application/json'
            }
          }
        );
        
        const pr = response.data;
        console.log(`✅ PR created: ${pr.html_url} (#${pr.number})`);
        
        pullRequests.push({
          number: pr.number,
          url: pr.html_url,
          title: pr.title,
          repo: `${owner}/${cleanRepoName}`,
          branch: codeImpl.branchName,
          timestamp: new Date().toISOString()
        });
      } catch (error) {
        const msg = error.response?.data?.message || error.message;
        console.error(`❌ Failed to create PR for ${owner}/${cleanRepoName}: ${msg}`);
        errors.push({ repo: `${owner}/${cleanRepoName}`, error: msg });
      }
    }
    
    if (pullRequests.length === 0 && errors.length > 0) {
      throw new Error(`All PR creations failed: ${errors.map(e => `${e.repo}: ${e.error}`).join('; ')}`);
    }
    
    return {
      success: true,
      pullRequests,
      pr: pullRequests[0] || null
    };
  }
};

function buildPRBody(ticketContext, codeImpl, tests) {
  const description = typeof ticketContext.description === 'object'
    ? adfToText(ticketContext.description)
    : ticketContext.description;
  let body = `## 🎫 Ticket: ${ticketContext.ticketKey}

${description || ticketContext.summary}

## 📊 Changes

`;

  if (codeImpl.metrics) {
    body += `### Metrics
- **Files Changed**: ${codeImpl.metrics.filesChanged}
- **Lines Added**: +${codeImpl.metrics.additions}
- **Lines Deleted**: -${codeImpl.metrics.deletions}
- **Net Change**: ${codeImpl.metrics.netChange} lines

`;
  }

  body += `### Affected Files
${codeImpl.changedFiles.map(f => `- \`${f}\``).join('\n')}

`;

  if (tests && tests.cases && tests.cases.length > 0) {
    body += `## 🧪 Test Cases

Generated ${tests.cases.length} test cases:

${tests.cases.map((tc, i) => `### ${i + 1}. ${tc.name}

${tc.description}

**Steps:**
${tc.steps.map((s, j) => `${j + 1}. ${s}`).join('\n')}

**Expected:** ${tc.expected}

`).join('\n')}
`;
  }

  body += `---
🤖 *This PR was automatically generated by [Zibby Agent](https://zibby.app)*
`;

  return body;
}
