-- ADCAMPAIGN-142: дата активации тикета

USE hahn;

$parse_path = DateTime::Parse("%Y-%m-%d");

$week_from_mls = ($mls) -> {
  $date = DateTime::FromMilliseconds($mls);
  $year = DateTime::GetYear($date);
  $week = DateTime::GetWeekOfYear($date);
  RETURN CAST($year * 100 + $week AS Uint32);
};

$week_from_table_name = ($table_name) -> {
  $date = $parse_path($table_name);
  $year = DateTime::GetYear($date);
  $week = DateTime::GetWeekOfYear($date);
  RETURN CAST($year * 100 + $week AS Uint32);
};

$has_recomendation = ($components) -> {
  RETURN ListAny(ListMap($components, ($x)->{ RETURN $x ILIKE "%!_Рекомендации" ESCAPE '!' }));
};

$OPTIMIZATIONS = ListCollect(AsList(
  "Оптимизация без расширения",
  "Оптимизация РМП",
  "Оптимизация с расширением",
  "Проработка элементов объявления",
  "Тексты",
));

$has_optimization = ($components) -> {
  RETURN ListAny(
    ListMap(
      $components,
      ($x)->{RETURN ListHas($OPTIMIZATIONS, $x)}
      )
    );
};

$parse_group_ids = ($gr) -> {
  RETURN ListMap($gr, ($x) -> {RETURN Unwrap(Cast($x AS Int64))}) ?? ListCreate(Int64);
};


INSERT INTO @ticket WITH TRUNCATE
SELECT 
  Unwrap(key) AS key
, Unwrap(type) AS type
, Unwrap(client_id) AS client_id
, Unwrap(resolved_mls) AS resolved_mls
, tracked_date_mls AS tracked_date_mls
, Unwrap(time_spent_total_h) AS time_spent_total_h
, Unwrap(components) AS components
, ListMap(Unwrap(new_campaign_ids), ($x) -> {RETURN Unwrap($x)}) AS new_campaign_ids
, $parse_group_ids(new_group_ids) AS new_group_ids
, $has_recomendation(components) AS has_recomendation
, $has_optimization(components) AS has_optimization
, ListLength(Unwrap(new_group_ids)) > 0 AS has_new_group
, ListLength(Unwrap(new_campaign_ids)) > 0 AS has_new_campaign
, ListHas(components, "8_week_OK") AS is_good_age
FROM {{input1}}
-- FROM `//home/vipplanners/insights/data/startrek/tables/issues`
WHERE status = "closed"
  AND resolution = "fixed"
  AND client_id > 1  -- 1 иногда используется в семантике никакого client_id
  AND type IN ("income", "newFeature")
  AND resolved_mls > 0
; COMMIT;

$client_wl = (
SELECT DISTINCT client_id FROM @ticket
);

$campaign_wl = (
SELECT DISTINCT campaign_id
FROM @ticket
FLATTEN BY new_campaign_ids AS campaign_id
WHERE has_new_campaign
);

$group_wl = (
SELECT DISTINCT group_id
FROM @ticket
FLATTEN BY new_group_ids AS group_id
WHERE has_new_group
);

$client_costvec = (
SELECT
  client_id
, TOP_BY(
    AsStruct(
      Unwrap(cube_week) AS cube_week,
      cost AS cost
  )
  , cube_week
  , 144
  ) AS cost_vec
FROM (
  SELECT
    client_id
  , cube_week
  , Cast(SUM(cost) AS Uint32) ?? 0u AS cost
  FROM RANGE(`//home/comdep-cubes/direct/production/hypercubes/clients`, `2019`)
  GROUP BY
    client_id
  , $week_from_table_name(cube_date) AS cube_week
)
GROUP BY client_id
);

$cid_start_date = (
SELECT
  cid
, DateTime::ToMilliseconds(DateTime::MakeDatetime($parse_path(MIN(cube_date)))) AS shows_start_date_mls
FROM RANGE(`//home/comdep-cubes/direct/production/hypercubes/campaigns`, `2019`)
WHERE shows > 0
  AND client_id IN COMPACT $client_wl
  AND cid IN COMPACT $campaign_wl
GROUP BY cid
);

$key_start_by_cid = (
SELECT
  key
, MIN(s.shows_start_date_mls) AS shows_start_date_mls
FROM @ticket AS t
FLATTEN LIST BY new_campaign_ids AS cid
JOIN $cid_start_date AS s
  ON t.cid = s.cid
WHERE has_new_campaign
GROUP BY t.key AS key
);

$pid_start_date = (
SELECT
  pid
, DateTime::ToMilliseconds(DateTime::MakeDatetime($parse_path(MIN(TableName())))) AS shows_start_date_mls
FROM RANGE(`//home/comdep-cubes/direct/production/cube`, `2019`)
WHERE shows > 0
  AND client_id IN COMPACT $client_wl
  AND cid IN COMPACT $campaign_wl
  AND pid IN COMPACT $group_wl
GROUP BY pid
);

$key_start_by_pid = (
SELECT
  key
, MIN(s.shows_start_date_mls) AS shows_start_date_mls
FROM @ticket AS t
FLATTEN LIST BY new_group_ids AS pid
JOIN $pid_start_date AS s
  ON t.pid = s.pid
WHERE has_new_group
GROUP BY t.key AS key
);

$calc_activation = ($start_st) -> {
  $start = AsDict(
    ("new_campaign", $start_st.new_campaign),
    ("new_group", $start_st.new_group),
    ("optimization", $start_st.optimization),
    ("recomendation", $start_st.recomendation),
  );
  $filtered_start = ListFilter(DictItems($start), ($kv) -> {RETURN $kv.1 > 0});
  $min_kv = ListSortAsc($filtered_start, ($kv) -> {RETURN $kv.1})[0];
  RETURN $min_kv;
};

$date_from_mls = DateTime::Format("%Y-%m-%d");

INSERT INTO @offers_1 WITH TRUNCATE
SELECT
  key
, type
, client_id
, time_spent_total_h
, components
, new_campaign_ids
, new_group_ids
, resolved_mls
, resolved_week
, new_campaign_start_mls
, new_group_start_mls
, optimization_start_mls
, recomendation_start_mls
, has_recomendation
, has_optimization
, has_new_campaign
, has_new_group
, is_good_age
, activation.0 AS activation_type
, activation.1 AS task_activation_mls
, $date_from_mls(DateTime::FromMilliseconds(activation.1)) AS task_activation_date
, $week_from_mls(activation.1) AS task_activation_week
FROM (
  SELECT
    key
  , type
  , client_id
  , time_spent_total_h
  , components
  , new_campaign_ids
  , new_group_ids
  , resolved_mls
  , Unwrap(resolved_week) AS resolved_week
  , new_campaign_start_mls
  , new_group_start_mls
  , optimization_start_mls
  , recomendation_start_mls
  , has_recomendation
  , has_optimization
  , has_new_campaign
  , has_new_group
  , is_good_age
  , $calc_activation(
      AsStruct(
        new_campaign_start_mls AS new_campaign,
        new_group_start_mls AS new_group,
        optimization_start_mls AS optimization,
        recomendation_start_mls AS recomendation
    )) AS activation
  FROM (
    SELECT
      t.key AS key
    , t.type AS type
    , t.client_id AS client_id
    , t.time_spent_total_h AS time_spent_total_h
    , t.components AS components
    , t.new_campaign_ids AS new_campaign_ids
    , t.new_group_ids AS new_group_ids
    , t.resolved_mls AS resolved_mls
    , $week_from_mls(t.resolved_mls) AS resolved_week
    , c.shows_start_date_mls AS new_campaign_start_mls
    , p.shows_start_date_mls AS new_group_start_mls
    , IF(t.has_optimization AND tracked_date_mls > 0, tracked_date_mls, Nothing(ParseType("Uint64?"))) AS optimization_start_mls
    , IF(t.has_recomendation AND tracked_date_mls > 0,tracked_date_mls, Nothing(ParseType("Uint64?"))) AS recomendation_start_mls
    , t.has_recomendation AS has_recomendation
    , t.has_optimization AS has_optimization
    , t.has_new_group AS has_new_group
    , t.has_new_campaign AS has_new_campaign
    , t.is_good_age AS is_good_age
    FROM @ticket AS t
    LEFT JOIN $key_start_by_cid AS c
      ON t.key = c.key
    LEFT JOIN $key_start_by_pid AS p
      ON t.key = p.key
  )
)
; COMMIT;

$make_filter = ($date) -> {
  RETURN ($x) -> {RETURN $x.cube_week > $date};
};

$analyze_cost_vec = ($cost_vec, $week, $size) -> {
  $MIN_COST = 1000;
  -- порядок по возрасту от cube_week, от меньшего к большему
  $history_vec = ListTake(
    ListExtract(ListSkipWhile($cost_vec, $make_filter($week)), "cost"),
    $size) ?? AsList(0u);
  $history_vec = IF(ListLength($history_vec) > 0, $history_vec, AsList(0u));
  $active_weeks = ListLength(
       -- первый элемент должен быть всегда — это затраты на неделе активации
       ListFilter(ListSkip($history_vec, 1), ($x) -> {RETURN $x > $MIN_COST})
  );
  $is_new = NOT ($active_weeks > 0);
  $is_good_history = $active_weeks > 5;

  RETURN AsStruct(
    $history_vec AS history_vec,
    $active_weeks AS active_weeks,
    $is_new AS is_new,
    $is_good_history AS is_good_history
  );
};

INSERT INTO @offers WITH TRUNCATE
SELECT
  key
, type
, client_id
, time_spent_total_h
, components
, new_campaign_ids
, new_group_ids
, resolved_mls
, resolved_week
, new_campaign_start_mls
, new_group_start_mls
, optimization_start_mls
, recomendation_start_mls
, has_recomendation
, has_optimization
, has_new_campaign
, has_new_group
, is_good_age
, activation_type
, task_activation_mls
, task_activation_date
, task_activation_week
, cost_vec.history_vec AS history_vec
, cost_vec.active_weeks AS active_weeks
, cost_vec.is_new AS is_new_client
, cost_vec.is_good_history AS is_good_history
FROM (
  SELECT
    key
  , type
  , o.client_id AS client_id
  , time_spent_total_h
  , components
  , new_campaign_ids
  , new_group_ids
  , resolved_mls
  , resolved_week
  , new_campaign_start_mls
  , new_group_start_mls
  , optimization_start_mls
  , recomendation_start_mls
  , has_recomendation
  , has_optimization
  , has_new_campaign
  , has_new_group
  , is_good_age
  , activation_type
  , task_activation_mls
  , task_activation_date
  , task_activation_week
  , $analyze_cost_vec(v.cost_vec, task_activation_week, 13) AS cost_vec
  FROM @offers_1 AS o
  LEFT JOIN $client_costvec AS v
    ON o.client_id = v.client_id
)
; COMMIT;

INSERT INTO {{input2}} WITH TRUNCATE
-- INSERT INTO `//home/vipplanners/insights/data/startrek/tables/offers` WITH TRUNCATE
SELECT *
FROM @offers
WHERE
  -- Если дата активации была раньше даты резолюции,
  --   то это ок, даже для больших интервалов. Такое возможно при 
  --   раздельной оптимизации и запуске переданных черновиков,
  -- Но если дата активации сильно далеко отстоит от даты резолюции, то мы 
  --   к себе атрибутировать такое, малол ли что еще клиент за это время сделал.
  -- 30 дней выбрали экспертно.
  (DateTime::FromMilliseconds(task_activation_mls) - 
     DateTime::FromMilliseconds(resolved_mls)
  ) < Interval("P60D")
ORDER BY key
;

INSERT INTO `//home/vipplanners/insights/data/startrek/tables/offers.tocheck` WITH TRUNCATE
SELECT *
FROM @offers
WHERE (task_activation_mls IS NULL) OR (NOT is_good_history)
ORDER BY key
;
