import { ReportData, Standard, ComplianceItem } from '../types';

/**
 * Extracts a numeric value from a string like "0.22%", "415 MPa", etc.
 */
function extractNumber(val: string): number | null {
  if (!val) return null;
  const cleanVal = val.replace(/,/g, '.');
  const match = cleanVal.match(/-?\d+(\.\d+)?/);
  return match ? parseFloat(match[0]) : null;
}

/**
 * Parses the product string to try and find a thickness in mm.
 * E.g., "CHAPA 50MM", "PLATE 25.4 MM"
 */
function parseThickness(productDesc: string): number {
  if (!productDesc) return 0;
  
  const cleanDesc = productDesc.replace(/,/g, '.');
  
  // Try to find the pattern "num x num x num" (Thickness x Width x Length)
  const matchDimensions = cleanDesc.match(/(\d+(?:\.\d+)?)\s*(?:x|X|\*)\s*\d+(?:\.\d+)?\s*(?:x|X|\*)\s*\d+(?:\.\d+)?/);
  if (matchDimensions) {
    return parseFloat(matchDimensions[1]);
  }
  
  const match = cleanDesc.match(/(\d+(\.\d+)?)\s*(mm)/i);
  if (match) return parseFloat(match[1]);
  return 0; // Default or unknown
}

function normalizeElementName(element: string): string {
  const map: Record<string, string> = {
    'c': 'carbono',
    'carbon': 'carbono',
    'carbono': 'carbono',
    'mn': 'manganes',
    'manganese': 'manganes',
    'manganes': 'manganes',
    'si': 'silicio',
    'silicon': 'silicio',
    'silicio': 'silicio',
    'p': 'fosforo',
    'phosphorus': 'fosforo',
    'fosforo': 'fosforo',
    's': 'enxofre',
    'sulfur': 'enxofre',
    'enxofre': 'enxofre',
    'cu': 'cobre',
    'copper': 'cobre',
    'cobre': 'cobre',
    'ni': 'niquel',
    'nickel': 'niquel',
    'niquel': 'niquel',
    'cr': 'cromo',
    'chromium': 'cromo',
    'cromo': 'cromo',
    'mo': 'molibdenio',
    'molybdenum': 'molibdenio',
    'molibdenio': 'molibdenio',
    'v': 'vanadio',
    'vanadium': 'vanadio',
    'vanadio': 'vanadio',
    'nb': 'niobio',
    'columbium': 'niobio',
    'niobium': 'niobio',
    'niobio': 'niobio',
    'ti': 'titanio',
    'titanium': 'titanio',
    'titanio': 'titanio',
    'al': 'aluminio',
    'aluminum': 'aluminio',
    'aluminio': 'aluminio'
  };
  
  const lower = element.toLowerCase().trim();
  // Remove content in parentheses, e.g. "C (Carbon)" -> "c"
  const clean = lower.replace(/\(.*?\)/g, '').trim();
  return map[clean] || clean;
}

function getTolerance(elementName: string, productVal: number, thickness: number, norm: Standard): number {
  if (!norm.tolerancias_analise_produto_astma6) return 0;
  
  const tolRules = norm.tolerancias_analise_produto_astma6[elementName];
  if (!tolRules) return 0;

  if (tolRules.tabela && tolRules.tabela.length > 0) {
    for (const faixa of tolRules.tabela) {
      if (faixa.espessura_ate_mm && thickness <= faixa.espessura_ate_mm) {
        return faixa.tolerancia_mais || 0;
      }
      if (faixa.espessura_maior_que_mm && thickness > faixa.espessura_maior_que_mm) {
        return faixa.tolerancia_mais || 0;
      }
      if (faixa.limite_corrida_ate && productVal <= faixa.limite_corrida_ate) {
        return faixa.tolerancia_mais || 0;
      }
    }
  }

  return tolRules.tolerancia_mais || 0;
}

export function validateCertificateAgainstStandard(extractedReport: ReportData, standard: Standard): ReportData {
  const report = JSON.parse(JSON.stringify(extractedReport)) as ReportData;
  const thickness = parseThickness(report.identification.product);
  
  let allOk = true;

  // Encontrar limites baseados no produto (simplificado: pegamos o primeiro grupo que atende a espessura, ou o flat limits)
  let activeLimits: Record<string, number | null> = {};
  
  if (standard.limites_quimicos_corrida) {
    const grupos = Object.values(standard.limites_quimicos_corrida)[0] || [];
    for (const limite of grupos) {
      if (!limite.espessura_max_mm || thickness <= limite.espessura_max_mm) {
        // Encontrou a faixa certa
        for (const [key, val] of Object.entries(limite)) {
          if (typeof val === 'number') {
             activeLimits[key] = val;
          }
        }
        break; // Pega o primeiro correspondente
      }
    }
  } else if (standard.parametros_controle?.quimicos) {
    activeLimits = { ...standard.parametros_controle.quimicos };
  }

  // Validate Chemical
  if (report.compliance.chemical) {
    for (const item of report.compliance.chemical) {
      if (!item.element) continue;
      
      const normElement = normalizeElementName(item.element);
      const val = extractNumber(item.certificate);
      
      if (val !== null) {
        // Look for max limit
        const maxLimit = activeLimits[`${normElement}_max`] || activeLimits[normElement];
        const minLimit = activeLimits[`${normElement}_min`];
        
        let status: 'OK' | 'FALHA' = 'OK';
        let normStr = [];
        
        // Product tolerance
        const tolerance = getTolerance(normElement, maxLimit as number || 0, thickness, standard);
        
        if (minLimit !== undefined && minLimit !== null) {
          normStr.push(`Min: ${minLimit}`);
          if (val < (minLimit - tolerance)) status = 'FALHA';
        }
        
        if (maxLimit !== undefined && maxLimit !== null) {
          normStr.push(`Max: ${maxLimit}`);
          if (val > (maxLimit + tolerance)) status = 'FALHA';
        }
        
        if (normStr.length > 0) {
          item.norm = normStr.join(' - ');
        } else {
          item.norm = 'Não especificado';
        }
        
        item.status = status;
        if (status === 'FALHA') allOk = false;
      }
    }
  }

  // Validate Mechanical
  const mechLimits = standard.parametros_controle?.mecanicos || {};
  if (report.compliance.mechanical) {
    for (const item of report.compliance.mechanical) {
      if (!item.property) continue;
      
      const val = extractNumber(item.certificate);
      if (val !== null) {
        const propLower = item.property.toLowerCase();
        let maxLimit: number | null = null;
        let minLimit: number | null = null;
        
        if (propLower.includes('yield') || propLower.includes('escoamento')) {
           minLimit = mechLimits['limite_escoamento_min'] || mechLimits['yield_strength_min'] || null;
           maxLimit = mechLimits['limite_escoamento_max'] || mechLimits['yield_strength_max'] || null;
        } else if (propLower.includes('tensile') || propLower.includes('resistencia')) {
           minLimit = mechLimits['limite_resistencia_min'] || mechLimits['tensile_strength_min'] || null;
           maxLimit = mechLimits['limite_resistencia_max'] || mechLimits['tensile_strength_max'] || null;
        } else if (propLower.includes('elongation') || propLower.includes('alongamento')) {
           minLimit = mechLimits['alongamento_min'] || mechLimits['elongation_min'] || null;
        }

        let status: 'OK' | 'FALHA' = 'OK';
        let normStr = [];
        
        if (minLimit !== null) {
          normStr.push(`Min: ${minLimit}`);
          if (val < minLimit) status = 'FALHA';
          item.differencePercentage = `${val >= minLimit ? '+' : ''}${(((val - minLimit) / minLimit) * 100).toFixed(1)}%`;
        }
        
        if (maxLimit !== null) {
          normStr.push(`Max: ${maxLimit}`);
          if (val > maxLimit) status = 'FALHA';
        }
        
        if (normStr.length > 0) {
          item.norm = normStr.join(' - ');
        } else {
          item.norm = 'Não especificado';
        }
        
        item.status = status;
        if (status === 'FALHA') allOk = false;
      }
    }
  }

  report.compliance.status = allOk ? 'CONFORME' : 'NÃO CONFORME';
  if (!allOk) {
    report.compliance.nonComplianceReason = 'Valores fora dos limites da norma técnica considerando bitola e tolerâncias de produto.';
  }

  return report;
}
