<div class="campaigns-page campaign-terms-page">
  <div class="campaigns-header">
    <h2><i class="fa-solid fa-list-check"></i> Grupy i frazy</h2>
  </div>

  <div class="campaigns-filters">
    <div class="filter-group">
      <label for="terms_client_id"><i class="fa-solid fa-building"></i> Klient</label>
      <select id="terms_client_id" name="terms_client_id" class="form-control">
        <option value="">- wybierz klienta -</option>
        <?php foreach ( $this -> clients as $client ): ?>
          <option value="<?= $client['id']; ?>"><?= htmlspecialchars( $client['name'] ); ?></option>
        <?php endforeach; ?>
      </select>
    </div>
    <div class="filter-group">
      <label for="terms_campaign_id"><i class="fa-solid fa-bullhorn"></i> Kampania</label>
      <select id="terms_campaign_id" name="terms_campaign_id" class="form-control">
        <option value="">- wybierz kampanie -</option>
      </select>
    </div>
    <div class="filter-group">
      <label for="terms_ad_group_id"><i class="fa-solid fa-layer-group"></i> Grupa reklam</label>
      <select id="terms_ad_group_id" name="terms_ad_group_id" class="form-control">
        <option value="">- wszystkie grupy -</option>
      </select>
    </div>

    <div class="filter-group terms-columns-group">
      <label><i class="fa-solid fa-table-columns"></i> Kolumny</label>
      <div class="terms-columns-box">
        <details class="terms-columns-control">
          <summary>Grupy reklam</summary>
          <div class="terms-columns-list" id="terms_columns_list_ad_groups"></div>
        </details>
        <details class="terms-columns-control">
          <summary>Frazy wyszukiwane</summary>
          <div class="terms-columns-list" id="terms_columns_list_search"></div>
        </details>
        <details class="terms-columns-control">
          <summary>Frazy wykluczajace</summary>
          <div class="terms-columns-list" id="terms_columns_list_negative"></div>
        </details>
        <details class="terms-columns-control">
          <summary>Frazy dodane</summary>
          <div class="terms-columns-list" id="terms_columns_list_keywords"></div>
        </details>
      </div>
    </div>
  </div>

  <div class="campaign-terms-wrap">
    <div class="campaigns-extra-card terms-card terms-adgroups-card">
      <div class="campaigns-extra-card-title">
        <span class="terms-card-title-label"><i class="fa-solid fa-layer-group"></i> Grupy reklam</span>
        <button type="button" id="terms_adgroups_toggle" class="terms-card-toggle" title="Zwin tabele grup reklam" aria-label="Zwin tabele grup reklam" aria-expanded="true">
          <i class="fa-solid fa-chevron-up"></i>
        </button>
      </div>
      <div class="campaigns-extra-table-wrap">
        <table class="table table-sm campaigns-extra-table" id="terms_ad_groups_table">
          <thead>
            <tr>
              <th>Grupa reklam</th>
              <th>Klik. 30d</th>
              <th>Koszt 30d</th>
              <th>Wartosc 30d</th>
              <th>ROAS 30d</th>
              <th>Klik. all</th>
              <th>Koszt all</th>
              <th>Wartosc all</th>
              <th>ROAS all</th>
            </tr>
          </thead>
          <tbody>
            <tr><td colspan="9" class="campaigns-empty-row">Wybierz klienta i kampanie.</td></tr>
          </tbody>
        </table>
      </div>
    </div>

    <div class="campaigns-extra-card terms-card terms-search-card">
      <div class="campaigns-extra-card-title">
        <i class="fa-solid fa-magnifying-glass"></i> Frazy wyszukiwane (klikniecia >= 1)
      </div>
      <div class="terms-search-toolbar">
        <input type="text" id="phrase_search_search" class="form-control terms-table-search-input" placeholder="Szukaj frazy..." />
        <label class="terms-search-toolbar-label"><i class="fa-solid fa-filter"></i> Klik. all</label>
        <input type="number" id="terms_min_clicks_all" class="form-control" min="0" step="1" placeholder=">= np. 100" />
        <input type="number" id="terms_max_clicks_all" class="form-control" min="0" step="1" placeholder="<= np. 500" />
        <label class="terms-search-toolbar-label"><i class="fa-solid fa-filter"></i> Konw. all</label>
        <input type="number" id="terms_min_conversions_all" class="form-control" min="0" step="0.01" placeholder=">= np. 1" />
        <input type="number" id="terms_max_conversions_all" class="form-control" min="0" step="0.01" placeholder="<= np. 10" />
        <label class="terms-search-selected-label">Zaznaczone: <span id="terms_search_selected_count">0</span></label>
        <button type="button" id="terms_ai_analyze_btn" class="terms-ai-analyze-btn">
          <i class="fa-solid fa-robot"></i> Analizuj zaznaczone w ChatGPT
        </button>
      </div>
      <div class="campaigns-extra-table-wrap">
        <table class="table table-sm campaigns-extra-table" id="terms_search_table">
          <thead>
            <tr>
              <th class="terms-search-select-cell">
                <input type="checkbox" id="terms_search_select_all" aria-label="Zaznacz wszystkie frazy na stronie" title="Zaznacz wszystkie frazy na stronie">
              </th>
              <th>Fraza</th>
              <th>Grupa reklam</th>
              <th>Klik. all</th>
              <th>Koszt all</th>
              <th>Wartosc all</th>
              <th>Konw. all</th>
              <th>ROAS all</th>
              <th>Klik. 30d</th>
              <th>Koszt 30d</th>
              <th>Wartosc 30d</th>
              <th>Konw. 30d</th>
              <th>ROAS 30d</th>
              <th>Akcja</th>
            </tr>
          </thead>
          <tbody>
            <tr><td colspan="14" class="campaigns-empty-row">Brak danych.</td></tr>
          </tbody>
        </table>
      </div>
    </div>

    <div class="campaigns-extra-card terms-card terms-negative-card">
      <div class="campaigns-extra-card-title">
        <i class="fa-solid fa-ban"></i> Frazy wykluczajace
      </div>
      <div class="terms-negative-toolbar">
        <input type="text" id="phrase_search_negative" class="form-control terms-table-search-input" placeholder="Szukaj frazy..." />
        <button type="button" id="terms_delete_selected_negative" class="terms-negative-bulk-btn" disabled>
          <i class="fa-solid fa-trash"></i> Usun zaznaczone (<span id="terms_negative_selected_count">0</span>)
        </button>
      </div>
      <div class="campaigns-extra-table-wrap">
        <table class="table table-sm campaigns-extra-table" id="terms_negative_table">
          <thead>
            <tr>
              <th class="terms-negative-select-cell">
                <input type="checkbox" id="terms_negative_select_all" aria-label="Zaznacz wszystkie frazy na stronie" title="Zaznacz wszystkie frazy na stronie">
              </th>
              <th>Fraza</th>
              <th>Match type</th>
              <th>Akcja</th>
              <th>Poziom</th>
            </tr>
          </thead>
          <tbody>
            <tr><td colspan="5" class="campaigns-empty-row">Brak danych.</td></tr>
          </tbody>
        </table>
      </div>
    </div>

    <div class="campaigns-extra-card terms-card terms-keywords-card">
      <div class="campaigns-extra-card-title">
        <i class="fa-solid fa-key"></i> Frazy dodane do kampanii/grup reklam
      </div>
      <div class="terms-keywords-toolbar">
        <input type="text" id="phrase_search_keywords" class="form-control terms-table-search-input" placeholder="Szukaj frazy..." />
        <button type="button" id="terms_add_keyword_btn" class="terms-negative-bulk-btn">
          <i class="fa-solid fa-plus"></i> Dodaj fraze
        </button>
      </div>
      <div class="campaigns-extra-table-wrap">
        <table class="table table-sm campaigns-extra-table" id="terms_keywords_table">
          <thead>
            <tr>
              <th>Fraza</th>
              <th>Match type</th>
              <th>Grupa reklam</th>
              <th>Akcja</th>
              <th>Klik. all</th>
              <th>Koszt all</th>
              <th>Wartosc all</th>
              <th>Konw. all</th>
              <th>ROAS all</th>
              <th>Klik. 30d</th>
              <th>Koszt 30d</th>
              <th>Wartosc 30d</th>
              <th>Konw. 30d</th>
              <th>ROAS 30d</th>
            </tr>
          </thead>
          <tbody>
            <tr><td colspan="14" class="campaigns-empty-row">Brak danych.</td></tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</div>

<script type="text/javascript">
var terms_ad_groups_table = null;
var terms_search_table = null;
var terms_negative_table = null;
var terms_keywords_table = null;
var terms_search_selected_ids = {};
var terms_negative_selected_ids = {};
var terms_ai_modal_instance = null;

var TERMS_STORAGE_CLIENT = 'campaign_terms.last_client_id';
var TERMS_STORAGE_CAMPAIGN = 'campaign_terms.last_campaign_id';
var TERMS_STORAGE_AD_GROUP = 'campaign_terms.last_ad_group_id';
var TERMS_STORAGE_SEARCH_TABLE_PAGE_PREFIX = 'campaign_terms.search_table_page.';
var TERMS_STORAGE_NEGATIVE_TABLE_PAGE_PREFIX = 'campaign_terms.negative_table_page.';
var TERMS_STORAGE_COLUMNS_PREFIX = 'campaign_terms.columns.';
var TERMS_STORAGE_AD_GROUPS_COLLAPSED = 'campaign_terms.ad_groups_collapsed';
var TERMS_STORAGE_MIN_CLICKS_ALL = 'campaign_terms.min_clicks_all';
var TERMS_STORAGE_MAX_CLICKS_ALL = 'campaign_terms.max_clicks_all';
var TERMS_STORAGE_MIN_CONVERSIONS_ALL = 'campaign_terms.min_conversions_all';
var TERMS_STORAGE_MAX_CONVERSIONS_ALL = 'campaign_terms.max_conversions_all';

var terms_search_filter_registered = false;

var TERMS_COLUMNS_LABELS = {
  ad_groups: [
    'Grupa reklam',
    'Klik. 30d',
    'Koszt 30d',
    'Wartosc 30d',
    'ROAS 30d',
    'Klik. all',
    'Koszt all',
    'Wartosc all',
    'ROAS all'
  ],
  search: [
    'Zaznacz',
    'Fraza',
    'Grupa reklam',
    'Klik. all',
    'Koszt all',
    'Wartosc all',
    'Konw. all',
    'ROAS all',
    'Klik. 30d',
    'Koszt 30d',
    'Wartosc 30d',
    'Konw. 30d',
    'ROAS 30d',
    'Akcja'
  ],
  negative: [
    'Zaznacz',
    'Fraza',
    'Match type',
    'Akcja',
    'Poziom'
  ],
  keywords: [
    'Fraza',
    'Match type',
    'Grupa reklam',
    'Klik. all',
    'Koszt all',
    'Wartosc all',
    'Konw. all',
    'ROAS all',
    'Klik. 30d',
    'Koszt 30d',
    'Wartosc 30d',
    'Konw. 30d',
    'ROAS 30d'
  ]
};

var TERMS_COLUMNS_LIST_SELECTORS = {
  ad_groups: '#terms_columns_list_ad_groups',
  search: '#terms_columns_list_search',
  negative: '#terms_columns_list_negative',
  keywords: '#terms_columns_list_keywords'
};

var TERMS_COLUMNS_TABLE_SELECTORS = {
  ad_groups: '#terms_ad_groups_table',
  search: '#terms_search_table',
  negative: '#terms_negative_table',
  keywords: '#terms_keywords_table'
};

function terms_storage_set( key, value )
{
  try
  {
    if ( value === null || value === undefined || value === '' )
      localStorage.removeItem( key );
    else
      localStorage.setItem( key, String( value ) );
  }
  catch ( e ) {}
}

function terms_storage_get( key )
{
  try
  {
    return localStorage.getItem( key ) || '';
  }
  catch ( e )
  {
    return '';
  }
}

function terms_pagination_context()
{
  var client_id = $( '#terms_client_id' ).val() || '0';
  var campaign_id = $( '#terms_campaign_id' ).val() || '0';
  var ad_group_id = $( '#terms_ad_group_id' ).val() || '0';
  return [ client_id, campaign_id, ad_group_id ].join( ':' );
}

function terms_page_storage_key( table_type )
{
  var prefix = table_type === 'negative' ? TERMS_STORAGE_NEGATIVE_TABLE_PAGE_PREFIX : TERMS_STORAGE_SEARCH_TABLE_PAGE_PREFIX;
  return prefix + terms_pagination_context();
}

function terms_columns_storage_key( table_key )
{
  return TERMS_STORAGE_COLUMNS_PREFIX + table_key + '.v4.' + terms_pagination_context();
}

function terms_get_table_instance( table_key )
{
  if ( table_key === 'ad_groups' ) return terms_ad_groups_table;
  if ( table_key === 'search' ) return terms_search_table;
  if ( table_key === 'negative' ) return terms_negative_table;
  if ( table_key === 'keywords' ) return terms_keywords_table;
  return null;
}

function terms_get_saved_columns_visibility( table_key, columns_count )
{
  var raw = terms_storage_get( terms_columns_storage_key( table_key ) );
  if ( !raw )
    return null;

  try
  {
    var saved = JSON.parse( raw );
    if ( !Array.isArray( saved ) || saved.length !== columns_count )
      return null;

    return saved.map( function( visible ) { return !!visible; } );
  }
  catch ( e )
  {
    return null;
  }
}

function terms_save_columns_visibility( table_key, table_instance )
{
  if ( !table_instance || !table_instance.columns )
    return;

  var columns_count = table_instance.columns().count();
  var visible_map = [];
  var i = 0;

  for ( i = 0; i < columns_count; i++ )
  {
    if ( table_key === 'search' && i === 0 )
    {
      visible_map.push( true );
      continue;
    }

    if ( table_key === 'negative' && i === 0 )
    {
      visible_map.push( true );
      continue;
    }

    visible_map.push( table_instance.column( i ).visible() );
  }

  terms_storage_set( terms_columns_storage_key( table_key ), JSON.stringify( visible_map ) );
}

function terms_apply_saved_columns_visibility( table_key, table_instance )
{
  if ( !table_instance || !table_instance.columns )
    return;

  var columns_count = table_instance.columns().count();
  var saved_visibility = terms_get_saved_columns_visibility( table_key, columns_count );
  var i = 0;

  if ( !saved_visibility )
    return;

  for ( i = 0; i < columns_count; i++ )
  {
    var is_visible = saved_visibility[i];

    if ( table_key === 'search' && i === 0 )
      is_visible = true;

    if ( table_key === 'negative' && i === 0 )
      is_visible = true;

    table_instance.column( i ).visible( is_visible, false );
  }

  table_instance.columns.adjust().draw( false );
}

function terms_render_columns_picker( table_key, table_instance )
{
  var selector = TERMS_COLUMNS_LIST_SELECTORS[table_key] || '';
  var labels = TERMS_COLUMNS_LABELS[table_key] || [];
  var columns_count = ( table_instance && table_instance.columns ) ? table_instance.columns().count() : 0;
  var $list = $( selector );
  var i = 0;

  if ( !$list.length )
    return;

  $list.empty();

  if ( !columns_count )
  {
    $list.append( '<div class="terms-col-item">Brak kolumn.</div>' );
    return;
  }

  for ( i = 0; i < columns_count; i++ )
  {
    if ( table_key === 'search' && i === 0 )
      continue;

    if ( table_key === 'negative' && i === 0 )
      continue;

    var label = labels[i] || ( 'Kolumna ' + ( i + 1 ) );
    var checked = table_instance.column( i ).visible() ? ' checked' : '';
    var id = 'terms_col_' + table_key + '_' + i;

    $list.append(
      '<label class="terms-col-item" for="' + id + '">' +
        '<input type="checkbox" class="terms-col-toggle" id="' + id + '" data-table-key="' + table_key + '" data-col-index="' + i + '"' + checked + '>' +
        '<span>' + label + '</span>' +
      '</label>'
    );
  }
}

function terms_get_clicks_filter_value( selector )
{
  var raw = $( selector ).val();

  if ( raw === '' || raw === null || raw === undefined )
    return null;

  var n = parseInt( raw, 10 );

  if ( isNaN( n ) )
    return null;

  if ( n < 0 )
    n = 0;

  return n;
}

function terms_get_min_clicks_all()
{
  return terms_get_clicks_filter_value( '#terms_min_clicks_all' );
}

function terms_get_max_clicks_all()
{
  return terms_get_clicks_filter_value( '#terms_max_clicks_all' );
}

function terms_get_conversions_filter_value( selector )
{
  var raw = $( selector ).val();

  if ( raw === '' || raw === null || raw === undefined )
    return null;

  var normalized = String( raw ).replace( /\s+/g, '' ).replace( /,/g, '.' );
  var n = parseFloat( normalized );

  if ( isNaN( n ) )
    return null;

  if ( n < 0 )
    n = 0;

  return n;
}

function terms_get_min_conversions_all()
{
  return terms_get_conversions_filter_value( '#terms_min_conversions_all' );
}

function terms_get_max_conversions_all()
{
  return terms_get_conversions_filter_value( '#terms_max_conversions_all' );
}

function terms_register_search_filters()
{
  var ext_search = null;

  if ( terms_search_filter_registered )
    return;

  if ( $.fn.dataTable && $.fn.dataTable.ext && $.fn.dataTable.ext.search )
    ext_search = $.fn.dataTable.ext.search;
  else if ( typeof DataTable !== 'undefined' && DataTable.ext && DataTable.ext.search )
    ext_search = DataTable.ext.search;

  if ( !ext_search )
    return;

  ext_search.push( function( settings, data )
  {
    var table_id = settings && settings.nTable ? settings.nTable.id : '';
    var min_clicks = terms_get_min_clicks_all();
    var max_clicks = terms_get_max_clicks_all();
    var min_conversions = terms_get_min_conversions_all();
    var max_conversions = terms_get_max_conversions_all();

    if ( table_id !== 'terms_search_table' )
      return true;

    if ( min_clicks === null && max_clicks === null && min_conversions === null && max_conversions === null )
      return true;

    var clicks_raw = data && data.length > 3 ? String( data[3] ) : '0';
    var clicks = parseInt( clicks_raw.replace( /[^\d-]/g, '' ), 10 );

    if ( isNaN( clicks ) )
      clicks = 0;

    if ( min_clicks !== null && clicks < min_clicks )
      return false;

    if ( max_clicks !== null && clicks > max_clicks )
      return false;

    var conversions_raw = data && data.length > 6 ? String( data[6] ) : '0';
    var conversions = parseFloat( conversions_raw.replace( /\s+/g, '' ).replace( /,/g, '.' ).replace( /[^\d.-]/g, '' ) );

    if ( isNaN( conversions ) )
      conversions = 0;

    if ( min_conversions !== null && conversions < min_conversions )
      return false;

    if ( max_conversions !== null && conversions > max_conversions )
      return false;

    return true;
  } );

  terms_search_filter_registered = true;
}

function terms_set_ad_groups_collapsed( collapsed )
{
  var $card = $( '.terms-adgroups-card' );
  var $toggle = $( '#terms_adgroups_toggle' );

  if ( !$card.length || !$toggle.length )
    return;

  if ( collapsed )
  {
    $card.addClass( 'is-collapsed' );
    $toggle.attr( 'title', 'Rozwin tabele grup reklam' );
    $toggle.attr( 'aria-label', 'Rozwin tabele grup reklam' );
    $toggle.attr( 'aria-expanded', 'false' );
    $toggle.find( 'i' ).attr( 'class', 'fa-solid fa-chevron-down' );
  }
  else
  {
    $card.removeClass( 'is-collapsed' );
    $toggle.attr( 'title', 'Zwin tabele grup reklam' );
    $toggle.attr( 'aria-label', 'Zwin tabele grup reklam' );
    $toggle.attr( 'aria-expanded', 'true' );
    $toggle.find( 'i' ).attr( 'class', 'fa-solid fa-chevron-up' );
  }

  terms_storage_set( TERMS_STORAGE_AD_GROUPS_COLLAPSED, collapsed ? '1' : '0' );
}

function terms_restore_ad_groups_collapsed()
{
  var saved = terms_storage_get( TERMS_STORAGE_AD_GROUPS_COLLAPSED );
  terms_set_ad_groups_collapsed( saved === '1' );
}

function terms_get_saved_page( table_type )
{
  var page_raw = terms_storage_get( terms_page_storage_key( table_type ) );
  var page = parseInt( page_raw, 10 );

  if ( isNaN( page ) || page < 0 )
    return 0;

  return page;
}

function terms_save_current_page( table_type, table_instance )
{
  if ( !table_instance || typeof table_instance.page !== 'function' )
    return;

  var info = table_instance.page.info();
  if ( !info )
    return;

  terms_storage_set( terms_page_storage_key( table_type ), info.page );
}

function terms_restore_saved_page( table_type, table_instance )
{
  if ( !table_instance || typeof table_instance.page !== 'function' )
    return;

  var info = table_instance.page.info();
  if ( !info || !info.pages )
    return;

  var saved_page = terms_get_saved_page( table_type );
  var page_to_set = saved_page;

  if ( page_to_set >= info.pages )
    page_to_set = info.pages - 1;

  if ( page_to_set < 0 )
    page_to_set = 0;

  if ( page_to_set !== info.page )
    table_instance.page( page_to_set ).draw( 'page' );
}

function format_num( value, digits )
{
  var n = Number( value || 0 );
  return n.toLocaleString( 'pl-PL', {
    minimumFractionDigits: digits || 0,
    maximumFractionDigits: digits || 0
  } );
}

function terms_to_number( value )
{
  if ( typeof value === 'number' )
  {
    return isNaN( value ) ? 0 : value;
  }

  if ( value === null || value === undefined )
  {
    return 0;
  }

  var str = String( value ).trim();
  if ( !str )
  {
    return 0;
  }

  str = str.replace( /\s+/g, '' ).replace( /,/g, '.' );
  var num = Number( str );
  return isNaN( num ) ? 0 : num;
}

function terms_percentile( sorted_values, percentile )
{
  var values = sorted_values || [];
  var n = values.length;

  if ( !n )
    return 0;

  if ( n === 1 )
    return values[0];

  var p = Math.min( 1, Math.max( 0, percentile ) );
  var index = ( n - 1 ) * p;
  var low = Math.floor( index );
  var high = Math.ceil( index );

  if ( low === high )
    return values[low];

  var weight = index - low;
  return values[low] + ( values[high] - values[low] ) * weight;
}

function terms_get_roas_bounds( rows, key )
{
  var values = [];

  ( rows || [] ).forEach( function( row )
  {
    values.push( terms_to_number( row && row[key] ) );
  } );

  if ( !values.length )
  {
    return { min: 0, max: 0 };
  }

  values.sort( function( a, b ) { return a - b; } );

  var raw_min = values[0];
  var raw_max = values[ values.length - 1 ];
  var robust_min = terms_percentile( values, 0.05 );
  var robust_max = terms_percentile( values, 0.95 );

  if ( robust_max <= robust_min )
  {
    robust_min = raw_min;
    robust_max = raw_max;
  }

  if ( robust_max <= robust_min )
  {
    robust_max = robust_min + 0.000001;
  }

  return {
    min: robust_min,
    max: robust_max
  };
}

function terms_render_roas_perf_cell( value, min, max )
{
  var roas_value = terms_to_number( value );
  var roas_min = terms_to_number( min );
  var roas_max = terms_to_number( max );
  var equal_range = false;

  if ( Math.abs( roas_max - roas_min ) < 0.000001 )
  {
    equal_range = true;
    roas_max = roas_min + 0.000001;
  }

  var roas_value_for_bar = roas_value;
  if ( roas_value_for_bar < roas_min ) roas_value_for_bar = roas_min;
  if ( roas_value_for_bar > roas_max ) roas_value_for_bar = roas_max;

  var t = ( roas_value_for_bar - roas_min ) / ( roas_max - roas_min );

  if ( equal_range && roas_value > 0 )
    t = 1;

  if ( t < 0 ) t = 0;
  if ( t > 1 ) t = 1;

  var min_px = 20;
  var max_px = 120;
  var fill_px = Math.round( min_px + t * ( max_px - min_px ) );
  var color_hex = '#94A3B8';

  if ( roas_max > 0 )
  {
    var from = [ 231, 76, 60 ];
    var to = [ 46, 204, 113 ];
    var r = Math.round( from[0] + ( to[0] - from[0] ) * t );
    var g = Math.round( from[1] + ( to[1] - from[1] ) * t );
    var b = Math.round( from[2] + ( to[2] - from[2] ) * t );

    color_hex = '#' + [ r, g, b ].map( function( component )
    {
      var hex = component.toString( 16 ).toUpperCase();
      return hex.length === 1 ? '0' + hex : hex;
    } ).join( '' );
  }
  else
  {
    fill_px = 40;
  }

  return '<div class="roas-cell">' +
    format_num( roas_value, 0 ) + '%' +
    '<div class="roas-perf-wrap" title="Min: ' + format_num( roas_min, 2 ) + ' | Max: ' + format_num( roas_max, 2 ) + '" style="margin-top:4px;width:' + max_px + 'px;height:8px;background:#eee;border-radius:4px;overflow:hidden;">' +
      '<div class="roas-perf-fill" style="height:100%;width:' + fill_px + 'px;background:' + color_hex + ';"></div>' +
    '</div>' +
  '</div>';
}

function terms_escape_html( text )
{
  return String( text || '' )
    .replace( /&/g, '&amp;' )
    .replace( /</g, '&lt;' )
    .replace( />/g, '&gt;' )
    .replace( /"/g, '&quot;' )
    .replace( /'/g, '&#39;' );
}

function terms_build_debug_details_html( debug_payload )
{
  if ( !debug_payload )
    return '';

  return '<hr style="margin:10px 0;">' +
    '<details style="font-size:11px;color:#666;text-align:left;">' +
      '<summary style="cursor:pointer;font-weight:700;">Debug</summary>' +
      '<div style="margin-top:8px;">' +
        '<pre style="font-size:10px;max-height:220px;overflow:auto;background:#f5f5f5;padding:6px;">' + terms_escape_html( JSON.stringify( debug_payload, null, 2 ) ) + '</pre>' +
      '</div>' +
    '</details>';
}

function terms_get_selected_search_ids()
{
  var ids = [];

  Object.keys( terms_search_selected_ids ).forEach( function( key )
  {
    var id = parseInt( key, 10 );

    if ( !isNaN( id ) && id > 0 && terms_search_selected_ids[key] )
      ids.push( id );
  } );

  return ids;
}

function terms_sync_search_row_checkboxes()
{
  $( '#terms_search_table .terms-search-select-row' ).each( function()
  {
    var id = parseInt( $( this ).data( 'search-term-id' ), 10 );
    var checked = !isNaN( id ) && id > 0 && !!terms_search_selected_ids[id];
    $( this ).prop( 'checked', checked );
  } );
}

function terms_update_search_selection_ui()
{
  var selected_ids = terms_get_selected_search_ids();
  var selected_count = selected_ids.length;
  var $select_all = $( '#terms_search_select_all' );
  var page_ids = [];
  var selected_on_page = 0;
  var i = 0;

  $( '#terms_search_selected_count' ).text( selected_count );

  if ( !$select_all.length )
    return;

  if ( !terms_search_table )
  {
    $select_all.prop( 'checked', false );
    $select_all.prop( 'indeterminate', false );
    $select_all.prop( 'disabled', true );
    return;
  }

  var page_rows = terms_search_table.rows( { page: 'current', search: 'applied' } ).data();
  for ( i = 0; i < page_rows.length; i++ )
  {
    var id = parseInt( page_rows[i].id, 10 );
    if ( !isNaN( id ) && id > 0 )
      page_ids.push( id );
  }

  if ( !page_ids.length )
  {
    $select_all.prop( 'checked', false );
    $select_all.prop( 'indeterminate', false );
    $select_all.prop( 'disabled', true );
    return;
  }

  for ( i = 0; i < page_ids.length; i++ )
  {
    if ( terms_search_selected_ids[ page_ids[i] ] )
      selected_on_page++;
  }

  $select_all.prop( 'disabled', false );

  if ( selected_on_page === 0 )
  {
    $select_all.prop( 'checked', false );
    $select_all.prop( 'indeterminate', false );
    return;
  }

  if ( selected_on_page === page_ids.length )
  {
    $select_all.prop( 'checked', true );
    $select_all.prop( 'indeterminate', false );
    return;
  }

  $select_all.prop( 'checked', false );
  $select_all.prop( 'indeterminate', true );
}

function terms_clear_search_selection()
{
  terms_search_selected_ids = {};
  terms_update_search_selection_ui();
}

function terms_add_ai_recommendations_to_negative( selected_rows, options, done )
{
  var index = 0;
  var success_count = 0;
  var duplicate_count = 0;
  var failed = [];
  var debug_items = [];

  function next_request()
  {
    if ( index >= selected_rows.length )
    {
      done({
        success_count: success_count,
        duplicate_count: duplicate_count,
        failed_count: failed.length,
        failed: failed,
        debug_items: debug_items
      });
      return;
    }

    var item = selected_rows[index++];
    var request_payload = {
      search_term_id: item.search_term_id,
      match_type: options.match_type,
      scope: options.scope,
      keyword_text: item.keyword_text
    };

    $.ajax({
      url: '/campaign_terms/add_negative_keyword/',
      type: 'POST',
      data: request_payload,
      success: function( response )
      {
        var data = null;

        try
        {
          data = JSON.parse( response );
        }
        catch ( e )
        {
          data = null;
        }

        if ( data && data.success )
        {
          debug_items.push({
            phrase: item.keyword_text,
            success: true,
            duplicate: !!data.duplicate,
            request: request_payload,
            response: data,
            debug: data && data.debug ? data.debug : null
          });

          var verification = data && data.debug ? data.debug.verification : null;
          var verification_found = true;

          if ( verification && typeof verification === 'object' && Object.prototype.hasOwnProperty.call( verification, 'found' ) )
            verification_found = !!verification.found;

          if ( verification_found || data.duplicate )
          {
            success_count++;

            if ( data.duplicate )
              duplicate_count++;
          }
          else
          {
            failed.push({
              phrase: item.keyword_text,
              message: 'Brak potwierdzenia dodania frazy po stronie Google Ads.',
              error: '',
              debug: data && data.debug ? data.debug : null,
              response: data,
              request: request_payload
            });
          }
        }
        else
        {
          debug_items.push({
            phrase: item.keyword_text,
            success: false,
            request: request_payload,
            response: data,
            debug: data && data.debug ? data.debug : null,
            error: data && data.error ? data.error : ''
          });

          failed.push({
            phrase: item.keyword_text,
            message: data && data.message ? data.message : 'Nieznany blad',
            error: data && data.error ? data.error : '',
            debug: data && data.debug ? data.debug : null,
            response: data,
            request: request_payload
          });
        }

        next_request();
      },
      error: function( xhr, status_text, error_thrown )
      {
        debug_items.push({
          phrase: item.keyword_text,
          success: false,
          request: request_payload,
          response: {
            status: xhr && xhr.status ? xhr.status : 0,
            response_text: xhr && xhr.responseText ? String( xhr.responseText ).slice( 0, 1000 ) : ''
          },
          debug: null,
          error: String( error_thrown || status_text || '' )
        });

        failed.push({
          phrase: item.keyword_text,
          message: 'Blad komunikacji z serwerem',
          error: String( error_thrown || status_text || '' ),
          debug: null,
          request: request_payload,
          response: {
            status: xhr && xhr.status ? xhr.status : 0,
            response_text: xhr && xhr.responseText ? String( xhr.responseText ).slice( 0, 1000 ) : ''
          }
        });
        next_request();
      }
    });
  }

  next_request();
}

function terms_open_ai_recommendations_modal( recommendations, analyzed_count )
{
  var rows = Array.isArray( recommendations ) ? recommendations : [];
  var roas_all_bounds = terms_get_roas_bounds( rows, 'roas_all_time' );
  var recommendation_map = {};
  var exclude_count = 0;
  var html_rows = '';

  rows.forEach( function( item )
  {
    var search_term_id = parseInt( item.search_term_id || item.id || 0, 10 );
    if ( !isNaN( search_term_id ) && search_term_id > 0 )
    {
      recommendation_map[ search_term_id ] = {
        keyword_text: String( item.phrase || '' )
      };
    }

    var action = String( item.action || '' ).toLowerCase() === 'exclude' ? 'exclude' : 'keep';
    var checked = action === 'exclude' ? ' checked' : '';
    var action_label = action === 'exclude' ? 'wyklucz' : 'zostaw';
    var action_class = action === 'exclude' ? 'action-exclude' : 'action-keep';

    if ( action === 'exclude' )
      exclude_count++;

    html_rows +=
      '<tr>' +
        '<td style="text-align:center;"><input type="checkbox" class="terms-ai-select-row" data-search-term-id="' + search_term_id + '"' + checked + '></td>' +
        '<td class="term-col" title="' + terms_escape_html( item.phrase || '' ) + '">' + terms_escape_html( item.phrase || '' ) + '</td>' +
        '<td><span class="terms-ai-action-badge ' + action_class + '">' + action_label + '</span></td>' +
        '<td class="reason-col">' + terms_escape_html( item.reason || '' ) + '</td>' +
        '<td style="text-align:right;">' + format_num( item.clicks_all_time || 0, 0 ) + '</td>' +
        '<td style="text-align:right;">' + format_num( item.cost_all_time || 0, 2 ) + '</td>' +
        '<td style="text-align:right;">' + format_num( item.conversion_value_all_time || 0, 2 ) + '</td>' +
        '<td style="text-align:right;">' + format_num( item.conversions_all_time || 0, 2 ) + '</td>' +
        '<td style="text-align:right;">' + terms_render_roas_perf_cell( item.roas_all_time || 0, roas_all_bounds.min, roas_all_bounds.max ) + '</td>' +
      '</tr>';
  } );

  if ( !html_rows )
  {
    html_rows = '<tr><td colspan="9" style="text-align:center;color:#94A3B8;font-style:italic;">Brak rekomendacji do wyswietlenia.</td></tr>';
  }

  var content_html =
    '<div class="terms-ai-modal-toolbar">' +
      '<label><input type="checkbox" id="terms_ai_select_all" checked> Zaznacz wszystkie</label>' +
      '<label for="terms_ai_scope">Poziom</label>' +
      '<select id="terms_ai_scope" class="form-control">' +
        '<option value="campaign" selected>Kampania</option>' +
        '<option value="ad_group">Grupa reklam</option>' +
      '</select>' +
      '<label for="terms_ai_match_type">Match type</label>' +
      '<select id="terms_ai_match_type" class="form-control">' +
        '<option value="PHRASE" selected>Dopasowanie do wyrazenia</option>' +
        '<option value="EXACT">Dopasowanie scisle</option>' +
        '<option value="BROAD">Dopasowanie przyblizone</option>' +
      '</select>' +
    '</div>' +
    '<div class="terms-ai-summary">Przeanalizowano: <strong>' + format_num( analyzed_count || rows.length, 0 ) + '</strong>, rekomendowane do wykluczenia: <strong>' + format_num( exclude_count, 0 ) + '</strong>.</div>' +
    '<div class="terms-ai-results-wrap">' +
      '<table class="terms-ai-results-table">' +
        '<thead>' +
          '<tr>' +
            '<th style="width:42px;text-align:center;">#</th>' +
            '<th>Fraza</th>' +
            '<th style="width:88px;">Akcja</th>' +
            '<th>Powod</th>' +
            '<th style="width:90px;text-align:right;">Klik. all</th>' +
            '<th style="width:90px;text-align:right;">Koszt all</th>' +
            '<th style="width:95px;text-align:right;">Wartosc all</th>' +
            '<th style="width:90px;text-align:right;">Konw. all</th>' +
            '<th style="width:140px;text-align:right;">ROAS all</th>' +
          '</tr>' +
        '</thead>' +
        '<tbody>' + html_rows + '</tbody>' +
      '</table>' +
    '</div>';

  terms_ai_modal_instance = $.confirm({
    title: 'Analiza ChatGPT - fraza / akcja / powod',
    columnClass: 'col-md-11',
    content: content_html,
    type: 'blue',
    buttons: {
      apply: {
        text: 'Dodaj zaznaczone do wykluczajacych',
        btnClass: 'btn-blue',
        action: function()
        {
          var modal = this;
          var selected_rows = [];

          modal.$content.find( '.terms-ai-select-row:checked' ).each( function()
          {
            var search_term_id = parseInt( $( this ).data( 'search-term-id' ), 10 );
            var keyword_text = '';

            if ( !isNaN( search_term_id ) && search_term_id > 0 && recommendation_map[ search_term_id ] )
              keyword_text = String( recommendation_map[ search_term_id ].keyword_text || '' );

            keyword_text = $.trim( keyword_text );

            if ( !isNaN( search_term_id ) && search_term_id > 0 && keyword_text )
            {
              selected_rows.push({
                search_term_id: search_term_id,
                keyword_text: keyword_text
              });
            }
          } );

          if ( !selected_rows.length )
          {
            $.alert({
              title: 'Uwaga',
              columnClass: 'col-md-4 col-md-offset-4',
              content: 'Zaznacz frazy, ktore chcesz dodac do wykluczajacych.',
              type: 'orange'
            });
            return false;
          }

          modal.showLoading( true );

          terms_add_ai_recommendations_to_negative(
            selected_rows,
            {
              scope: modal.$content.find( '#terms_ai_scope' ).val() || 'campaign',
              match_type: modal.$content.find( '#terms_ai_match_type' ).val() || 'PHRASE'
            },
            function( result )
            {
              modal.close();
              var debug_payload = result && result.debug_items ? result.debug_items.slice( 0, 20 ) : null;
              var debug_html = terms_build_debug_details_html( debug_payload );

              if ( result.failed_count === 0 )
              {
                var success_message = 'Dodano do wykluczajacych: ' + result.success_count + '.';

                if ( result.duplicate_count > 0 )
                  success_message += '<br><small style="display:block;margin-top:8px;color:#64748B;">Duplikaty (juz istnialy w Google Ads): ' + result.duplicate_count + '.</small>';

                success_message += debug_html;

                $.alert({
                  title: 'Sukces',
                  columnClass: 'col-md-4 col-md-offset-4',
                  content: success_message,
                  type: 'green'
                });
                load_phrase_tables();
                return;
              }

              $.alert({
                title: result.success_count > 0 ? 'Czesciowy sukces' : 'Blad',
                columnClass: 'col-md-5 col-md-offset-4',
                content: 'Dodano: ' + result.success_count + ', bledy: ' + result.failed_count + '.' +
                  ( result.duplicate_count > 0
                    ? '<br><small style="display:block;margin-top:8px;color:#64748B;">Duplikaty (juz istnialy w Google Ads): ' + result.duplicate_count + '.</small>'
                    : '' ) +
                  ( result.failed && result.failed.length
                    ? '<br><small style="display:block;margin-top:8px;max-height:160px;overflow:auto;">' +
                      result.failed.slice( 0, 10 ).map( function( f )
                      {
                        return '• ' + terms_escape_html( String( f.phrase || '' ) ) + ': ' + terms_escape_html( String( f.message || '' ) ) +
                          ( f.error ? ' (' + terms_escape_html( String( f.error ) ) + ')' : '' );
                      } ).join( '<br>' ) +
                      ( result.failed.length > 10 ? '<br>...i kolejne ' + ( result.failed.length - 10 ) + ' bledow.' : '' ) +
                      '</small>'
                    : '' ),
                type: result.success_count > 0 ? 'orange' : 'red'
              });

              if ( result.success_count > 0 )
                load_phrase_tables();
            }
          );

          return false;
        }
      },
      close: { text: 'Zamknij' }
    },
    onDestroy: function()
    {
      terms_ai_modal_instance = null;
    }
  });
}

function destroy_table_if_exists( selector )
{
  if ( $.fn.DataTable.isDataTable( selector ) )
  {
    $( selector ).DataTable().destroy();
    $( selector + ' tbody' ).empty();
  }
}

function apply_header_titles( selector )
{
  $( selector + ' thead th' ).each( function()
  {
    var $th = $( this );
    var title = $.trim( $th.find( '.dt-column-title' ).first().text() || $th.text() );

    if ( title )
    {
      $th.attr( 'title', title );
      $th.find( '.dt-column-title' ).attr( 'title', title );
    }
  } );
}

function terms_get_selected_negative_ids()
{
  var ids = [];

  Object.keys( terms_negative_selected_ids ).forEach( function( key )
  {
    var id = parseInt( key, 10 );

    if ( !isNaN( id ) && id > 0 && terms_negative_selected_ids[key] )
      ids.push( id );
  } );

  return ids;
}

function terms_sync_negative_row_checkboxes()
{
  $( '#terms_negative_table .terms-negative-select-row' ).each( function()
  {
    var id = parseInt( $( this ).data( 'negative-keyword-id' ), 10 );
    var checked = !isNaN( id ) && id > 0 && !!terms_negative_selected_ids[id];
    $( this ).prop( 'checked', checked );
  } );
}

function terms_update_negative_selection_ui()
{
  var selected_ids = terms_get_selected_negative_ids();
  var selected_count = selected_ids.length;
  var $select_all = $( '#terms_negative_select_all' );
  var page_ids = [];
  var selected_on_page = 0;
  var i = 0;

  $( '#terms_negative_selected_count' ).text( selected_count );
  $( '#terms_delete_selected_negative' ).prop( 'disabled', selected_count === 0 );

  if ( !$select_all.length )
    return;

  if ( !terms_negative_table )
  {
    $select_all.prop( 'checked', false );
    $select_all.prop( 'indeterminate', false );
    $select_all.prop( 'disabled', true );
    return;
  }

  var page_rows = terms_negative_table.rows( { page: 'current' } ).data();
  for ( i = 0; i < page_rows.length; i++ )
  {
    var id = parseInt( page_rows[i].id, 10 );
    if ( !isNaN( id ) && id > 0 )
      page_ids.push( id );
  }

  if ( !page_ids.length )
  {
    $select_all.prop( 'checked', false );
    $select_all.prop( 'indeterminate', false );
    $select_all.prop( 'disabled', true );
    return;
  }

  for ( i = 0; i < page_ids.length; i++ )
  {
    if ( terms_negative_selected_ids[ page_ids[i] ] )
      selected_on_page++;
  }

  $select_all.prop( 'disabled', false );

  if ( selected_on_page === 0 )
  {
    $select_all.prop( 'checked', false );
    $select_all.prop( 'indeterminate', false );
    return;
  }

  if ( selected_on_page === page_ids.length )
  {
    $select_all.prop( 'checked', true );
    $select_all.prop( 'indeterminate', false );
    return;
  }

  $select_all.prop( 'checked', false );
  $select_all.prop( 'indeterminate', true );
}

function terms_clear_negative_selection()
{
  terms_negative_selected_ids = {};
  terms_update_negative_selection_ui();
}


var MATCH_TYPE_LABELS = { 'BROAD': 'Przyblizone', 'PHRASE': 'Do wyrazenia', 'EXACT': 'Scisle' };
function render_match_type_label( data, type ) {
  if ( type !== 'display' ) return data || '';
  var val = String( data || '' ).toUpperCase();
  return MATCH_TYPE_LABELS[val] || val;
}

function build_ad_groups_table( rows )
{
  destroy_table_if_exists( '#terms_ad_groups_table' );

  terms_ad_groups_table = new DataTable( '#terms_ad_groups_table', {
    data: rows || [],
    stateSave: true,
    processing: false,
    serverSide: false,
    autoWidth: false,
    searching: false,
    lengthChange: false,
    pageLength: 15,
    pagingType: 'simple_numbers',
    order: [],
    columns: [
      { data: 'ad_group_name', defaultContent: '' },
      { data: 'clicks_30', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) : Number( data || 0 ); } },
      { data: 'cost_30', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'conversion_value_30', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'roas_30', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) + '%' : Number( data || 0 ); } },
      { data: 'clicks_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) : Number( data || 0 ); } },
      { data: 'cost_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'conversion_value_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'roas_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) + '%' : Number( data || 0 ); } }
    ],
    columnDefs: [
      { targets: 0, className: 'text-cell' },
      { targets: [1,5], className: 'num-cell', width: '80px' },
      { targets: [2,3,6,7], className: 'num-cell', width: '90px' },
      { targets: [4,8], className: 'num-cell', width: '85px' }
    ],
    language: {
      emptyTable: 'Brak danych do wyswietlenia',
      info: 'Wpisy _START_ - _END_ z _TOTAL_',
      paginate: { next: 'Dalej', previous: 'Wstecz' }
    }
  });

  terms_apply_saved_columns_visibility( 'ad_groups', terms_ad_groups_table );
  terms_render_columns_picker( 'ad_groups', terms_ad_groups_table );
}

function build_search_terms_table( rows, negative_keywords )
{
  destroy_table_if_exists( '#terms_search_table' );
  terms_search_table = null;
  terms_clear_search_selection();

  var roas_all_bounds = terms_get_roas_bounds( rows || [], 'roas_all_time' );

  var negative_set = {};
  ( negative_keywords || [] ).forEach( function( nk ) {
    negative_set[ String( nk.keyword_text || '' ).toLowerCase().trim() ] = true;
  });

  terms_search_table = new DataTable( '#terms_search_table', {
    data: rows || [],
    stateSave: true,
    processing: false,
    serverSide: false,
    autoWidth: false,
    searching: true,
    lengthChange: false,
    pageLength: 15,
    pagingType: 'simple_numbers',
    order: [[ 3, 'desc' ]],
    columns: [
      { data: 'id', orderable: false, searchable: false, width: '42px', render: function( data, type ) {
          var search_term_id = parseInt( data, 10 ) || 0;
          if ( type !== 'display' ) return search_term_id;
          return '<input type="checkbox" class="terms-search-select-row" data-search-term-id="' + search_term_id + '" aria-label="Zaznacz fraze do analizy">';
      } },
      { data: 'search_term', defaultContent: '', width: '340px' },
      { data: 'ad_group_name', defaultContent: '', width: '360px' },
      { data: 'clicks_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) : Number( data || 0 ); } },
      { data: 'cost_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'conversion_value_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
        { data: 'conversions_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
        { data: 'roas_all_time', render: function( data, type ){
          if ( type !== 'display' ) return Number( data || 0 );
          return terms_render_roas_perf_cell( data, roas_all_bounds.min, roas_all_bounds.max );
        } },
      { data: 'clicks_30', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) : Number( data || 0 ); } },
      { data: 'cost_30', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'conversion_value_30', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
        { data: 'conversions_30', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
        { data: 'roas_30', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) + '%' : Number( data || 0 ); } },
      { data: 'id', orderable: false, searchable: false, render: function( data, type, row ) {
          if ( type !== 'display' ) return data;
          return '<button type="button" class="terms-add-negative-btn" data-search-term-id="' + row.id + '" title="Dodaj do wykluczajacych"><i class="fa-solid fa-ban"></i></button>';
      } }
    ],
    columnDefs: [
      { targets: 0, className: 'dt-center terms-search-select-cell', width: '42px' },
      { targets: 1, className: 'text-cell phrase-nowrap', width: '220px' },
      { targets: 2, className: 'text-cell' },
      { targets: [3,8], className: 'num-cell', width: '70px' },
      { targets: [4,5,9,10], className: 'num-cell', width: '85px' },
      { targets: [6,11], className: 'num-cell', width: '80px' },
      { targets: [7,12], className: 'num-cell', width: '130px' },
      { targets: 13, className: 'dt-center', width: '50px' }
    ],
    createdRow: function( row, data ) {
      var term = String( data.search_term || '' ).toLowerCase().trim();
      if ( negative_set[ term ] )
      {
        $( row ).addClass( 'term-is-negative' );
      }
    },
    language: {
      emptyTable: 'Brak danych do wyswietlenia',
      info: 'Wpisy _START_ - _END_ z _TOTAL_',
      search: 'Szukaj:',
      paginate: { next: 'Dalej', previous: 'Wstecz' }
    }
  });

  terms_apply_saved_columns_visibility( 'search', terms_search_table );

  $( '#terms_search_table' )
    .off( 'page.dt.termsPagination' )
    .on( 'page.dt.termsPagination', function()
    {
      terms_save_current_page( 'search', terms_search_table );
    } )
    .off( 'draw.dt.termsSelection' )
    .on( 'draw.dt.termsSelection', function()
    {
      terms_sync_search_row_checkboxes();
      terms_update_search_selection_ui();
    } );

  var q = $( '#phrase_search_search' ).val();
  terms_search_table.search( q ).draw();
  terms_restore_saved_page( 'search', terms_search_table );
  terms_sync_search_row_checkboxes();
  terms_update_search_selection_ui();
  apply_header_titles( '#terms_search_table' );
  terms_render_columns_picker( 'search', terms_search_table );
}

function build_negative_terms_table( rows )
{
  destroy_table_if_exists( '#terms_negative_table' );
  terms_negative_table = null;
  terms_clear_negative_selection();

  terms_negative_table = new DataTable( '#terms_negative_table', {
    data: rows || [],
    stateSave: true,
    processing: false,
    serverSide: false,
    autoWidth: false,
    searching: true,
    lengthChange: false,
    pageLength: 15,
    pagingType: 'simple_numbers',
    order: [],
    columns: [
      { data: 'id', orderable: false, searchable: false, width: '42px', render: function( data, type ) {
          var negative_keyword_id = parseInt( data, 10 ) || 0;
          if ( type !== 'display' ) return negative_keyword_id;
          return '<input type="checkbox" class="terms-negative-select-row" data-negative-keyword-id="' + negative_keyword_id + '" aria-label="Zaznacz fraze do usuniecia">';
      } },
      { data: 'keyword_text', defaultContent: '', width: '520px' },
      { data: 'match_type', defaultContent: '', render: render_match_type_label },
      { data: 'id', orderable: false, searchable: false, render: function( data, type ) {
          if ( type !== 'display' ) return data;
          return '<button type="button" class="terms-remove-negative-btn" data-negative-keyword-id="' + data + '" title="Usun z wykluczajacych"><i class="fa-solid fa-trash"></i></button>';
      } },
      { data: 'scope', render: function( data, type, row ) {
          var scope = data === 'ad_group' ? 'Ad group' : 'Kampania';
          if ( data === 'ad_group' && row.ad_group_name )
            scope = 'Ad group: ' + row.ad_group_name;
          return scope;
      } }
    ],
    columnDefs: [
      { targets: 0, className: 'dt-center terms-negative-select-cell', width: '42px' },
      { targets: 1, className: 'text-cell phrase-nowrap' },
      { targets: 2, width: '120px' },
      { targets: 3, className: 'dt-center', width: '70px' },
      { targets: 4, className: 'text-cell', width: '150px' }
    ],
    language: {
      emptyTable: 'Brak danych do wyswietlenia',
      info: 'Wpisy _START_ - _END_ z _TOTAL_',
      search: 'Szukaj:',
      paginate: { next: 'Dalej', previous: 'Wstecz' }
    }
  });

  terms_apply_saved_columns_visibility( 'negative', terms_negative_table );

  $( '#terms_negative_table' )
    .off( 'page.dt.termsPagination' )
    .on( 'page.dt.termsPagination', function()
    {
      terms_save_current_page( 'negative', terms_negative_table );
    } )
    .off( 'draw.dt.termsSelection' )
    .on( 'draw.dt.termsSelection', function()
    {
      terms_sync_negative_row_checkboxes();
      terms_update_negative_selection_ui();
    } );

  var q = $( '#phrase_search_negative' ).val();
  terms_negative_table.search( q ).draw();
  terms_restore_saved_page( 'negative', terms_negative_table );
  terms_sync_negative_row_checkboxes();
  terms_update_negative_selection_ui();
  apply_header_titles( '#terms_negative_table' );
  terms_render_columns_picker( 'negative', terms_negative_table );
}

function build_keywords_table( rows )
{
  destroy_table_if_exists( '#terms_keywords_table' );

  var roas_all_bounds = terms_get_roas_bounds( rows || [], 'roas_all_time' );

  terms_keywords_table = new DataTable( '#terms_keywords_table', {
    data: rows || [],
    stateSave: true,
    processing: false,
    serverSide: false,
    autoWidth: false,
    searching: true,
    lengthChange: false,
    pageLength: 15,
    pagingType: 'simple_numbers',
    order: [[ 4, 'desc' ]],
    columns: [
      { data: 'keyword_text', defaultContent: '', render: function( data, type, row ) {
          if ( type !== 'display' ) return data;
          var text = $('<span>').text( data ).html();
          if ( row.status === 'PAUSED' ) return '<span class="text-muted">' + text + '</span>';
          return text;
      } },
      { data: 'match_type', defaultContent: '', render: render_match_type_label },
      { data: 'ad_group_name', defaultContent: '-' },
      { data: 'id', orderable: false, searchable: false, render: function( data, type, row ) {
          if ( type !== 'display' ) return data;
          var is_paused = ( row.status === 'PAUSED' );
          var toggle_icon = is_paused ? 'fa-play' : 'fa-pause';
          var toggle_title = is_paused ? 'Wznow fraze' : 'Wstrzymaj fraze';
          var toggle_class = is_paused ? 'text-success' : 'text-warning';
          return '<button type="button" class="terms-toggle-keyword-status-btn ' + toggle_class + '" data-keyword-id="' + data + '" title="' + toggle_title + '"><i class="fa-solid ' + toggle_icon + '"></i></button>' +
                 ' <button type="button" class="terms-change-match-type-btn" data-keyword-id="' + data + '" title="Zmien dopasowanie"><i class="fa-solid fa-pen-to-square"></i></button>' +
                 ' <button type="button" class="terms-delete-keyword-btn" data-keyword-id="' + data + '" title="Usun fraze"><i class="fa-solid fa-trash"></i></button>';
      } },
      { data: 'clicks_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) : Number( data || 0 ); } },
      { data: 'cost_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'conversion_value_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'conversions_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'roas_all_time', render: function( data, type ){
        if ( type !== 'display' ) return Number( data || 0 );
        return terms_render_roas_perf_cell( data, roas_all_bounds.min, roas_all_bounds.max );
      } },
      { data: 'clicks_30', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) : Number( data || 0 ); } },
      { data: 'cost_30', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'conversion_value_30', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'conversions_30', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
      { data: 'roas_30', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) + '%' : Number( data || 0 ); } }
    ],
    columnDefs: [
      { targets: 0, className: 'text-cell phrase-nowrap', width: '220px' },
      { targets: [1,2], className: 'text-cell', width: '140px' },
      { targets: 3, className: 'dt-center', width: '110px' },
      { targets: [4,9], className: 'num-cell', width: '70px' },
      { targets: [5,6,10,11], className: 'num-cell', width: '85px' },
      { targets: [7,12], className: 'num-cell', width: '80px' },
      { targets: [8,13], className: 'num-cell', width: '130px' }
    ],
    language: {
      emptyTable: 'Brak danych do wyswietlenia',
      info: 'Wpisy _START_ - _END_ z _TOTAL_',
      paginate: { next: 'Dalej', previous: 'Wstecz' }
    }
  });

  var q = $( '#phrase_search_keywords' ).val();
  terms_keywords_table.search( q ).draw();
  apply_header_titles( '#terms_keywords_table' );
  terms_render_columns_picker( 'keywords', terms_keywords_table );
}

function reset_all_tables()
{
  build_ad_groups_table( [] );
  build_search_terms_table( [] );
  build_negative_terms_table( [] );
  build_keywords_table( [] );
}

function load_phrase_tables()
{
  var campaign_id = $( '#terms_campaign_id' ).val();
  var ad_group_id = $( '#terms_ad_group_id' ).val();

  if ( !campaign_id )
  {
    reset_all_tables();
    return;
  }

  $.ajax({
    url: '/campaign_terms/get_campaign_phrase_details/',
    type: 'POST',
    data: {
      campaign_id: campaign_id,
      ad_group_id: ad_group_id
    },
    success: function( response )
    {
      var data = JSON.parse( response );
      var negative_keywords = data.negative_keywords || [];
      build_search_terms_table( data.search_terms || [], negative_keywords );
      build_negative_terms_table( negative_keywords );
      build_keywords_table( data.keywords || [] );
    }
  });
}

function load_ad_groups()
{
  var campaign_id = $( '#terms_campaign_id' ).val();
  var $ad_group_select = $( '#terms_ad_group_id' );
  var saved_ad_group_id = terms_storage_get( TERMS_STORAGE_AD_GROUP );

  $ad_group_select.empty();
  $ad_group_select.append( '<option value="">- wszystkie grupy -</option>' );

  if ( !campaign_id )
  {
    build_ad_groups_table( [] );
    load_phrase_tables();
    return;
  }

  $.ajax({
    url: '/campaign_terms/get_campaign_ad_groups/',
    type: 'POST',
    data: { campaign_id: campaign_id },
    success: function( response )
    {
      var data = JSON.parse( response );
      var ad_groups = data.ad_groups || [];
      build_ad_groups_table( ad_groups );

      ad_groups.forEach( function( row ) {
        $ad_group_select.append( '<option value="' + row.id + '">' + row.ad_group_name + '</option>' );
      });

      if ( saved_ad_group_id && $ad_group_select.find( 'option[value="' + saved_ad_group_id + '"]' ).length )
      {
        $ad_group_select.val( saved_ad_group_id );
      }

      load_phrase_tables();
    }
  });
}

function load_campaigns_for_client( restore_campaign_id )
{
  var client_id = $( '#terms_client_id' ).val();
  var $campaign_select = $( '#terms_campaign_id' );

  $campaign_select.empty();
  $campaign_select.append( '<option value="">- wybierz kampanie -</option>' );

  if ( !client_id )
  {
    $( '#terms_ad_group_id' ).val( '' );
    reset_all_tables();
    return;
  }

  $.ajax({
    url: '/campaign_terms/get_campaigns_list/client_id=' + client_id,
    type: 'GET',
    success: function( response )
    {
      var data = JSON.parse( response );
      var campaigns = Object.entries( data.campaigns || {} );

      campaigns = campaigns.filter( function( pair )
      {
        var row = pair[1] || {};
        var campaign_name = String( row.campaign_name || '' ).toLowerCase().trim();
        return campaign_name !== '--- konto ---';
      } );

      campaigns.sort( function( a, b ) {
        var nameA = String( ( a[1] && a[1].campaign_name ) ? a[1].campaign_name : '' ).toLowerCase();
        var nameB = String( ( b[1] && b[1].campaign_name ) ? b[1].campaign_name : '' ).toLowerCase();
        if ( nameA > nameB ) return 1;
        if ( nameA < nameB ) return -1;
        return 0;
      });

      campaigns.forEach( function( pair ) {
        var value = pair[1];
        $campaign_select.append( '<option value="' + value.id + '">' + value.campaign_name + '</option>' );
      });

      if ( restore_campaign_id && $campaign_select.find( 'option[value="' + restore_campaign_id + '"]' ).length )
      {
        $campaign_select.val( restore_campaign_id );
      }

      load_ad_groups();
    }
  });
}

$( function()
{
  terms_register_search_filters();

  var saved_min_clicks_all = terms_storage_get( TERMS_STORAGE_MIN_CLICKS_ALL );
  if ( saved_min_clicks_all !== '' )
    $( '#terms_min_clicks_all' ).val( saved_min_clicks_all );
  var saved_max_clicks_all = terms_storage_get( TERMS_STORAGE_MAX_CLICKS_ALL );
  if ( saved_max_clicks_all !== '' )
    $( '#terms_max_clicks_all' ).val( saved_max_clicks_all );
  var saved_min_conversions_all = terms_storage_get( TERMS_STORAGE_MIN_CONVERSIONS_ALL );
  if ( saved_min_conversions_all !== '' )
    $( '#terms_min_conversions_all' ).val( saved_min_conversions_all );
  var saved_max_conversions_all = terms_storage_get( TERMS_STORAGE_MAX_CONVERSIONS_ALL );
  if ( saved_max_conversions_all !== '' )
    $( '#terms_max_conversions_all' ).val( saved_max_conversions_all );

  $( 'body' ).on( 'change', '#terms_client_id', function()
  {
    var client_id = $( this ).val();
    terms_storage_set( TERMS_STORAGE_CLIENT, client_id );
    terms_storage_set( TERMS_STORAGE_CAMPAIGN, '' );
    terms_storage_set( TERMS_STORAGE_AD_GROUP, '' );
    load_campaigns_for_client( '' );
  });

  $( 'body' ).on( 'change', '#terms_campaign_id', function()
  {
    var campaign_id = $( this ).val();
    terms_storage_set( TERMS_STORAGE_CAMPAIGN, campaign_id );
    terms_storage_set( TERMS_STORAGE_AD_GROUP, '' );
    $( '#terms_ad_group_id' ).val( '' );
    load_ad_groups();
  });

  $( 'body' ).on( 'change', '#terms_ad_group_id', function()
  {
    terms_storage_set( TERMS_STORAGE_AD_GROUP, $( this ).val() );

    if ( terms_ad_groups_table )
    {
      terms_apply_saved_columns_visibility( 'ad_groups', terms_ad_groups_table );
      terms_render_columns_picker( 'ad_groups', terms_ad_groups_table );
      apply_header_titles( '#terms_ad_groups_table' );
    }

    load_phrase_tables();
  });

  $( 'body' ).on( 'click', '.terms-add-negative-btn', function()
  {
    var search_term_id = $( this ).data( 'search-term-id' );
    var row_data = terms_search_table ? terms_search_table.row( $( this ).closest( 'tr' ) ).data() : null;
    var selected_search_term = row_data ? String( row_data.search_term || '' ) : '';

    $.confirm({
      title: 'Dodaj do wykluczajacych',
      columnClass: 'col-md-4 col-md-offset-4',
      content:
        '<div class="form-group" style="margin-bottom:10px;">' +
          '<label for="negative_scope" style="display:block;margin-bottom:6px;">Poziom wykluczenia</label>' +
          '<select id="negative_scope" class="form-control">' +
            '<option value="campaign" selected>Kampania (zalecane)</option>' +
            '<option value="ad_group">Grupa reklam</option>' +
          '</select>' +
          '<small style="display:block;margin-top:6px;color:#64748B;">Kampania = widoczne w wykluczeniach kampanii. Grupa reklam = tylko w tej grupie.</small>' +
        '</div>' +
        '<div class="form-group" style="margin-bottom:0;">' +
          '<label for="negative_match_type" style="display:block;margin-bottom:6px;">Typ dopasowania</label>' +
          '<select id="negative_match_type" class="form-control">' +
            '<option value="PHRASE" selected>Dopasowanie do wyrazenia</option>' +
            '<option value="EXACT">Dopasowanie scisle</option>' +
            '<option value="BROAD">Dopasowanie przyblizone</option>' +
          '</select>' +
        '</div>' +
        '<div class="form-group" style="margin-top:10px;margin-bottom:0;">' +
          '<label for="negative_keyword_text" style="display:block;margin-bottom:6px;">Fraza wykluczajaca</label>' +
          '<input id="negative_keyword_text" type="text" class="form-control" placeholder="Wpisz fraze do wykluczenia..." />' +
          '<small style="display:block;margin-top:6px;color:#64748B;">Mozesz zmienic fraze przed zapisem, np. usunac jej fragment.</small>' +
        '</div>',
      type: 'blue',
      onContentReady: function()
      {
        this.$content.find( '#negative_keyword_text' ).val( selected_search_term );
      },
      buttons: {
        confirm: {
          text: 'Zapisz',
          btnClass: 'btn-blue',
          action: function()
          {
            var match_type = this.$content.find( '#negative_match_type' ).val() || 'PHRASE';
            var scope = this.$content.find( '#negative_scope' ).val() || 'campaign';
            var keyword_text = $.trim( this.$content.find( '#negative_keyword_text' ).val() || '' );
            var modal = this;

            if ( keyword_text === '' )
            {
              $.alert({
                title: 'Uwaga',
                columnClass: 'col-md-4 col-md-offset-4',
                content: 'Wpisz fraze, ktora ma zostac dodana do wykluczajacych.',
                type: 'orange'
              });
              return false;
            }

            modal.showLoading( true );

            $.ajax({
              url: '/campaign_terms/add_negative_keyword/',
              type: 'POST',
              data: {
                search_term_id: search_term_id,
                match_type: match_type,
                scope: scope,
                keyword_text: keyword_text
              },
              success: function( response )
              {
                var data = JSON.parse( response );
                modal.close();

                if ( data.success )
                {
                  var debugHtml = '';
                  if ( data.debug )
                  {
                    debugHtml = '<hr style="margin:10px 0;">' +
                      '<details style="font-size:11px;color:#666;text-align:left;">' +
                        '<summary style="cursor:pointer;font-weight:700;">Debug</summary>' +
                        '<div style="margin-top:8px;">' +
                          'Customer ID: ' + ( data.debug.customer_id || 'brak' ) + '<br>' +
                          'Campaign ID: ' + ( data.debug.campaign_external_id || 'brak' ) + '<br>' +
                          'Ad Group ID: ' + ( data.debug.ad_group_external_id || 'brak' ) + '<br>' +
                          'Scope: ' + ( data.debug.scope || 'brak' ) + '<br>' +
                          'Keyword: ' + ( data.debug.keyword_text || 'brak' ) + '<br>' +
                          'API response: <pre style="font-size:10px;max-height:120px;overflow:auto;background:#f5f5f5;padding:6px;margin-top:4px;">' + JSON.stringify( data.debug.api_response, null, 2 ) + '</pre>' +
                          'Verification: <pre style="font-size:10px;max-height:120px;overflow:auto;background:#f5f5f5;padding:6px;margin-top:4px;">' + JSON.stringify( data.debug.verification, null, 2 ) + '</pre>' +
                        '</div>' +
                      '</details>';
                  }
                  var successDialog = $.alert({
                    title: 'Sukces',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Fraza zostala dodana do wykluczajacych.' )
                      + '<br><small style="display:block;margin-top:8px;color:#64748B;">Zmiana moze byc widoczna w panelu Google Ads po 1-3 minutach.</small>'
                      + debugHtml,
                    type: 'green'
                  });
                  setTimeout( function() { successDialog.close(); }, 10000 );
                  load_phrase_tables();
                }
                else
                {
                  var debugHtml = '';
                  if ( data.debug )
                  {
                    debugHtml = '<hr style="margin:10px 0;">' +
                      '<details style="font-size:11px;color:#666;text-align:left;">' +
                        '<summary style="cursor:pointer;font-weight:700;">Debug</summary>' +
                        '<div style="margin-top:8px;">' +
                          '<pre style="font-size:10px;max-height:150px;overflow:auto;background:#f5f5f5;padding:6px;">' + JSON.stringify( data.debug, null, 2 ) + '</pre>' +
                        '</div>' +
                      '</details>';
                  }
                  $.alert({
                    title: 'Blad',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Nie udalo sie dodac frazy.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
                    type: 'red'
                  });
                }
              },
              error: function()
              {
                modal.close();
                $.alert({
                  title: 'Blad',
                  columnClass: 'col-md-4 col-md-offset-4',
                  content: 'Blad komunikacji z serwerem.',
                  type: 'red'
                });
              }
            });

            return false;
          }
        },
        cancel: { text: 'Anuluj' }
      }
    });
  });

  $( 'body' ).on( 'change', '#terms_ai_select_all', function()
  {
    if ( !terms_ai_modal_instance )
      return;

    var checked = $( this ).is( ':checked' );
    terms_ai_modal_instance.$content.find( '.terms-ai-select-row' ).prop( 'checked', checked );
  });

  $( 'body' ).on( 'click', '#terms_ai_analyze_btn', function()
  {
    var campaign_id = $( '#terms_campaign_id' ).val();
    var ad_group_id = $( '#terms_ad_group_id' ).val() || 0;
    var selected_ids = terms_get_selected_search_ids();
    var $btn = $( this );

    if ( !campaign_id )
    {
      $.alert({
        title: 'Uwaga',
        columnClass: 'col-md-4 col-md-offset-4',
        content: 'Wybierz kampanie przed analiza ChatGPT.',
        type: 'orange'
      });
      return;
    }

    if ( !selected_ids.length )
    {
      $.alert({
        title: 'Uwaga',
        columnClass: 'col-md-4 col-md-offset-4',
        content: 'Zaznacz frazy w tabeli, ktore chcesz wyslac do analizy.',
        type: 'orange'
      });
      return;
    }

    $btn.prop( 'disabled', true ).html( '<i class="fa-solid fa-spinner fa-spin"></i> Analizuje...' );

    $.ajax({
      url: '/campaign_terms/analyze_search_terms_with_ai/',
      type: 'POST',
      data: {
        campaign_id: campaign_id,
        ad_group_id: ad_group_id,
        search_term_ids: selected_ids
      },
      success: function( response )
      {
        var data = null;

        try
        {
          data = JSON.parse( response );
        }
        catch ( e )
        {
          data = null;
        }

        if ( data && data.success )
        {
          terms_open_ai_recommendations_modal( data.recommendations || [], data.analyzed_count || selected_ids.length );
          return;
        }

        $.alert({
          title: 'Blad',
          columnClass: 'col-md-5 col-md-offset-4',
          content: ( data && data.message ) ? data.message : 'Nie udalo sie wykonac analizy ChatGPT.',
          type: 'red'
        });
      },
      error: function()
      {
        $.alert({
          title: 'Blad',
          columnClass: 'col-md-4 col-md-offset-4',
          content: 'Blad komunikacji z serwerem.',
          type: 'red'
        });
      },
      complete: function()
      {
        $btn.prop( 'disabled', false ).html( '<i class="fa-solid fa-robot"></i> Analizuj w ChatGPT' );
      }
    });
  });

  $( 'body' ).on( 'change', '.terms-search-select-row', function()
  {
    var search_term_id = parseInt( $( this ).data( 'search-term-id' ), 10 );

    if ( isNaN( search_term_id ) || search_term_id <= 0 )
      return;

    if ( $( this ).is( ':checked' ) )
      terms_search_selected_ids[ search_term_id ] = true;
    else
      delete terms_search_selected_ids[ search_term_id ];

    terms_update_search_selection_ui();
  });

  $( 'body' ).on( 'change', '#terms_search_select_all', function()
  {
    if ( !terms_search_table )
      return;

    var should_select = $( this ).is( ':checked' );

    terms_search_table.rows( { page: 'current', search: 'applied' } ).every( function()
    {
      var row_data = this.data() || {};
      var search_term_id = parseInt( row_data.id, 10 );

      if ( isNaN( search_term_id ) || search_term_id <= 0 )
        return;

      if ( should_select )
        terms_search_selected_ids[ search_term_id ] = true;
      else
        delete terms_search_selected_ids[ search_term_id ];
    } );

    terms_sync_search_row_checkboxes();
    terms_update_search_selection_ui();
  });

  $( 'body' ).on( 'change', '.terms-negative-select-row', function()
  {
    var negative_keyword_id = parseInt( $( this ).data( 'negative-keyword-id' ), 10 );

    if ( isNaN( negative_keyword_id ) || negative_keyword_id <= 0 )
      return;

    if ( $( this ).is( ':checked' ) )
      terms_negative_selected_ids[ negative_keyword_id ] = true;
    else
      delete terms_negative_selected_ids[ negative_keyword_id ];

    terms_update_negative_selection_ui();
  });

  $( 'body' ).on( 'change', '#terms_negative_select_all', function()
  {
    if ( !terms_negative_table )
      return;

    var should_select = $( this ).is( ':checked' );

    terms_negative_table.rows( { page: 'current' } ).every( function()
    {
      var row_data = this.data() || {};
      var negative_keyword_id = parseInt( row_data.id, 10 );

      if ( isNaN( negative_keyword_id ) || negative_keyword_id <= 0 )
        return;

      if ( should_select )
        terms_negative_selected_ids[ negative_keyword_id ] = true;
      else
        delete terms_negative_selected_ids[ negative_keyword_id ];
    } );

    terms_sync_negative_row_checkboxes();
    terms_update_negative_selection_ui();
  });

  $( 'body' ).on( 'click', '#terms_delete_selected_negative', function()
  {
    var selected_ids = terms_get_selected_negative_ids();
    var selected_count = selected_ids.length;

    if ( !selected_count )
    {
      $.alert({
        title: 'Uwaga',
        columnClass: 'col-md-4 col-md-offset-4',
        content: 'Zaznacz frazy, ktore chcesz usunac.',
        type: 'orange'
      });
      return;
    }

    $.confirm({
      title: 'Usun zaznaczone frazy',
      columnClass: 'col-md-4 col-md-offset-4',
      content: 'Czy na pewno usunac zaznaczone frazy wykluczajace (<strong>' + selected_count + '</strong>)? Operacja zostanie wyslana do Google Ads API.',
      type: 'red',
      buttons: {
        confirm: {
          text: 'Usun',
          btnClass: 'btn-red',
          keys: [ 'enter' ],
          action: function()
          {
            var modal = this;
            modal.showLoading( true );

            $.ajax({
              url: '/campaign_terms/delete_negative_keywords/',
              type: 'POST',
              data: { negative_keyword_ids: selected_ids },
              success: function( response )
              {
                var data = JSON.parse( response );
                modal.close();
                var debugHtml = terms_build_debug_details_html( data && data.debug ? data.debug : null );

                if ( data.success )
                {
                  $.alert({
                    title: data.partial ? 'Czesciowy sukces' : 'Sukces',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Frazy zostaly usuniete z wykluczajacych.' ) + debugHtml,
                    type: data.partial ? 'orange' : 'green'
                  });

                  terms_clear_negative_selection();
                  load_phrase_tables();
                  return;
                }

                $.alert({
                  title: 'Blad',
                  columnClass: 'col-md-4 col-md-offset-4',
                  content: ( data.message || 'Nie udalo sie usunac zaznaczonych fraz.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
                  type: 'red'
                });
              },
              error: function()
              {
                modal.close();
                $.alert({
                  title: 'Blad',
                  columnClass: 'col-md-4 col-md-offset-4',
                  content: 'Blad komunikacji z serwerem.',
                  type: 'red'
                });
              }
            });

            return false;
          }
        },
        cancel: { text: 'Anuluj' }
      }
    });
  });

  $( 'body' ).on( 'click', '.terms-remove-negative-btn', function()
  {
    var negative_keyword_id = parseInt( $( this ).data( 'negative-keyword-id' ), 10 );
    var row_data = terms_negative_table ? terms_negative_table.row( $( this ).closest( 'tr' ) ).data() : null;
    var keyword_text = row_data ? String( row_data.keyword_text || '' ) : '';

    if ( !negative_keyword_id )
    {
      return;
    }

    $.confirm({
      title: 'Usun fraze wykluczajaca',
      columnClass: 'col-md-4 col-md-offset-4',
      content: 'Czy na pewno usunac fraze <strong>' + keyword_text + '</strong> z wykluczajacych? Operacja zostanie wyslana do Google Ads API.',
      type: 'red',
      buttons: {
        confirm: {
          text: 'Usun',
          btnClass: 'btn-red',
          keys: [ 'enter' ],
          action: function()
          {
            var modal = this;
            modal.showLoading( true );

            $.ajax({
              url: '/campaign_terms/delete_negative_keyword/',
              type: 'POST',
              data: { negative_keyword_id: negative_keyword_id },
              success: function( response )
              {
                var data = JSON.parse( response );
                modal.close();
                var debugHtml = terms_build_debug_details_html( data && data.debug ? data.debug : null );

                if ( data.success )
                {
                  $.alert({
                    title: 'Sukces',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Fraza zostala usunieta z wykluczajacych.' ) + debugHtml,
                    type: 'green'
                  });
                  load_phrase_tables();
                  return;
                }

                $.alert({
                  title: 'Blad',
                  columnClass: 'col-md-4 col-md-offset-4',
                  content: ( data.message || 'Nie udalo sie usunac frazy.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
                  type: 'red'
                });
              },
              error: function()
              {
                modal.close();
                $.alert({
                  title: 'Blad',
                  columnClass: 'col-md-4 col-md-offset-4',
                  content: 'Blad komunikacji z serwerem.',
                  type: 'red'
                });
              }
            });

            return false;
          }
        },
        cancel: { text: 'Anuluj' }
      }
    });
  });

  $( 'body' ).on( 'input', '#phrase_search_search', function()
  {
    var q = $( this ).val();
    if ( terms_search_table )
      terms_search_table.search( q ).draw();
  });

  $( 'body' ).on( 'input', '#phrase_search_negative', function()
  {
    var q = $( this ).val();
    if ( terms_negative_table )
      terms_negative_table.search( q ).draw();
  });

  $( 'body' ).on( 'input', '#phrase_search_keywords', function()
  {
    var q = $( this ).val();
    if ( terms_keywords_table )
      terms_keywords_table.search( q ).draw();
  });

  $( 'body' ).on( 'input change', '#terms_min_clicks_all, #terms_max_clicks_all, #terms_min_conversions_all, #terms_max_conversions_all', function()
  {
    terms_storage_set( TERMS_STORAGE_MIN_CLICKS_ALL, $( '#terms_min_clicks_all' ).val() );
    terms_storage_set( TERMS_STORAGE_MAX_CLICKS_ALL, $( '#terms_max_clicks_all' ).val() );
    terms_storage_set( TERMS_STORAGE_MIN_CONVERSIONS_ALL, $( '#terms_min_conversions_all' ).val() );
    terms_storage_set( TERMS_STORAGE_MAX_CONVERSIONS_ALL, $( '#terms_max_conversions_all' ).val() );
    if ( terms_search_table )
      terms_search_table.draw();
  });

  $( 'body' ).on( 'change', '.terms-col-toggle', function()
  {
    var table_key = $( this ).data( 'table-key' );
    var col_index = parseInt( $( this ).data( 'col-index' ), 10 );
    var is_visible = $( this ).is( ':checked' );
    var table = terms_get_table_instance( table_key );
    var selector = TERMS_COLUMNS_TABLE_SELECTORS[table_key] || '';

    if ( !table || isNaN( col_index ) )
      return;

    table.column( col_index ).visible( is_visible, false );
    table.columns.adjust().draw( false );
    terms_save_columns_visibility( table_key, table );

    if ( selector )
      apply_header_titles( selector );
  });

  $( 'body' ).on( 'click', '#terms_adgroups_toggle', function()
  {
    var was_collapsed = $( '.terms-adgroups-card' ).hasClass( 'is-collapsed' );

    terms_set_ad_groups_collapsed( !was_collapsed );

    if ( was_collapsed && terms_ad_groups_table )
      terms_ad_groups_table.columns.adjust().draw( false );
  });

  $( 'body' ).on( 'click', '.terms-change-match-type-btn', function()
  {
    var keyword_id = parseInt( $( this ).data( 'keyword-id' ), 10 );
    var row_data = terms_keywords_table ? terms_keywords_table.row( $( this ).closest( 'tr' ) ).data() : null;
    var keyword_text = row_data ? String( row_data.keyword_text || '' ) : '';
    var current_match = row_data ? String( row_data.match_type || 'BROAD' ).toUpperCase() : 'BROAD';

    if ( !keyword_id ) return;

    $.confirm({
      title: 'Zmien dopasowanie frazy',
      columnClass: 'col-md-4 col-md-offset-4',
      content:
        '<div style="margin-bottom:10px;"><strong>' + $('<span>').text( keyword_text ).html() + '</strong></div>' +
        '<div class="form-group" style="margin-bottom:0;">' +
          '<label for="kw_new_match_type" style="display:block;margin-bottom:6px;">Nowy typ dopasowania</label>' +
          '<select id="kw_new_match_type" class="form-control">' +
            '<option value="BROAD"' + ( current_match === 'BROAD' ? ' selected' : '' ) + '>Dopasowanie przyblizone</option>' +
            '<option value="PHRASE"' + ( current_match === 'PHRASE' ? ' selected' : '' ) + '>Dopasowanie do wyrazenia</option>' +
            '<option value="EXACT"' + ( current_match === 'EXACT' ? ' selected' : '' ) + '>Dopasowanie scisle</option>' +
          '</select>' +
          '<small style="display:block;margin-top:6px;color:#64748B;">Obecne: ' + current_match + '. Zmiana usunie stary keyword i doda nowy w Google Ads.</small>' +
        '</div>',
      type: 'blue',
      buttons: {
        confirm: {
          text: 'Zmien',
          btnClass: 'btn-blue',
          action: function()
          {
            var new_match_type = this.$content.find( '#kw_new_match_type' ).val() || 'BROAD';
            var modal = this;

            if ( new_match_type === current_match )
            {
              $.alert({ title: 'Info', columnClass: 'col-md-4 col-md-offset-4', content: 'Wybrany typ dopasowania jest taki sam jak obecny.', type: 'blue' });
              return;
            }

            modal.showLoading( true );

            $.ajax({
              url: '/campaign_terms/update_keyword_match_type/',
              type: 'POST',
              data: { keyword_id: keyword_id, new_match_type: new_match_type },
              success: function( response )
              {
                var data = JSON.parse( response );
                modal.close();

                if ( data.success )
                {
                  var debugHtml = terms_build_debug_details_html( data.debug || null );
                  var successDialog = $.alert({
                    title: 'Sukces',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Dopasowanie zmienione.' ) + debugHtml,
                    type: 'green'
                  });
                  setTimeout( function() { successDialog.close(); }, 8000 );
                  load_phrase_tables();
                }
                else
                {
                  var debugHtml = terms_build_debug_details_html( data.debug || null );
                  $.alert({
                    title: 'Blad',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Nie udalo sie zmienic dopasowania.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
                    type: 'red'
                  });
                }
              },
              error: function()
              {
                modal.close();
                $.alert({ title: 'Blad', columnClass: 'col-md-4 col-md-offset-4', content: 'Blad komunikacji z serwerem.', type: 'red' });
              }
            });

            return false;
          }
        },
        cancel: { text: 'Anuluj' }
      }
    });
  });

  $( 'body' ).on( 'click', '.terms-delete-keyword-btn', function()
  {
    var keyword_id = parseInt( $( this ).data( 'keyword-id' ), 10 );
    var row_data = terms_keywords_table ? terms_keywords_table.row( $( this ).closest( 'tr' ) ).data() : null;
    var keyword_text = row_data ? String( row_data.keyword_text || '' ) : '';

    if ( !keyword_id ) return;

    $.confirm({
      title: 'Usun fraze',
      columnClass: 'col-md-4 col-md-offset-4',
      content: 'Czy na pewno usunac fraze <strong>' + $('<span>').text( keyword_text ).html() + '</strong>? Operacja zostanie wyslana do Google Ads API.',
      type: 'red',
      buttons: {
        confirm: {
          text: 'Usun',
          btnClass: 'btn-red',
          keys: [ 'enter' ],
          action: function()
          {
            var modal = this;
            modal.showLoading( true );

            $.ajax({
              url: '/campaign_terms/delete_keyword/',
              type: 'POST',
              data: { keyword_id: keyword_id },
              success: function( response )
              {
                var data = JSON.parse( response );
                modal.close();
                var debugHtml = terms_build_debug_details_html( data.debug || null );

                if ( data.success )
                {
                  $.alert({
                    title: 'Sukces',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Fraza zostala usunieta.' ) + debugHtml,
                    type: 'green'
                  });
                  load_phrase_tables();
                }
                else
                {
                  $.alert({
                    title: 'Blad',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Nie udalo sie usunac frazy.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
                    type: 'red'
                  });
                }
              },
              error: function()
              {
                modal.close();
                $.alert({ title: 'Blad', columnClass: 'col-md-4 col-md-offset-4', content: 'Blad komunikacji z serwerem.', type: 'red' });
              }
            });

            return false;
          }
        },
        cancel: { text: 'Anuluj' }
      }
    });
  });

  $( 'body' ).on( 'click', '.terms-toggle-keyword-status-btn', function()
  {
    var btn = $( this );
    var keyword_id = parseInt( btn.data( 'keyword-id' ), 10 );
    var row_data = terms_keywords_table ? terms_keywords_table.row( btn.closest( 'tr' ) ).data() : null;
    var keyword_text = row_data ? String( row_data.keyword_text || '' ) : '';
    var is_paused = row_data && row_data.status === 'PAUSED';

    if ( !keyword_id ) return;

    var action_label = is_paused ? 'wznowic' : 'wstrzymac';
    var action_past = is_paused ? 'wznowiona' : 'wstrzymana';

    $.confirm({
      title: is_paused ? 'Wznow fraze' : 'Wstrzymaj fraze',
      columnClass: 'col-md-4 col-md-offset-4',
      content: 'Czy na pewno ' + action_label + ' fraze <strong>' + $('<span>').text( keyword_text ).html() + '</strong>?',
      type: is_paused ? 'green' : 'orange',
      buttons: {
        confirm: {
          text: is_paused ? 'Wznow' : 'Wstrzymaj',
          btnClass: is_paused ? 'btn-green' : 'btn-warning',
          keys: [ 'enter' ],
          action: function()
          {
            var modal = this;
            modal.showLoading( true );

            $.ajax({
              url: '/campaign_terms/toggle_keyword_status/',
              type: 'POST',
              data: { keyword_id: keyword_id },
              success: function( response )
              {
                var data = JSON.parse( response );
                modal.close();
                var debugHtml = terms_build_debug_details_html( data.debug || null );

                if ( data.success )
                {
                  var successDialog = $.alert({
                    title: 'Sukces',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Status frazy zmieniony.' ) + debugHtml,
                    type: 'green'
                  });
                  setTimeout( function() { successDialog.close(); }, 5000 );
                  load_phrase_tables();
                }
                else
                {
                  $.alert({
                    title: 'Blad',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Nie udalo sie zmienic statusu.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
                    type: 'red'
                  });
                }
              },
              error: function()
              {
                modal.close();
                $.alert({ title: 'Blad', columnClass: 'col-md-4 col-md-offset-4', content: 'Blad komunikacji z serwerem.', type: 'red' });
              }
            });

            return false;
          }
        },
        cancel: { text: 'Anuluj' }
      }
    });
  });

  $( 'body' ).on( 'click', '#terms_add_keyword_btn', function()
  {
    var campaign_id = $( '#terms_campaign_id' ).val();
    if ( !campaign_id )
    {
      $.alert({ title: 'Uwaga', columnClass: 'col-md-4 col-md-offset-4', content: 'Wybierz kampanie przed dodaniem frazy.', type: 'orange' });
      return;
    }

    var ad_group_options = '';
    $( '#terms_ad_group_id option' ).each( function()
    {
      var val = $( this ).val();
      if ( val )
        ad_group_options += '<option value="' + val + '">' + $('<span>').text( $( this ).text() ).html() + '</option>';
    });

    if ( !ad_group_options )
    {
      $.alert({ title: 'Uwaga', columnClass: 'col-md-4 col-md-offset-4', content: 'Brak grup reklam. Wybierz kampanie z grupami.', type: 'orange' });
      return;
    }

    var selected_ad_group = $( '#terms_ad_group_id' ).val() || '';

    $.confirm({
      title: 'Dodaj fraze do grupy reklam',
      columnClass: 'col-md-4 col-md-offset-4',
      content:
        '<div class="form-group" style="margin-bottom:10px;">' +
          '<label for="add_kw_text" style="display:block;margin-bottom:6px;">Fraza</label>' +
          '<input id="add_kw_text" type="text" class="form-control" placeholder="Wpisz fraze..." />' +
        '</div>' +
        '<div class="form-group" style="margin-bottom:10px;">' +
          '<label for="add_kw_match_type" style="display:block;margin-bottom:6px;">Typ dopasowania</label>' +
          '<select id="add_kw_match_type" class="form-control">' +
            '<option value="BROAD" selected>Dopasowanie przyblizone</option>' +
            '<option value="PHRASE">Dopasowanie do wyrazenia</option>' +
            '<option value="EXACT">Dopasowanie scisle</option>' +
          '</select>' +
        '</div>' +
        '<div class="form-group" style="margin-bottom:0;">' +
          '<label for="add_kw_ad_group" style="display:block;margin-bottom:6px;">Grupa reklam</label>' +
          '<select id="add_kw_ad_group" class="form-control">' + ad_group_options + '</select>' +
        '</div>',
      type: 'blue',
      onContentReady: function()
      {
        if ( selected_ad_group )
          this.$content.find( '#add_kw_ad_group' ).val( selected_ad_group );
      },
      buttons: {
        confirm: {
          text: 'Dodaj',
          btnClass: 'btn-blue',
          action: function()
          {
            var keyword_text = $.trim( this.$content.find( '#add_kw_text' ).val() || '' );
            var match_type = this.$content.find( '#add_kw_match_type' ).val() || 'BROAD';
            var ad_group_id = this.$content.find( '#add_kw_ad_group' ).val() || '';
            var modal = this;

            if ( keyword_text === '' )
            {
              $.alert({ title: 'Uwaga', columnClass: 'col-md-4 col-md-offset-4', content: 'Wpisz fraze do dodania.', type: 'orange' });
              return false;
            }

            if ( !ad_group_id )
            {
              $.alert({ title: 'Uwaga', columnClass: 'col-md-4 col-md-offset-4', content: 'Wybierz grupe reklam.', type: 'orange' });
              return false;
            }

            modal.showLoading( true );

            $.ajax({
              url: '/campaign_terms/add_keyword/',
              type: 'POST',
              data: {
                campaign_id: campaign_id,
                ad_group_id: ad_group_id,
                keyword_text: keyword_text,
                match_type: match_type
              },
              success: function( response )
              {
                var data = JSON.parse( response );
                modal.close();

                if ( data.success )
                {
                  var debugHtml = terms_build_debug_details_html( data.debug || null );
                  var successDialog = $.alert({
                    title: 'Sukces',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Fraza zostala dodana.' )
                      + '<br><small style="display:block;margin-top:8px;color:#64748B;">Zmiana moze byc widoczna w panelu Google Ads po 1-3 minutach.</small>'
                      + debugHtml,
                    type: 'green'
                  });
                  setTimeout( function() { successDialog.close(); }, 10000 );
                  load_phrase_tables();
                }
                else
                {
                  var debugHtml = terms_build_debug_details_html( data.debug || null );
                  $.alert({
                    title: 'Blad',
                    columnClass: 'col-md-4 col-md-offset-4',
                    content: ( data.message || 'Nie udalo sie dodac frazy.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
                    type: 'red'
                  });
                }
              },
              error: function()
              {
                modal.close();
                $.alert({ title: 'Blad', columnClass: 'col-md-4 col-md-offset-4', content: 'Blad komunikacji z serwerem.', type: 'red' });
              }
            });

            return false;
          }
        },
        cancel: { text: 'Anuluj' }
      }
    });
  });

  terms_restore_ad_groups_collapsed();
  reset_all_tables();

  var saved_client_id = terms_storage_get( TERMS_STORAGE_CLIENT );
  var saved_campaign_id = terms_storage_get( TERMS_STORAGE_CAMPAIGN );

  if ( saved_client_id && $( '#terms_client_id option[value="' + saved_client_id + '"]' ).length )
  {
    $( '#terms_client_id' ).val( saved_client_id );
    load_campaigns_for_client( saved_campaign_id );
  }
});
</script>
