// services/bitbucket-oauth.js
const database = require('../config/database');

class BitbucketOAuthService {
  constructor() {
    this.clientId = process.env.BITBUCKET_CLIENT_ID;
    this.clientSecret = process.env.BITBUCKET_CLIENT_SECRET;
    this.redirectUri = process.env.BITBUCKET_REDIRECT_URI || 'http://localhost:8000/api/vcs/bitbucket/auth/callback';
  }

  getAuthUrl(state) {
    if (!this.clientId) throw new Error('Bitbucket OAuth not configured');
    const scopes = process.env.BITBUCKET_OAUTH_SCOPES || 'repository account';
    const params = new URLSearchParams({
      client_id: this.clientId,
      response_type: 'code',
      state,
      // Bitbucket Cloud uses 'repository' for read access; 'repository:write' for write
      scope: scopes,
      redirect_uri: this.redirectUri
    });
    return `https://bitbucket.org/site/oauth2/authorize?${params.toString()}`;
  }

  async exchangeCodeForToken(code) {
    const resp = await fetch('https://bitbucket.org/site/oauth2/access_token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded', Authorization: `Basic ${Buffer.from(`${this.clientId}:${this.clientSecret}`).toString('base64')}` },
      body: new URLSearchParams({ grant_type: 'authorization_code', code, redirect_uri: this.redirectUri })
    });
    let data = null; 
    try { data = await resp.json(); } catch (_) { data = null; }
    if (!resp.ok) {
      const detail = data?.error_description || data?.error || (await resp.text().catch(() => '')) || 'unknown_error';
      throw new Error(`Bitbucket token exchange failed: ${detail}`);
    }
    return data.access_token;
  }

  async getUserInfo(accessToken) {
    const resp = await fetch('https://api.bitbucket.org/2.0/user', { headers: { Authorization: `Bearer ${accessToken}` } });
    if (!resp.ok) throw new Error('Failed to fetch Bitbucket user');
    return await resp.json();
  }

  async storeToken(accessToken, user) {
    const result = await database.query(
      `INSERT INTO bitbucket_user_tokens (access_token, bitbucket_username, bitbucket_user_id, scopes, expires_at)
       VALUES ($1, $2, $3, $4, $5)
       ON CONFLICT (id) DO UPDATE SET access_token = EXCLUDED.access_token, bitbucket_username = EXCLUDED.bitbucket_username, bitbucket_user_id = EXCLUDED.bitbucket_user_id, scopes = EXCLUDED.scopes, expires_at = EXCLUDED.expires_at, updated_at = NOW()
       RETURNING *`,
       [accessToken, user.username || user.display_name, user.uuid || null, JSON.stringify(['repository:admin','webhook','account']), null]
    );
    return result.rows[0];
  }

  async getToken() {
    const r = await database.query('SELECT * FROM bitbucket_user_tokens ORDER BY created_at DESC LIMIT 1');
    return r.rows[0];
  }
}

module.exports = BitbucketOAuthService;


