import { computed, Injectable, isDevMode, signal } from '@angular/core';

export interface TwitchJwtPayload {
  exp: number;
  opaque_user_id: string;
  user_id?: string;
  channel_id: string;
  role: 'viewer' | 'broadcaster' | 'external';
  is_unlinked?: boolean;
  pubsub_perms?: { listen?: string[]; send?: string[] };
}

function decodeJwtPayload(token: string): TwitchJwtPayload | null {
  try {
    const part = token.split('.')[1];
    return JSON.parse(atob(part.replace(/-/g, '+').replace(/_/g, '/')));
  } catch {
    return null;
  }
}

function buildDevAuth(): TwitchAuth {
  const payload: TwitchJwtPayload = {
    exp: Math.floor(Date.now() / 1000) + 3600,
    opaque_user_id: 'UDEV000001',
    user_id: 'dev_user_1',
    channel_id: 'dev_channel_1',
    role: 'viewer',
  };
  const encoded = btoa(JSON.stringify(payload))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');
  return {
    channelId: payload.channel_id,
    clientId: 'dev_client_id',
    token: `eyJhbGciOiJIUzI1NiJ9.${encoded}.dev`,
    userId: payload.opaque_user_id,
  };
}

@Injectable({ providedIn: 'root' })
export class TwitchAuthService {
  private readonly _auth = signal<TwitchAuth | null>(null);
  private readonly _context = signal<TwitchContext | null>(null);
  private readonly _isVisible = signal(true);

  readonly auth = this._auth.asReadonly();
  readonly context = this._context.asReadonly();
  readonly isVisible = this._isVisible.asReadonly();

  readonly jwtPayload = computed(() => {
    const auth = this._auth();
    return auth ? decodeJwtPayload(auth.token) : null;
  });

  readonly isLoggedIn = computed(
    () => this.jwtPayload()?.opaque_user_id.startsWith('U') ?? false,
  );

  readonly channelId = computed(() => this.jwtPayload()?.channel_id ?? null);

  init(): void {
    if (isDevMode() && !window.Twitch?.ext) {
      if (typeof ngDevMode === 'undefined' || ngDevMode) {
        console.warn('[TwitchAuth] Twitch SDK not found — using dev auth');
      }
      this._auth.set(buildDevAuth());
      return;
    }

    if (window.Twitch) {
      window.Twitch.ext.onAuthorized((auth) => {
        this._auth.set(auth);
      });

      window.Twitch.ext.onContext((context) => {
        this._context.set(context);
      });

      window.Twitch.ext.onVisibilityChanged((isVisible, context) => {
        this._isVisible.set(isVisible);
        this._context.set(context);
      });
    }
  }
}
