/**
 * Dual Booking Price Engine V7
 * Independent Branding (Audience + Commercial Floor) & Conversion (GMV + Commission)
 * (C) 2026 STONK AI BOOKING
 */
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define([], factory);
  } else if (typeof module === 'object' && module.exports) {
    module.exports = factory();
  } else {
    var exp = factory();
    root.kocBookingPriceV7 = exp;
    root.kocBookingPriceV6 = exp;
    root.estimateKocBookingPrices = exp.estimateKocBookingPrices;
    root.calculateBrandingBookingPrice = exp.calculateBrandingBookingPrice;
    root.calculateConversionBookingPrice = exp.calculateConversionBookingPrice;
    root.formatCompactPrice = exp.formatCompactPrice;
    root.PRICE_TAG_SVG = exp.PRICE_TAG_SVG;
  }
})(typeof self !== 'undefined' ? self : this, function () {
  'use strict';

  var PRICE_TAG_SVG = '<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:3.5px;vertical-align:-1px;display:inline-block;"><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path><line x1="7" y1="7" x2="7.01" y2="7"></line></svg>';

  var BRANDING_FOLLOWER_ANCHORS = [
    [5000, 500000],
    [20000, 900000],
    [50000, 1600000],
    [100000, 2600000],
    [200000, 4200000],
    [500000, 8000000],
    [1000000, 13000000],
    [2000000, 20000000],
    [5000000, 35000000],
    [10000000, 50000000]
  ];

  function normalizeMetricValue(val) {
    if (val === null || val === undefined || val === '' || val === '—' || val === '-') return 0;
    if (typeof val === 'number') return isNaN(val) ? 0 : val;

    var str = String(val).trim();
    if (!str) return 0;

    str = str.replace(/[₫$đĐ\s]/g, '');

    var suffixMatch = str.match(/^([0-9.,]+)\s*([kKmMbBtT]|tỉ|tr)?$/i);
    if (!suffixMatch) {
      var clean = str.replace(/[^0-9.,-]/g, '');
      if (clean.includes(',') && !clean.includes('.')) {
        return parseFloat(clean.replace(',', '.')) || 0;
      }
      return parseFloat(clean.replace(/,/g, '')) || 0;
    }

    var numPart = suffixMatch[1];
    var unit = (suffixMatch[2] || '').toLowerCase();

    if (numPart.includes(',') && numPart.includes('.')) {
      if (numPart.lastIndexOf(',') > numPart.lastIndexOf('.')) {
        numPart = numPart.replace(/\./g, '').replace(',', '.');
      } else {
        numPart = numPart.replace(/,/g, '');
      }
    } else if (numPart.includes(',')) {
      var parts = numPart.split(',');
      if (parts.length === 2 && parts[1].length <= 2) {
        numPart = numPart.replace(',', '.');
      } else {
        numPart = numPart.replace(/,/g, '');
      }
    }

    var baseNum = parseFloat(numPart) || 0;

    if (unit === 'b' || unit === 't' || unit === 'tỉ') {
      return Math.round(baseNum * 1e9);
    } else if (unit === 'm' || unit === 'tr') {
      return Math.round(baseNum * 1e6);
    } else if (unit === 'k') {
      return Math.round(baseNum * 1e3);
    }

    return baseNum;
  }

  function calculateFollowerBrandingBase(followers) {
    var F = Number(followers) || 0;
    if (F <= 0) return 0;

    if (F < 5000) {
      var ratio = Math.max(0, F / 5000);
      return Math.max(300000, Math.round(300000 + ratio * (500000 - 300000)));
    }

    if (F >= 10000000) {
      var over = 50000000 * Math.pow(F / 10000000, 0.20);
      return Math.min(100000000, over);
    }

    for (var i = 0; i < BRANDING_FOLLOWER_ANCHORS.length - 1; i++) {
      var F1 = BRANDING_FOLLOWER_ANCHORS[i][0];
      var P1 = BRANDING_FOLLOWER_ANCHORS[i][1];
      var F2 = BRANDING_FOLLOWER_ANCHORS[i + 1][0];
      var P2 = BRANDING_FOLLOWER_ANCHORS[i + 1][1];
      if (F >= F1 && F <= F2) {
        var t = (Math.log(F) - Math.log(F1)) / (Math.log(F2) - Math.log(F1));
        return P1 + t * (P2 - P1);
      }
    }

    return 50000000;
  }

  function calculateBrandingViewFactor(avgView, followers) {
    var F = Number(followers) || 0;
    var V = Number(avgView) || 0;
    if (F <= 0 || V <= 0) return 1.00;

    var viewRatio = V / F;

    if (viewRatio < 0.005) return 0.80;
    if (viewRatio < 0.01) return 0.85;
    if (viewRatio < 0.03) return 0.90;
    if (viewRatio < 0.08) return 0.95;
    if (viewRatio < 0.20) return 1.03;
    if (viewRatio < 0.40) return 1.10;
    if (viewRatio < 0.70) return 1.18;
    if (viewRatio < 1.00) return 1.25;
    return 1.32;
  }

  function calculateBrandingEngagementFactor(engagement) {
    if (engagement === null || engagement === undefined || engagement === '') return 1.00;
    var ER = typeof engagement === 'number' ? engagement : parseFloat(String(engagement).replace('%', ''));
    if (isNaN(ER) || ER <= 0) return 1.00;
    if (ER > 0 && ER < 0.05) ER = ER * 100;

    if (ER < 0.3) return 0.97;
    if (ER < 1.0) return 1.00;
    if (ER < 3.0) return 1.05;
    if (ER < 6.0) return 1.10;
    return 1.15;
  }

  function calculateConversionGmvBase(gmv30d) {
    var G = normalizeMetricValue(gmv30d);
    if (G <= 0) return 0;

    var rawBase = 1500000 * Math.pow(G / 1000000000, 0.32);
    return Math.max(300000, Math.min(20000000, rawBase));
  }

  function getCommissionFactor(rate) {
    if (rate === null || rate === undefined || rate === '') return 1.00;
    var r = typeof rate === 'number' ? rate : parseFloat(String(rate).replace('%', ''));
    if (isNaN(r) || r <= 0) return 1.00;

    if (r <= 5) return 1.10;
    if (r <= 10) return 1.00;
    if (r <= 15) return 0.90;
    if (r <= 20) return 0.80;
    return 0.70;
  }

  function roundNice(val) {
    if (!val || isNaN(val) || val <= 0) return 0;
    if (val >= 20000000) return Math.round(val / 2000000) * 2000000;
    if (val >= 5000000)  return Math.round(val / 1000000) * 1000000;
    if (val >= 1000000)  return Math.round(val / 500000)  * 500000;
    return Math.round(val / 100000) * 100000;
  }

  function formatPriceNumber(n) {
    if (!n || isNaN(n) || n <= 0) return '0';
    if (n >= 1000000) {
      var tr = n / 1000000;
      return tr % 1 === 0 ? tr + 'M' : tr.toFixed(1).replace('.0', '') + 'M';
    }
    return Math.round(n / 1000) + 'K';
  }

  function formatCompactPrice(n) {
    if (!n || isNaN(n) || n <= 0) return '0';
    if (n >= 1000000) {
      var tr = n / 1000000;
      var rounded = Math.round(tr * 10) / 10;
      return rounded % 1 === 0 ? rounded + 'M' : rounded.toFixed(1).replace('.0', '') + 'M';
    }
    var k = Math.round(n / 1000);
    return k + 'K';
  }

  function estimateKocBookingPrices(input) {
    if (!input || typeof input !== 'object') {
      return {
        branding: null,
        conversion: null,
        badgeText: 'Chưa đủ dữ liệu',
        badgeHtml: '',
        tooltip: 'Ước tính giá booking:\n• Chưa đủ dữ liệu',
        formulaVersion: 'v7_dual'
      };
    }

    var followers = normalizeMetricValue(input.followers !== undefined ? input.followers : (input.followerCount !== undefined ? input.followerCount : 0));
    var avgView = normalizeMetricValue(input.avgView !== undefined ? input.avgView : (input.avg_video_view !== undefined ? input.avg_video_view : (input.video_med_view !== undefined ? input.video_med_view : (input.views !== undefined ? input.views : (input.avgVideoView !== undefined ? input.avgVideoView : 0)))));
    var gmv30d = normalizeMetricValue(input.gmv30d !== undefined ? input.gmv30d : (input.gmv !== undefined ? input.gmv : (input.gmv_current !== undefined ? input.gmv_current : (input.gms_30d !== undefined ? input.gms_30d : (input.revenue !== undefined ? input.revenue : 0)))));
    var sold = normalizeMetricValue(input.sold !== undefined ? input.sold : (input.units_sold !== undefined ? input.units_sold : (input.unitsSold !== undefined ? input.unitsSold : (input.orders !== undefined ? input.orders : 0))));
    var engagement = input.engagement !== undefined ? input.engagement : (input.engagementPct !== undefined ? input.engagementPct : (input.engagement_rate !== undefined ? input.engagement_rate : (input.engagementRate !== undefined ? input.engagementRate : null)));
    var commissionRate = input.commissionRate !== undefined ? input.commissionRate : (input.commission_rate !== undefined ? input.commission_rate : null);

    var viewRatio = followers > 0 ? avgView / followers : 0;
    var aov = (sold > 0 && gmv30d > 0) ? Math.round(gmv30d / sold) : null;

    // 1. Audience Branding Price
    var followerBasePrice = calculateFollowerBrandingBase(followers);
    var viewFactor = calculateBrandingViewFactor(avgView, followers);
    var engagementFactor = calculateBrandingEngagementFactor(engagement);
    var audienceBrandPrice = followerBasePrice * viewFactor * engagementFactor;

    // 2. Conversion Raw Price & Commission
    var rawConversionBase = calculateConversionGmvBase(gmv30d);
    var commFactor = getCommissionFactor(commissionRate);
    var rawConversionPrice = rawConversionBase * commFactor;

    // 3. Brand Commercial Floor
    var brandCommercialFloor = rawConversionPrice > 0 ? (rawConversionPrice / 0.75) : 0;

    // 4. Final Branding Center & Range
    var brandingCenter = 0;
    var brandingSource = 'audience';

    if (followers > 0 && gmv30d > 0) {
      if (brandCommercialFloor > audienceBrandPrice) {
        brandingCenter = brandCommercialFloor;
        brandingSource = 'commercial_floor';
      } else {
        brandingCenter = audienceBrandPrice;
        brandingSource = 'audience';
      }
    } else if (followers > 0) {
      brandingCenter = audienceBrandPrice;
      brandingSource = 'audience_only';
    } else if (gmv30d > 0) {
      brandingCenter = brandCommercialFloor;
      brandingSource = 'commercial_floor_only';
    }

    var branding = null;
    if (brandingCenter > 0) {
      var bMin = roundNice(brandingCenter * 0.85);
      var bMax = roundNice(brandingCenter * 1.20);
      if (bMin < 300000) bMin = 300000;
      if (bMax <= bMin) bMax = bMin + (bMin < 1000000 ? 200000 : 1000000);

      var bRangeFormatted = formatPriceNumber(bMin) + '–' + formatPriceNumber(bMax);
      branding = {
        followerBasePrice: Math.round(followerBasePrice),
        viewFactor: viewFactor,
        engagementFactor: engagementFactor,
        audienceBrandPrice: Math.round(audienceBrandPrice),
        brandCommercialFloor: Math.round(brandCommercialFloor),
        brandingSource: brandingSource,
        center: Math.round(brandingCenter),
        min: bMin,
        max: bMax,
        compactCenter: formatCompactPrice(brandingCenter),
        formattedRange: bRangeFormatted
      };
    }

    // 5. Final Conversion Center & Range
    var conversion = null;
    if (gmv30d > 0 && rawConversionPrice > 0) {
      var convCenter = rawConversionPrice;
      if (brandingCenter > 0) {
        convCenter = Math.min(rawConversionPrice, brandingCenter * 0.75);
      }
      var cMin = roundNice(convCenter * 0.75);
      var cMax = roundNice(convCenter * 1.25);
      if (cMin < 300000) cMin = 300000;
      if (cMax <= cMin) cMax = cMin + (cMin < 1000000 ? 200000 : 500000);

      var cRangeFormatted = formatPriceNumber(cMin) + '–' + formatPriceNumber(cMax) + ' + HH';
      conversion = {
        rawConversionPrice: Math.round(rawConversionPrice),
        commissionFactor: commFactor,
        center: Math.round(convCenter),
        min: cMin,
        max: cMax,
        compactCenter: formatCompactPrice(convCenter),
        formattedRange: cRangeFormatted
      };
    }

    // 6. UI Badge: Lấy từ Giá MIN thấp nhất đến Giá MAX cao nhất (Ví dụ '4.5M - 10M')
    var allMins = [];
    var allMaxs = [];
    if (conversion) {
      if (conversion.min) allMins.push(conversion.min);
      if (conversion.max) allMaxs.push(conversion.max);
    }
    if (branding) {
      if (branding.min) allMins.push(branding.min);
      if (branding.max) allMaxs.push(branding.max);
    }

    var badgeText = '';
    if (allMins.length && allMaxs.length) {
      var minVal = Math.min.apply(null, allMins);
      var maxVal = Math.max.apply(null, allMaxs);
      var minStr = formatCompactPrice(minVal);
      var maxStr = formatCompactPrice(maxVal);
      badgeText = (minVal === maxVal || minStr === maxStr) ? minStr : (minStr + ' - ' + maxStr);
    } else if (branding) {
      badgeText = formatCompactPrice(branding.min) + ' - ' + formatCompactPrice(branding.max);
    } else if (conversion) {
      badgeText = formatCompactPrice(conversion.min) + ' - ' + formatCompactPrice(conversion.max);
    } else {
      badgeText = 'Chưa đủ dữ liệu';
    }

    var tooltip = 'Ước tính giá booking:\n\n' +
      (conversion ? ('• Booking chuyển đổi:\n  ' + conversion.formattedRange + '\n  Fixed fee + hoa hồng Affiliate\n\n') : '') +
      (branding ? ('• Booking thương hiệu:\n  ' + branding.formattedRange + '\n  Branding / Độ phủ') : '');

    return {
      input: {
        followers: followers,
        avgView: avgView,
        viewRatio: viewRatio,
        engagement: engagement != null ? Number(engagement) : null,
        gmv30d: gmv30d,
        sold: sold,
        aov: aov,
        commissionRate: commissionRate != null ? Number(commissionRate) : null
      },
      branding: branding,
      conversion: conversion,
      badgeText: badgeText,
      tooltip: tooltip.trim(),
      formulaVersion: 'v7_dual'
    };
  }

  return {
    PRICE_TAG_SVG: PRICE_TAG_SVG,
    normalizeMetricValue: normalizeMetricValue,
    calculateFollowerBrandingBase: calculateFollowerBrandingBase,
    calculateBrandingViewFactor: calculateBrandingViewFactor,
    calculateBrandingEngagementFactor: calculateBrandingEngagementFactor,
    calculateConversionGmvBase: calculateConversionGmvBase,
    getCommissionFactor: getCommissionFactor,
    estimateKocBookingPrices: estimateKocBookingPrices,
    formatPriceNumber: formatPriceNumber,
    formatCompactPrice: formatCompactPrice
  };
});
