import crypto from 'crypto';
import { env } from '../config/env.js';

interface GiteaUser {
  id: number;
  login: string;
  email: string;
  full_name: string;
  avatar_url: string;
}

interface OAuthTokenResponse {
  access_token: string;
  token_type: string;
  expires_in: number;
  refresh_token?: string;
}

export class GiteaService {
  private giteaUrl: string;
  private clientId: string;
  private clientSecret: string;
  private redirectUri: string;
  private allowedUsers: Set<string>;

  constructor() {
    this.giteaUrl = env.GITEA_URL;
    this.clientId = env.GITEA_CLIENT_ID;
    this.clientSecret = env.GITEA_CLIENT_SECRET;
    this.redirectUri = env.GITEA_REDIRECT_URI;

    const allowed = env.GITEA_ALLOWED_USERS;
    this.allowedUsers = new Set(allowed.split(',').map(u => u.trim()).filter(Boolean));
  }

  /**
   * Generate OAuth authorization URL
   */
  getAuthorizationUrl(state: string): string {
    const params = new URLSearchParams({
      client_id: this.clientId,
      redirect_uri: this.redirectUri,
      response_type: 'code',
      state,
      scope: 'read:user',
    });

    return `${this.giteaUrl}/login/oauth/authorize?${params.toString()}`;
  }

  /**
   * Exchange authorization code for access token
   */
  async exchangeCodeForToken(code: string): Promise<OAuthTokenResponse> {
    const response = await fetch(`${this.giteaUrl}/login/oauth/access_token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
      body: JSON.stringify({
        client_id: this.clientId,
        client_secret: this.clientSecret,
        code,
        redirect_uri: this.redirectUri,
        grant_type: 'authorization_code',
      }),
    });

    if (!response.ok) {
      throw new Error(`Failed to exchange code: ${response.statusText}`);
    }

    return await response.json();
  }

  /**
   * Fetch user info from Gitea using access token
   */
  async getUserInfo(accessToken: string): Promise<GiteaUser> {
    const response = await fetch(`${this.giteaUrl}/api/v1/user`, {
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Accept': 'application/json',
      },
    });

    if (!response.ok) {
      throw new Error(`Failed to fetch user info: ${response.statusText}`);
    }

    return await response.json();
  }

  /**
   * Check if user is allowed to access the CMS
   */
  isUserAllowed(username: string): boolean {
    // If no allowed users specified, allow all
    if (this.allowedUsers.size === 0) {
      return true;
    }
    return this.allowedUsers.has(username);
  }

  /**
   * Generate random state for CSRF protection
   */
  generateState(): string {
    return crypto.randomBytes(32).toString('hex');
  }
}
