import { Injectable } from '@nestjs/common';
import { envs } from 'src/config/envs';
import { PrismaService } from 'src/prisma/prisma.service';

/**
 * Configuración operacional (plan §9.3), en la tabla `config` de la base propia.
 * La más específica gana: 'empresa:<uuid>' sobre 'global'. Caché de 60 s.
 * Nunca secretos.
 */
export const DEFECTOS = {
  /** Kill switch y encendido gradual. */
  ia_activa: 'true',
  /** Tokens (entrada + salida) por empresa y día. Superado, el chat muestra el contacto. */
  tope_tokens_diarios: '2000000',
  /** Kill switch de la carga de incidencias en YouTrack (§6.8). Solo ámbito global. */
  youtrack_activo: 'true',
} as const;

/** Editables por el superadmin con el env como valor por defecto. Solo ámbito global. */
export const DEFECTOS_SERVICIO: Record<ClaveServicio, () => string> = {
  modelo_redactor: () => envs.redactor.model,
  modelo_extractor: () => envs.extractor.model,
  modelo_consultor: () => envs.consultor.model,
  modelo_manual: () => envs.manual.model,
  modelo_capturas: () => envs.capturas.model,
  telefono_contacto: () => envs.telefonoContacto,
};

export type Etapa = 'redactor' | 'extractor' | 'consultor' | 'manual' | 'capturas';
export type ClaveServicio = `modelo_${Etapa}` | 'telefono_contacto';

export type ClaveConfig = keyof typeof DEFECTOS;

const TTL_MS = 60_000;

@Injectable()
export class ConfigOperativaService {
  private cache: { filas: Map<string, string>; vence: number } | null = null;

  constructor(private readonly prisma: PrismaService) {}

  async valor(clave: ClaveConfig, empresaId: string): Promise<string> {
    const filas = await this.filas();
    return filas.get(`${clave}|empresa:${empresaId}`) ?? filas.get(`${clave}|global`) ?? DEFECTOS[clave];
  }

  async iaActiva(empresaId: string): Promise<boolean> {
    return (await this.valor('ia_activa', empresaId)).trim().toLowerCase() === 'true';
  }

  async topeTokensDiarios(empresaId: string): Promise<number> {
    const n = Number(await this.valor('tope_tokens_diarios', empresaId));
    return Number.isFinite(n) && n > 0 ? n : Number(DEFECTOS.tope_tokens_diarios);
  }

  /** Tira el caché: la pantalla de configuración del superadmin ve su cambio al instante. */
  invalidar() {
    this.cache = null;
  }

  /** Modelo de una etapa: lo configurado en la pantalla del superadmin, o el del .env. */
  async modelo(etapa: Etapa): Promise<string> {
    return this.valorServicio(`modelo_${etapa}`);
  }

  async telefonoContacto(): Promise<string> {
    return this.valorServicio('telefono_contacto');
  }

  async valorServicio(clave: ClaveServicio): Promise<string> {
    const filas = await this.filas();
    return filas.get(`${clave}|global`) ?? DEFECTOS_SERVICIO[clave]();
  }

  async youtrackActivo(): Promise<boolean> {
    const filas = await this.filas();
    return (filas.get('youtrack_activo|global') ?? DEFECTOS.youtrack_activo).trim().toLowerCase() === 'true';
  }

  private async filas(): Promise<Map<string, string>> {
    if (this.cache && this.cache.vence > Date.now()) return this.cache.filas;
    const filas = await this.prisma.config.findMany();
    const mapa = new Map(filas.map((f) => [`${f.clave}|${f.ambito}`, f.valor]));
    this.cache = { filas: mapa, vence: Date.now() + TTL_MS };
    return mapa;
  }
}
