from collections import OrderedDict
from typing import Dict, Iterable, List, Optional, Tuple

from panoramic.cli.husky.core.taxonomy.enums import AggregationType
from panoramic.cli.husky.core.taxonomy.exceptions import TaxonsNotFound
from panoramic.cli.husky.core.taxonomy.getters import get_taxon_tel_metadata
from panoramic.cli.husky.core.taxonomy.models import Taxon
from panoramic.cli.husky.service.utils.taxon_slug_expression import (
    TaxonExpressionStr,
    TaxonMap,
    TaxonSlugExpression,
)
from tests.panoramic.cli.husky.test.mocks.husky_model import MOCK_DATA_SOURCE_NAME

taxon_mocks = [
    Taxon.create(
        slug='enhanced_cpm',
        display_name='Enhanced Spend for link clicks objective',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='1000 * enhanced_spend / generic_impressions',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='enhanced_spend',
        display_name='Enhanced Spend for link clicks objective',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='iff(objective == "LINK_CLICKS",generic_spend*1.5,generic_spend)',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='ad_id',
        display_name='Ad Id',
        taxon_description='Id of an Ad',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym='Ad Id',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='adgroup_id',
        display_name='Adgroup Id',
        taxon_description='Id of an Adgroup',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym='Adgroup Id',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='gender',
        display_name='Gender',
        taxon_description='Distribution of metrics by gender',
        taxon_group='Audience',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym='Gender',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='facebook_ads|gender',
        display_name='Gender',
        taxon_description='Distribution of metrics by gender',
        taxon_group='Audience',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        data_source='facebook_ads',
        display_state='visible',
        display_settings=None,
        acronym='Gender',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='twitter|gender',
        display_name='Gender',
        taxon_description='Distribution of metrics by gender',
        taxon_group='Audience',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        data_source='twitter',
        display_state='visible',
        display_settings=None,
        acronym='Gender',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='age_bucket',
        display_name='Age Bucket',
        taxon_description='Distribution of metrics by age',
        taxon_group='Audience',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym='Age',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='ad_name',
        display_name='Ad Name',
        taxon_description='Name of ad in platform',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='impressions',
        display_name='Impressions',
        taxon_description='impressions',
        taxon_group='Exposure',
        taxon_type='metric',
        validation_type='integer',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='impressions_numeric',
        display_name='Impressions_numeric',
        taxon_description='Impressions_numeric',
        taxon_group='Exposure',
        taxon_type='metric',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='spend',
        display_name='Marketing Spend',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym='Spend',
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='avg_spend',
        display_name='Average Marketing Spend',
        taxon_description='Average amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        aggregation={'type': 'avg'},
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym='Spend',
    ),
    Taxon.create(
        slug='views',
        display_name='Video Views',
        taxon_description='number of views',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='integer',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='link_clicks',
        display_name='Link Clicks',
        taxon_description='number of link clicks',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='integer',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='conversions',
        display_name='Conversions',
        taxon_description='number of Conversions',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='integer',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='conversion_rate',
        display_name='CVR',
        taxon_description='Conversion rate',
        taxon_group='Attribution',
        taxon_type='metric',
        calculation='conversions / link_clicks',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='account_id',
        display_name='Account ID',
        taxon_description='Account ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='company_id',
        display_name='Company ID',
        taxon_description='Company ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='project_id',
        display_name='Project ID',
        taxon_description='Project ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='raw_data',
        display_name='Account ID',
        taxon_description='Account ID',
        taxon_group='Exposure',
        taxon_type='metric',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='computed_simple',
        display_name='Simple computed taxon',
        taxon_description='Simple computed taxon',
        taxon_group='Exposure',
        taxon_type='metric',
        calculation='spend * impressions + 10',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='computed_division',
        display_name='Computed taxon with division',
        taxon_description='Computex taxon with division',
        taxon_group='Exposure',
        taxon_type='metric',
        calculation='spend/impressions * 20',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='computed_const',
        display_name='Computed taxon with constant',
        taxon_description='Computed taxon with constant',
        taxon_group='Exposure',
        taxon_type='metric',
        calculation='2',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='objective',
        display_name='Objective',
        taxon_description='Distribution of metrics by objective',
        taxon_group='Audience',
        taxon_type='dimension',
        validation_type='enum',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='cpm',
        display_name='CPM',
        taxon_description='CPM metric',
        taxon_group='Exposure',
        taxon_type='metric',
        calculation='1000 * spend / impressions',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='cpm_no_agg',
        display_name='CPM no aggregation defined',
        taxon_description='CPM metric no aggregation defined',
        taxon_group='Exposure',
        taxon_type='metric',
        calculation='1000 * spend / impressions',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='date',
        display_name='Date',
        taxon_description='date',
        taxon_group='Time',
        taxon_type='dimension',
        validation_type='datetime',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'group_by', 'params': None},
        acronym=None,
    ),
    Taxon.create(
        slug='week_of_year',
        display_name='Week of year',
        taxon_description='Time bucketed by week of the year',
        taxon_group='Time',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='date_hour',
        display_name='Hour',
        taxon_description='Time with hour precision.',
        taxon_group='Time',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='facebook_ads|spend',
        data_source='facebook_ads',
        display_name='Facebook Marketing Spend',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='facebook|ads_spend',
        data_source='facebook',
        display_name='Facebook Marketing Spend',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='adwords|spend',
        data_source='adwords',
        display_name='Adwords Marketing Spend',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='twitter|spend',
        data_source='twitter',
        display_name='Twitter Marketing Spend',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='facebook_ads|impressions',
        data_source='facebook_ads',
        display_name='Facebook Impressions',
        taxon_description='Impr',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='adwords|impressions',
        data_source='adwords',
        display_name='Adwords Impressions',
        taxon_description='Impr',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='twitter|impressions',
        data_source='twitter',
        display_name='Twitter Impressions',
        taxon_description='Impr',
        taxon_group='Billing',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='generic_spend',
        display_name='Generic Marketing Spend',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='?facebook_ads|spend + ?adwords|spend + ?twitter|spend',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='generic_impressions',
        display_name='Generic Impressions',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='?facebook_ads|impressions + ?adwords|impressions + ?twitter|impressions',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='generic_spend2',
        display_name='Generic Marketing Spend 2',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='generic_spend',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='generic_cpm',
        display_name='Generic Marketing Spend 2',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='1000 * generic_spend / generic_impressions',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='generic_cpm_at_least_value_10',
        display_name='Generic CPM',
        taxon_description='formula is: iff(generic_cpm>10, generic_cpm, 10)',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='iff(generic_cpm>10, generic_cpm, 10)',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_spend_all_required',
        display_name='fb_tw_spend_all_required',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='facebook_ads|spend + twitter|spend',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_adwords_spend_all_required',
        display_name='fb_adwords_spend_all_required',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='facebook_ads|spend + adwords|spend',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_spend_all_optional',
        display_name='fb_tw_spend_all_optional',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='?facebook_ads|spend + ?twitter|spend',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_adwords_spend_all_required',
        display_name='fb_tw_adwords_spend_all_required',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='facebook_ads|spend + twitter|spend + adwords|spend',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_adwords_spend_all_optional',
        display_name='fb_tw_adwords_spend_all_optional',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='?facebook_ads|spend + ?twitter|spend + ?adwords|spend',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_adwords_impressions_all_optional',
        display_name='fb_tw_adwords_impressions_all_optional',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='?facebook_ads|impressions + ?twitter|impressions + ?adwords|impressions',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='facebook_ads|ad_id',
        display_name='facebook_ads|ad_id',
        data_source='facebook_ads',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='fb_ad_id',
        display_name='fb_ad_id',
        data_source='facebook_ads',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='facebook_ads|ad_id',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='facebook_ads|ad_name',
        display_name='facebook_ads|ad_name',
        data_source='facebook_ads',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='twitter|ad_id',
        display_name='twitter|ad_id',
        data_source='twitter',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='tw_ad_id',
        display_name='tw_ad_id',
        data_source='twitter',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='twitter|ad_id',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='twitter|ad_name',
        display_name='twitter|ad_name',
        data_source='twitter',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='fb_tw_merged_ad_id',
        display_name='fb_tw_merged_ad_id',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='merge(?facebook_ads|ad_id, ?twitter|ad_id)',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='simple_concat_dimension',
        display_name='simple_concat_dimension',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='concat("a", ad_id)',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        data_source='twitter',
        slug='twitter|objective',
        display_name='twitter|objective',
        taxon_description='Distribution of metrics by objective',
        taxon_group='Audience',
        taxon_type='dimension',
        validation_type='enum',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        data_source='facebook_ads',
        slug='facebook_ads|objective',
        display_name='facebook_ads|objective',
        taxon_description='Distribution of metrics by objective',
        taxon_group='Audience',
        taxon_type='dimension',
        validation_type='enum',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': AggregationType.group_by.value},
    ),
    Taxon.create(
        slug='fb_tw_merged_objective',
        display_name='fb_tw_merged_objective',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='merge(?facebook_ads|objective, ?twitter|objective)',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_merged_objective_concat_xxx',
        display_name='fb_tw_merged_objective_concat_xxx',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='concat(merge(?facebook_ads|objective, ?twitter|objective),"_xxx")',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_merged_objective_concat_xxx',
        display_name='fb_tw_merged_objective',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='concat(fb_tw_merged_objective,"xxx")',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_merged_objective_override_unknowns',
        display_name='fb_tw_merged_objective_override',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='override(fb_tw_merged_objective,"om-slug")',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='fb_tw_merged_objective_override_no_unknowns',
        display_name='fb_tw_merged_objective_override_no_unknowns',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='dimension',
        calculation='override(fb_tw_merged_objective,"om-slug", false)',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='sumiff_spend_with_merged_objective',
        display_name='sumiff_spend_with_merged_objective',
        taxon_description='',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='iff(fb_tw_merged_objective == "LINK_CLICKS",generic_spend*1.5,generic_spend)',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='data_source',
        display_name='Data Source',
        taxon_description='Name of data source',
        taxon_group='INTERNAL',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym='Data source',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='facebook_ads|date',
        display_name='Date',
        data_source='facebook_ads',
        taxon_description='date',
        taxon_group='Time',
        taxon_type='dimension',
        validation_type='datetime',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='facebook_ads|done',
        display_name='Done',
        data_source='facebook_ads',
        taxon_description='done',
        taxon_group='Time',
        taxon_type='dimension',
        validation_type='boolean',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug=f'{MOCK_DATA_SOURCE_NAME}|dimension',
        display_name='Dimension',
        data_source=MOCK_DATA_SOURCE_NAME,
        taxon_description='dimension',
        taxon_group='INTERNAL',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug=f'{MOCK_DATA_SOURCE_NAME}|metric',
        display_name='Metric',
        data_source=MOCK_DATA_SOURCE_NAME,
        taxon_description='metric',
        taxon_group='INTERNAL',
        taxon_type='metric',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='twitter|date',
        display_name='Date',
        data_source='twitter',
        taxon_description='date',
        taxon_group='Time',
        taxon_type='dimension',
        validation_type='datetime',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='merged_date',
        display_name='Date',
        data_source='twitter',
        taxon_description='date',
        taxon_group='Time',
        taxon_type='dimension',
        calculation='merge(?facebook_ads|date,?twitter|date)',
        validation_type='datetime',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='pinterest|total_conversions_value',
        display_name='Total Conversions Value',
        data_source='pinterest',
        taxon_description='Total Conversions Value',
        taxon_group='Namespaced',
        taxon_type='metric',
        calculation='pinterest|total_conversions_value_in_micro_dollar_microdollars * 1000000',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='pinterest|total_conversions_value_in_micro_dollar_microdollars',
        display_name='Total Conversions Value In Micro Dollar Microdollars',
        data_source='pinterest',
        taxon_description='Total Conversions Value In Micro Dollar Microdollars',
        taxon_group='Namespaced',
        taxon_type='metric',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'sum', 'params': None},
    ),
    Taxon.create(
        slug='city',
        display_name='City',
        data_source=None,
        taxon_description='The city in which a user views or interacts with your ad. ',
        taxon_group='Location',
        taxon_type='dimension',
        calculation='merge(?bing|city)',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='bing|city',
        display_name='City',
        data_source='bing',
        taxon_description='The city in which a user views or interacts with your ad. ',
        taxon_group='Namespaced',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='campaign_id2',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        calculation='merge(?facebook_ads|campaign_id, ?doubleclick_campaign|campaign_id_varchar, '
        '?pinterest|campaign_id, ?adwords|campaign_id, ?doubleclick_bid|campaign_id, '
        '?the_trade_desk|campaign_id, ?linkedin|campaign_group_id, ?twitter|campaign_id, '
        '?snapchat|campaign_id, ?appnexus|line_item_id, ?verizon_dsp|order_id, ?bing|campaign_id)',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='facebook_ads|campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='facebook_ads',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='doubleclick_campaign|campaign_id_varchar',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='doubleclick_campaign',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='pinterest|campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='pinterest',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='adwords|campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='adwords',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='doubleclick_bid|campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='doubleclick_bid',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='the_trade_desk|campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='the_trade_desk',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='linkedin|campaign_group_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='linkedin',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='twitter|campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='twitter',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='snapchat|campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='snapchat',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='appnexus|line_item_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='appnexus',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='verizon_dsp|order_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='verizon_dsp',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='bing|campaign_id',
        display_name='Campaign ID',
        taxon_description='Campaign ID',
        taxon_group='Entity',
        taxon_type='dimension',
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        data_source='bing',
        aggregation={'type': 'group_by', 'params': None},
    ),
    Taxon.create(
        slug='spend_w_impr',
        display_name='Enhanced Spend for link clicks objective',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='spend + impressions',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='enhanced_cpm_2',
        display_name='Enhanced Cpm 2 for link clicks objective',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='enhanced_cpm',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='enhanced_cpm_no_agg',
        display_name='Enhanced Cpm 2 for link clicks objective',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='enhanced_cpm',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
    Taxon.create(
        slug='computed_metric_avg',
        display_name='Computed metric with avg taxons',
        taxon_description='Computed metric with avg taxons',
        taxon_group='Exposure',
        taxon_type='metric',
        calculation='1000 * avg_spend',
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
    ),
    Taxon.create(
        slug='simple_count_all',
        display_name='Simple count all taxon',
        taxon_description='Simple count all taxon',
        taxon_group='custom',
        taxon_type='dimension',
        calculation=None,
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': AggregationType.count_all.value, 'params': None},
    ),
    Taxon.create(
        slug='simple_min',
        display_name='Simple min taxon',
        taxon_description='Simple min taxon',
        taxon_group='custom',
        taxon_type='dimension',
        calculation=None,
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': AggregationType.min.value, 'params': None},
    ),
    Taxon.create(
        slug='simple_max',
        display_name='Simple max taxon',
        taxon_description='Simple max taxon',
        taxon_group='custom',
        taxon_type='dimension',
        calculation=None,
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': AggregationType.max.value, 'params': None},
    ),
    Taxon.create(
        slug='simple_count_distinct',
        display_name='Simple count distinct taxon',
        taxon_description='Simple count distinct taxon',
        taxon_group='custom',
        taxon_type='dimension',
        calculation=None,
        validation_type='numeric',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={'type': AggregationType.count_distinct.value, 'params': {'relevant_fields': []}},
    ),
    Taxon.create(
        slug='simple_first_by',
        display_name='Simple first_by taxon',
        taxon_description='Simple first_by taxon',
        taxon_group='custom',
        taxon_type='dimension',
        calculation=None,
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={
            'type': AggregationType.first_by.value,
            'params': {'sort_dimensions': [{'taxon': 'objective', 'order_by': 'asc'}]},
        },
    ),
    Taxon.create(
        slug='simple_last_by',
        display_name='Simple last by taxon',
        taxon_description='Simple last by taxon',
        taxon_group='custom',
        taxon_type='dimension',
        calculation=None,
        validation_type='text',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
        acronym=None,
        aggregation={
            'type': AggregationType.last_by.value,
            'params': {'sort_dimensions': [{'taxon': 'objective', 'order_by': 'asc'}]},
        },
    ),
    Taxon.create(
        slug='required_spend',
        display_name='Required Marketing Spend',
        taxon_description='Total amount of money invested into marketing',
        taxon_group='Billing',
        taxon_type='metric',
        calculation='facebook_ads|spend + adwords|spend + twitter|spend',
        validation_type='money',
        company_id='50',
        settings=None,
        display_state='visible',
        display_settings=None,
    ),
]


def _add_tel_metadata_to_taxons(taxon_map) -> TaxonMap:
    from panoramic.cli.husky.core.taxonomy.getters import Taxonomy

    Taxonomy.preload_taxons(taxon_mocks)

    for taxon in taxon_map.values():
        taxon.tel_metadata = get_taxon_tel_metadata(taxon)
    return taxon_map


TAXON_MAP: Dict[TaxonExpressionStr, Taxon] = {taxon.slug_expr: taxon for taxon in taxon_mocks}
_add_tel_metadata_to_taxons(TAXON_MAP)
"""
Not to be used directly, use mock_get_taxons_map()
"""


def mock_get_taxons_map(_company_id: Optional[int], _taxon_slugs: Iterable[str]) -> Dict[TaxonExpressionStr, Taxon]:
    """
    Fn that should be used to get mocked taxons.
    """
    taxon_map = {slug: TAXON_MAP[slug] for slug in _taxon_slugs if slug in TAXON_MAP}

    not_found_taxons = [slug for slug in _taxon_slugs if slug not in taxon_map]

    if len(not_found_taxons) > 0:
        raise TaxonsNotFound(taxon_slugs=not_found_taxons)

    return taxon_map


def get_specific_select_mocked_taxons(taxon_slugs: List[str]) -> Dict[TaxonSlugExpression, Taxon]:
    results = OrderedDict()

    for taxon_slug in taxon_slugs:
        taxon = mock_get_taxons_map(None, [taxon_slug])[taxon_slug]
        taxon_slug_expression = TaxonSlugExpression(taxon_slug)

        results[taxon_slug_expression] = taxon

    return results


def get_specific_projection_mocked_taxons(taxon_slugs: List[str]) -> List[Tuple[TaxonExpressionStr, Taxon]]:
    return [
        (TaxonExpressionStr(slug.slug), taxon) for slug, taxon in get_specific_select_mocked_taxons(taxon_slugs).items()
    ]


def get_mocked_taxons_by_slug(taxon_slugs: Iterable[str]) -> List[Taxon]:
    return [TAXON_MAP[slug] for slug in taxon_slugs]


def mock_get_taxons(
    company_ids: Optional[Iterable[str]] = None,
    taxon_slugs: Optional[Iterable[str]] = None,
    only_computed: Optional[bool] = None,
    data_sources: Optional[Iterable[Optional[str]]] = None,
    used_taxons: Optional[Iterable[str]] = None,
):
    """
    Mock counterpart to get_taxons()
    """

    def taxon_filter(taxon: Taxon):
        if taxon_slugs and taxon.slug not in taxon_slugs:
            return False
        if only_computed is True and taxon.is_computed_metric is False:
            return False

        if data_sources and taxon.data_source not in data_sources:
            return False
        if used_taxons and taxon.slug not in used_taxons:
            return False

        return True

    return [taxon for taxon in TAXON_MAP.values() if taxon_filter(taxon)]
