import { Injectable, Logger } from '@nestjs/common';
import { envs } from 'src/config/envs';

/**
 * Cliente mínimo de YouTrack (REST, token permanente de un usuario bot con
 * permiso solo en el proyecto). Sin credenciales queda no disponible y la
 * bandeja de incidencias espera (el chat nunca depende de esto).
 */
@Injectable()
export class YoutrackClient {
  private readonly logger = new Logger(YoutrackClient.name);
  private proyectoId: string | null = null;

  get disponible(): boolean {
    return !!(envs.youtrack.url && envs.youtrack.token);
  }

  private async pedir<T>(ruta: string, init?: RequestInit): Promise<T> {
    const r = await fetch(`${envs.youtrack.url}${ruta}`, {
      ...init,
      headers: {
        Authorization: `Bearer ${envs.youtrack.token}`,
        'Content-Type': 'application/json',
        Accept: 'application/json',
        ...init?.headers,
      },
      signal: AbortSignal.timeout(15_000),
    });
    const cuerpo = await r.text();
    if (!r.ok) throw new Error(`YouTrack ${r.status} en ${ruta}: ${cuerpo.slice(0, 300)}`);
    return (cuerpo ? JSON.parse(cuerpo) : {}) as T;
  }

  /** Id interno del proyecto (p. ej. NE). Se resuelve una vez por proceso. */
  private async proyecto(): Promise<string> {
    if (this.proyectoId) return this.proyectoId;
    const lista = await this.pedir<Array<{ id: string; shortName: string }>>(
      `/api/admin/projects?fields=id,shortName&query=${encodeURIComponent(envs.youtrack.proyecto)}`,
    );
    const p = lista.find((x) => x.shortName === envs.youtrack.proyecto);
    if (!p) throw new Error(`YouTrack: no existe el proyecto ${envs.youtrack.proyecto}`);
    this.proyectoId = p.id;
    return p.id;
  }

  /** Para la pantalla de configuración: valida credencial y proyecto sin crear nada. */
  async probar(): Promise<{ ok: boolean; detalle: string }> {
    if (!this.disponible) return { ok: false, detalle: 'Faltan YOUTRACK_URL o YOUTRACK_TOKEN en el servicio.' };
    try {
      this.proyectoId = null;
      await this.proyecto();
      return { ok: true, detalle: `Conectado: proyecto ${envs.youtrack.proyecto} encontrado.` };
    } catch (err) {
      return { ok: false, detalle: (err as Error).message };
    }
  }

  async crearIssue(summary: string, description: string): Promise<{ id: string; idReadable: string }> {
    const proyecto = await this.proyecto();
    return this.pedir<{ id: string; idReadable: string }>('/api/issues?fields=id,idReadable', {
      method: 'POST',
      body: JSON.stringify({ project: { id: proyecto }, summary, description }),
    });
  }

  async comentar(idReadable: string, texto: string): Promise<void> {
    await this.pedir(`/api/issues/${idReadable}/comments?fields=id`, {
      method: 'POST',
      body: JSON.stringify({ text: texto }),
    });
  }

  /** Comando de YouTrack ("Priority Critical", "State To do"). Que falle no corta nada. */
  async comando(idReadable: string, query: string): Promise<void> {
    try {
      await this.pedir('/api/commands', {
        method: 'POST',
        body: JSON.stringify({ query, issues: [{ idReadable }] }),
      });
    } catch (err) {
      this.logger.warn(`Comando "${query}" sobre ${idReadable} falló: ${(err as Error).message}`);
    }
  }
}
