/**
 * Tickets SLA + Priority Score v0 — port do ResultsDesk (React)
 * Spec negócio Roger: SLA_SETTINGS + fórmula composta origem × idle
 */
const TicketsSla = {
  SETTINGS: {
    ONBOARD: { response: 2, resolution: 72 },
    DESK: { response: 1, resolution: 8 },
    SECURITY: { response: 0.5, resolution: 4 },
    AGENTIC_OPS: { response: 0.5, resolution: 4 },
  },

  PRIORITY_CRITICAL: 7,
  PRIORITY_HIGH: 4,
  PRIORITY_WARN: 2,

  mapTenant(t) {
    const src = t.source || '';
    const ev = t.event || '';
    if (src === 'wazuh' || ev === 'wazuh.alert' || src === 'vm112-security' || (t.subject || '').startsWith('[security]')) {
      return 'SECURITY';
    }
    if (src === 'vm112-onboard' || ev.startsWith('onboarding') || ev.startsWith('domain.') || ev.startsWith('dns.')) {
      return 'ONBOARD';
    }
    if (src === 'agentic-ops' || (t.subject || '').toLowerCase().includes('[agentic')) {
      return 'AGENTIC_OPS';
    }
    return 'DESK';
  },

  hoursSince(iso) {
    if (!iso) return 0;
    try {
      return Math.max(0, Math.round((Date.now() - new Date(iso).getTime()) / 3600000));
    } catch {
      return 0;
    }
  },

  isInternalDomain(domain) {
    const d = String(domain || '').toLowerCase();
    return d.includes('itecnologys.com') || d.includes('ligbox.com.br');
  },

  computePriority(t) {
    const tenant = this.mapTenant(t);
    const sla = this.SETTINGS[tenant] || { response: 2, resolution: 24 };
    const totalAgeHours = this.hoursSince(t.created_at);
    const lastEvent = t._lastEventAt || null;
    const idleHours = t._idleHours != null
      ? t._idleHours
      : this.hoursSince(lastEvent || t.created_at);

    const wazuhLevel = t.severity != null ? Number(t.severity) : null;
    const isLead = t.crm_track === 'lead' || t.is_lead;

    let originScore = 1.0;
    if (tenant === 'SECURITY' && wazuhLevel != null && wazuhLevel >= 1) originScore = 4.0;
    else if (this.isInternalDomain(t.domain || t.email)) originScore = 3.0;
    else if (isLead) originScore = 2.0;

    let idleScore = 0.5;
    if (idleHours >= sla.resolution * 2) idleScore = 2.5;
    else if (idleHours >= sla.resolution) idleScore = 2.0;
    else if (idleHours >= sla.response * 2) idleScore = 1.5;
    else if (idleHours >= sla.response) idleScore = 1.0;

    const priorityScore = parseFloat((originScore * idleScore).toFixed(1));

    let responseSla = 'OK';
    let resolutionSla = 'OK';
    if (idleHours > sla.response) responseSla = 'WARNING';
    if (idleHours > sla.resolution) resolutionSla = `STALE (${sla.resolution}h+)`;

    let priorityBand = 'info';
    if (priorityScore >= this.PRIORITY_CRITICAL) priorityBand = 'critical';
    else if (priorityScore >= this.PRIORITY_HIGH) priorityBand = 'high';
    else if (priorityScore >= this.PRIORITY_WARN) priorityBand = 'warn';

    return {
      ...t,
      _tenant: tenant,
      _priorityScore: priorityScore,
      _priorityBand: priorityBand,
      _totalAgeHours: totalAgeHours,
      _idleHours: idleHours,
      _responseSla: responseSla,
      _resolutionSla: resolutionSla,
      _slaLimits: sla,
    };
  },

  processList(tickets) {
    return tickets
      .map((t) => this.computePriority(t))
      .sort((a, b) => b._priorityScore - a._priorityScore);
  },

  computeOverview(tickets) {
    const rows = tickets.map((t) => this.computePriority(t));
    const active = rows.filter((t) => !['closed'].includes(t.status));
    const resolved = rows.filter((t) => ['resolved', 'closed'].includes(t.status));

    const slaOk = active.filter((t) => t._responseSla === 'OK' && t._resolutionSla === 'OK').length;
    const slaPct = active.length ? Math.round((slaOk / active.length) * 100) : 100;

    const mttrSamples = resolved.map((t) => t._totalAgeHours).filter((h) => h > 0);
    const mttr = mttrSamples.length
      ? (mttrSamples.reduce((a, b) => a + b, 0) / mttrSamples.length).toFixed(1)
      : '—';

    const responseSamples = rows
      .filter((t) => t.assigned_at || t.assisted_at)
      .map((t) => {
        try {
          const start = new Date(t.created_at).getTime();
          const end = new Date(t.assigned_at || t.assisted_at).getTime();
          return Math.max(0, Math.round((end - start) / 3600000));
        } catch {
          return null;
        }
      })
      .filter((h) => h != null);
    const avgResponse = responseSamples.length
      ? (responseSamples.reduce((a, b) => a + b, 0) / responseSamples.length).toFixed(1)
      : (active.length
        ? (active.reduce((s, t) => s + t._idleHours, 0) / active.length).toFixed(1)
        : '—');

    const buckets = { critical: 0, high: 0, warn: 0, info: 0 };
    for (const t of rows) buckets[t._priorityBand] = (buckets[t._priorityBand] || 0) + 1;

    const criticalWaiting = active.filter(
      (t) => t._priorityBand === 'critical' && ['open', 'escalated', 'assisting'].includes(t.status),
    ).length;

    return {
      slaPct,
      mttr,
      avgResponse,
      buckets,
      criticalWaiting,
      total: rows.length,
    };
  },

  getInitials(name) {
    if (!name) return '—';
    const parts = String(name).trim().split(/\s+/);
    return ((parts[0]?.[0] || '') + (parts[1]?.[0] || parts[0]?.[1] || '')).toUpperCase() || '—';
  },

  assigneeLabel(t, userMap = {}) {
    const raw = t.assisted_by || t.assigned_to || '';
    if (!raw) return { label: 'Sem atribuição', initials: '—' };
    const label = userMap[raw] || raw.replace(/[._]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
    return { label, initials: this.getInitials(label) };
  },
};

window.TicketsSla = TicketsSla;
