// github-oauth.js
const { Octokit } = require('@octokit/rest');
const database = require('../config/database');

class GitHubOAuthService {
  constructor() {
    this.clientId = process.env.GITHUB_CLIENT_ID;
    this.clientSecret = process.env.GITHUB_CLIENT_SECRET;
    this.redirectUri = process.env.GITHUB_REDIRECT_URI || 'http://localhost:8010/api/github/auth/github/callback';
    
    if (!this.clientId || !this.clientSecret) {
      console.warn('GitHub OAuth not configured. Only public repositories will be accessible.');
    }
  }

  // Generate GitHub OAuth URL
  getAuthUrl(state) {
    if (!this.clientId) {
      throw new Error('GitHub OAuth not configured');
    }

    const params = new URLSearchParams({
      client_id: this.clientId,
      redirect_uri: this.redirectUri,
      scope: 'repo,user:email',
      state: state,
      allow_signup: 'false'
    });

    return `https://github.com/login/oauth/authorize?${params.toString()}`;
  }

  // Exchange authorization code for access token
  async exchangeCodeForToken(code) {
    const response = await fetch('https://github.com/login/oauth/access_token', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        client_id: this.clientId,
        client_secret: this.clientSecret,
        code: code,
      }),
    });

    const data = await response.json();
    
    if (data.error) {
      throw new Error(`OAuth error: ${data.error_description}`);
    }

    return data.access_token;
  }

  // Get user info from GitHub
  async getUserInfo(accessToken) {
    const octokit = new Octokit({ auth: accessToken });
    const { data: user } = await octokit.users.getAuthenticated();
    return user;
  }

  // Store GitHub token (no user ID)
  async storeToken(accessToken, githubUser) {
    const query = `
      INSERT INTO github_user_tokens (access_token, github_username, github_user_id, scopes, expires_at)
      VALUES ($1, $2, $3, $4, $5)
      ON CONFLICT (id) 
      DO UPDATE SET 
        access_token = $1,
        github_username = $2,
        github_user_id = $3,
        scopes = $4,
        expires_at = $5,
        updated_at = NOW()
      RETURNING *
    `;

    const result = await database.query(query, [
      accessToken,
      githubUser.login,
      githubUser.id,
      JSON.stringify(['repo', 'user:email']),
      null
    ]);

    return result.rows[0];
  }

  // Get stored token
  async getToken() {
    const query = 'SELECT * FROM github_user_tokens ORDER BY created_at DESC LIMIT 1';
    const result = await database.query(query);
    return result.rows[0];
  }

  // Create authenticated Octokit instance
  async getAuthenticatedOctokit() {
    const tokenRecord = await this.getToken();
    
    if (!tokenRecord) {
      return new Octokit({
        userAgent: 'CodeNuk-GitIntegration/1.0.0',
      });
    }

    return new Octokit({
      auth: tokenRecord.access_token,
      userAgent: 'CodeNuk-GitIntegration/1.0.0',
    });
  }

  // Check repository access
  async canAccessRepository(owner, repo) {
    try {
      const octokit = await this.getAuthenticatedOctokit();
      await octokit.repos.get({ owner, repo });
      return true;
    } catch (error) {
      if (error.status === 404) {
        return false;
      }
      throw error;
    }
  }

  // Revoke token
  async revokeToken() {
    const tokenRecord = await this.getToken();
    
    if (tokenRecord) {
      try {
        await fetch(`https://api.github.com/applications/${this.clientId}/grant`, {
          method: 'DELETE',
          headers: {
            'Authorization': `Basic ${Buffer.from(`${this.clientId}:${this.clientSecret}`).toString('base64')}`,
            'Accept': 'application/vnd.github.v3+json',
          },
          body: JSON.stringify({
            access_token: tokenRecord.access_token
          })
        });
      } catch (error) {
        console.error('Error revoking token on GitHub:', error);
      }

      await database.query('DELETE FROM github_user_tokens');
    }
  }
}

module.exports = GitHubOAuthService;
