const { v4: uuidv4 } = require('uuid');
const database = require('../config/database');

class OAuthTokensModel {
  constructor() {
    this.db = database;
  }

  // GitLab OAuth tokens
  async createGitLabToken(tokenData) {
    const {
      access_token,
      gitlab_username,
      gitlab_user_id,
      scopes,
      expires_at
    } = tokenData;

    const query = `
      INSERT INTO gitlab_user_tokens (
        id, access_token, gitlab_username, gitlab_user_id, 
        scopes, expires_at, created_at, updated_at
      ) VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
      RETURNING *
    `;

    const values = [
      uuidv4(),
      access_token,
      gitlab_username,
      gitlab_user_id,
      scopes,
      expires_at
    ];

    const result = await this.db.query(query, values);
    return result.rows[0];
  }

  async getGitLabTokenByUsername(gitlab_username) {
    const query = `
      SELECT * FROM gitlab_user_tokens 
      WHERE gitlab_username = $1 
      ORDER BY created_at DESC 
      LIMIT 1
    `;
    
    const result = await this.db.query(query, [gitlab_username]);
    return result.rows[0];
  }

  async updateGitLabToken(token_id, tokenData) {
    const {
      access_token,
      scopes,
      expires_at
    } = tokenData;

    const query = `
      UPDATE gitlab_user_tokens 
      SET access_token = $2, scopes = $3, expires_at = $4, updated_at = NOW()
      WHERE id = $1
      RETURNING *
    `;

    const result = await this.db.query(query, [token_id, access_token, scopes, expires_at]);
    return result.rows[0];
  }

  // Bitbucket OAuth tokens
  async createBitbucketToken(tokenData) {
    const {
      access_token,
      bitbucket_username,
      bitbucket_user_id,
      scopes,
      expires_at
    } = tokenData;

    const query = `
      INSERT INTO bitbucket_user_tokens (
        id, access_token, bitbucket_username, bitbucket_user_id, 
        scopes, expires_at, created_at, updated_at
      ) VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
      RETURNING *
    `;

    const values = [
      uuidv4(),
      access_token,
      bitbucket_username,
      bitbucket_user_id,
      scopes,
      expires_at
    ];

    const result = await this.db.query(query, values);
    return result.rows[0];
  }

  async getBitbucketTokenByUsername(bitbucket_username) {
    const query = `
      SELECT * FROM bitbucket_user_tokens 
      WHERE bitbucket_username = $1 
      ORDER BY created_at DESC 
      LIMIT 1
    `;
    
    const result = await this.db.query(query, [bitbucket_username]);
    return result.rows[0];
  }

  async updateBitbucketToken(token_id, tokenData) {
    const {
      access_token,
      scopes,
      expires_at
    } = tokenData;

    const query = `
      UPDATE bitbucket_user_tokens 
      SET access_token = $2, scopes = $3, expires_at = $4, updated_at = NOW()
      WHERE id = $1
      RETURNING *
    `;

    const result = await this.db.query(query, [token_id, access_token, scopes, expires_at]);
    return result.rows[0];
  }

  // Gitea OAuth tokens
  async createGiteaToken(tokenData) {
    const {
      access_token,
      gitea_username,
      gitea_user_id,
      scopes,
      expires_at
    } = tokenData;

    const query = `
      INSERT INTO gitea_user_tokens (
        id, access_token, gitea_username, gitea_user_id, 
        scopes, expires_at, created_at, updated_at
      ) VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
      RETURNING *
    `;

    const values = [
      uuidv4(),
      access_token,
      gitea_username,
      gitea_user_id,
      scopes,
      expires_at
    ];

    const result = await this.db.query(query, values);
    return result.rows[0];
  }

  async getGiteaTokenByUsername(gitea_username) {
    const query = `
      SELECT * FROM gitea_user_tokens 
      WHERE gitea_username = $1 
      ORDER BY created_at DESC 
      LIMIT 1
    `;
    
    const result = await this.db.query(query, [gitea_username]);
    return result.rows[0];
  }

  async updateGiteaToken(token_id, tokenData) {
    const {
      access_token,
      scopes,
      expires_at
    } = tokenData;

    const query = `
      UPDATE gitea_user_tokens 
      SET access_token = $2, scopes = $3, expires_at = $4, updated_at = NOW()
      WHERE id = $1
      RETURNING *
    `;

    const result = await this.db.query(query, [token_id, access_token, scopes, expires_at]);
    return result.rows[0];
  }

  // Generic methods for all providers
  async deleteExpiredTokens() {
    const queries = [
      'DELETE FROM gitlab_user_tokens WHERE expires_at < NOW()',
      'DELETE FROM bitbucket_user_tokens WHERE expires_at < NOW()',
      'DELETE FROM gitea_user_tokens WHERE expires_at < NOW()'
    ];

    let totalDeleted = 0;
    for (const query of queries) {
      const result = await this.db.query(query);
      totalDeleted += result.rowCount;
    }

    return totalDeleted;
  }

  async getAllTokensByProvider(provider) {
    const tableMap = {
      'gitlab': 'gitlab_user_tokens',
      'bitbucket': 'bitbucket_user_tokens',
      'gitea': 'gitea_user_tokens'
    };

    const tableName = tableMap[provider];
    if (!tableName) {
      throw new Error(`Unsupported provider: ${provider}`);
    }

    const query = `SELECT * FROM ${tableName} ORDER BY created_at DESC`;
    const result = await this.db.query(query);
    return result.rows;
  }
}

module.exports = OAuthTokensModel;
