<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm https://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
  version="2.0">

  <!-- @formatter:off -->

  <!-- HQL queries -->

  <named-query name="AppleMusicChartTrackEntity.findChartTrackAtDateOrChartDateDimensionTrack">
    <query>
      <![CDATA[
        select e
        from AppleMusicChartTrackEntity e
          join AppleMusicTrackEntity t on t.appleMusicTrackId = e.appleMusicTrackId
          join AppleMusicMarketRankEntity mr on mr.appleMusicCountryId = e.appleMusicCountryId
        where (
            ((:trackIds) is not NULL and e.appleMusicTrackId in (:trackIds))
            or
            ((:isrcs) is not NULL and t.isrc in (:isrcs))
          )
          and (:minPosition is NULL or e.currentPosition >= :minPosition)
          and (:maxPosition is NULL or e.currentPosition <= :maxPosition)
          and (:minRank is NULL or mr.rank >= :minRank)
          and (:maxRank is NULL or mr.rank <= :maxRank)
          and ((:countryCode) is NULL or e.appleMusicCountryId in (:countryCode))

          and (
            (cast(:chartDate as date) is not NULL and e.id.chartDate = :chartDate)
            or
            (cast(:chartDate as date) is NULL and (e.chartDateKey) in (:chartDateKeys))
          )
      ]]>
    </query>
  </named-query>

  <named-query name="AppleMusicChartTrackEntity.findChartTrackAtDateOrChartDateDimensionIsrc">
    <query>
      <![CDATA[
        select e
        from AppleMusicChartTrackEntity e
          join AppleMusicMarketRankEntity mr on mr.appleMusicCountryId = e.appleMusicCountryId
        where (
            ((:trackIds) is not NULL and e.appleMusicTrackId in (:trackIds))
            or
            ((:isrcs) is not NULL and e.isrc in (:isrcs))
          )
          and (:minPosition is NULL or e.currentPosition >= :minPosition)
          and (:maxPosition is NULL or e.currentPosition <= :maxPosition)
          and (:minRank is NULL or mr.rank >= :minRank)
          and (:maxRank is NULL or mr.rank <= :maxRank)
          and ((:countryCode) is NULL or e.appleMusicCountryId in (:countryCode))

          and (
            (cast(:chartDate as date) is not NULL and e.id.chartDate = :chartDate)
            or
            (cast(:chartDate as date) is NULL and (e.chartDateKey) in (:chartDateKeys))
          )
      ]]>
    </query>
  </named-query>

  <named-query name="SpotifyChartTrackEntity.findChartTrackAtDateOrChartDateDimensionTrack">
    <query>
      <![CDATA[
        select e
        from SpotifyChartTrackEntity e
          join SpotifyTrackEntity t on t.id.spotifyTrackId = e.spotifyTrackId and t.id.spotifyCountryId = e.spotifyCountryId
          join SpotifyChartEntity c on c.spotifyChartId = e.spotifyChartId
          join SpotifyMarketRankEntity mr on mr.spotifyCountryId = c.spotifyCountryId
        where (
            ((:trackIds) is not NULL and e.spotifyTrackId in (:trackIds))
            or
            ((:isrcs) is not NULL and t.isrc in (:isrcs))
          )
          and (:minPosition is NULL or e.currentPosition >= :minPosition)
          and (:maxPosition is NULL or e.currentPosition <= :maxPosition)
          and (:minRank is NULL or mr.rank >= :minRank)
          and (:maxRank is NULL or mr.rank <= :maxRank)
          and ((:countryCode) is NULL or c.spotifyCountryId in (:countryCode))
          and ((:chartBreakdowns) is NULL or c.breakdown in (:chartBreakdowns))
          and ((:chartTypes) is NULL or c.type in (:chartTypes))

          and (
            (cast(:chartDate as date) is not NULL and e.id.chartDate = :chartDate)
            or
            (cast(:chartDate as date) is NULL and (e.chartDateKey) in (:chartDateKeys))
          )
      ]]>
    </query>
  </named-query>

  <named-query name="SpotifyChartTrackEntity.findChartTrackAtDateOrChartDateDimensionIsrc">
    <query>
      <![CDATA[
        select e
        from SpotifyChartTrackEntity e
          join SpotifyChartEntity c on c.spotifyChartId = e.spotifyChartId
          join SpotifyMarketRankEntity mr on mr.spotifyCountryId = c.spotifyCountryId
        where (
            ((:trackIds) is not NULL and e.spotifyTrackId in (:trackIds))
            or
            ((:isrcs) is not NULL and e.isrc in (:isrcs))
          )
          and (:minPosition is NULL or e.currentPosition >= :minPosition)
          and (:maxPosition is NULL or e.currentPosition <= :maxPosition)
          and (:minRank is NULL or mr.rank >= :minRank)
          and (:maxRank is NULL or mr.rank <= :maxRank)
          and ((:countryCode) is NULL or c.spotifyCountryId in (:countryCode))
          and ((:chartBreakdowns) is NULL or c.breakdown in (:chartBreakdowns))
          and ((:chartTypes) is NULL or c.type in (:chartTypes))

          and (
            (cast(:chartDate as date) is not NULL and e.id.chartDate = :chartDate)
            or
            (cast(:chartDate as date) is NULL and (e.chartDateKey) in (:chartDateKeys))
          )
      ]]>
    </query>
  </named-query>


  <!-- Native queries -->

  <named-native-query name="AppleMusicCharts.findLastChartDates">
    <query>
      select apple_music_chart_id, max_date as chart_date from apple.fact_max_chart_date
    </query>
  </named-native-query>

  <named-native-query name="SpotifyCharts.findLastChartDates">
    <query>
      select spotify_chart_id, max_date as chart_date from spotify.fact_max_chart_date
    </query>
  </named-native-query>

  <named-native-query name="AdsStatusDailyEntity.getStatusSummary">
    <query>
      with valid_until_data as (
        select dsp, parent_rep_owner, account_id, max(date) as date
        from data_health.ads_status_daily
        where (dsp in (:dsps) or :dsps isnull)
        group by dsp, parent_rep_owner, account_id),
           min_max_data as (
             select dsp, parent_rep_owner, account_id, min(date) as min_date, max(date) as max_date
             from data_health.ads_status_daily
             where status in (
               SELECT UNNEST(cast(string_to_array(:statuses, ',') as data_health.data_health_status[]))
             ) and campaign_id is null
             group by dsp, parent_rep_owner, account_id),
           all_data as (
             select dsp, parent_rep_owner, account_id
             from data_health.ads_status_daily
             where (dsp in (:dsps) or :dsps isnull)
               and ((account_id in (:accounts)) or :accounts isnull or account_id is null)
               and (parent_rep_owner in (:parenRepOwners) or :parenRepOwners isnull or parent_rep_owner is null)
             group by dsp, parent_rep_owner, account_id)
      select ad.dsp, ad.parent_rep_owner, ad.account_id, mm.min_date, mm.max_date, vu.date as valid_until
      from all_data ad
             left join min_max_data mm on
          ad.dsp = mm.dsp and ((ad.parent_rep_owner = mm.parent_rep_owner) or (ad.parent_rep_owner is null and
                                                                               mm.parent_rep_owner is null))
          and ((ad.account_id = mm.account_id) or (ad.account_id is null and mm.account_id is null))
             left join valid_until_data vu on
          ad.dsp = vu.dsp and ((ad.parent_rep_owner = vu.parent_rep_owner) or (ad.parent_rep_owner is null and
                                                                               vu.parent_rep_owner is null))
          and ((ad.account_id = vu.account_id) or (ad.account_id is null and vu.account_id is null))
    </query>
  </named-native-query>

  <named-native-query name="SpotifyChartsStatusDailyEntity.getStatusSummary">
    <query>
      with valid_until_data as (
        select breakdown, chart_type, market, max(date) as date
        from data_health.spotify_charts_status_daily
        where (breakdown in (:breakdowns) or :breakdowns is NULL)
        group by breakdown, chart_type, market
      ),
      min_max_data as (
        select breakdown, chart_type, market, min(date) as min_date, max(date) as max_date
        from data_health.spotify_charts_status_daily
        where status in (
          SELECT UNNEST(cast(string_to_array(:statuses, ',') as data_health.data_health_status[]))
        )
        group by breakdown, chart_type, market
      ),
      all_data as (
        select breakdown, chart_type, market
        from data_health.spotify_charts_status_daily
        where (breakdown in (:breakdowns) or :breakdowns is NULL)
        and (chart_type in (:chartTypes) or :chartTypes is NULL or chart_type is NULL)
        and (market in (:countryCodes) or :countryCodes is NULL or market is NULL)

        group by breakdown, chart_type, market
      )

      select ad.breakdown, ad.chart_type, ad.market as country_code, mm.min_date, mm.max_date, vu.date as valid_until
      from all_data ad
      left join min_max_data mm on ad.breakdown = mm.breakdown and ((ad.chart_type = mm.chart_type) or (ad.chart_type is NULL and mm.chart_type is NULL))
      and ((ad.market = mm.market) or (ad.market is NULL and mm.market is NULL))

      left join valid_until_data vu on ad.breakdown = vu.breakdown and ((ad.chart_type = vu.chart_type) or (ad.chart_type is NULL and vu.chart_type is NULL))
      and ((ad.market = vu.market) or (ad.market is NULL and vu.market is NULL))
    </query>
  </named-native-query>

  <named-native-query name="AppleMusicChartsStatusDailyEntity.getStatusSummary">
    <query>
      with valid_until_data as (
        select chart_type, market, max(date) as date, max(source_table_updated_at) as date_time, max(last_updated_time) as last_updated_time
        from data_health.apple_charts_status_daily
        group by chart_type, market
      ),
      min_max_data as (
        select chart_type, market, min(date) as min_date, max(date) as max_date, min(source_table_updated_at) as min_time,
          max(source_table_updated_at) as max_time
        from data_health.apple_charts_status_daily
        where status in (
          SELECT UNNEST(cast(string_to_array(:statuses, ',') as data_health.data_health_status[]))
        )
        group by chart_type, market
      ),
      all_data as (
        select chart_type, market
        from data_health.apple_charts_status_daily
        where TRUE
        and (market in (:countryCodes) or :countryCodes is NULL or market is NULL)

        group by chart_type, market
      )

      select ad.chart_type, ad.market as country_code, mm.min_date, mm.max_date, vu.date as valid_until, mm.min_time as min_date_time,
        mm.max_time as max_date_time, vu.date_time as valid_until_time, vu.last_updated_time as last_update_date_time
      from all_data ad
      left join min_max_data mm on ((ad.chart_type = mm.chart_type) or (ad.chart_type is NULL and mm.chart_type is NULL))
      and ((ad.market = mm.market) or (ad.market is NULL and mm.market is NULL))

      left join valid_until_data vu on ((ad.chart_type = vu.chart_type) or (ad.chart_type is NULL and vu.chart_type is NULL))
      and ((ad.market = vu.market) or (ad.market is NULL and vu.market is NULL))
    </query>
  </named-native-query>

  <named-native-query name="DspDataStatusDailyEntity.getStatusSummary">
    <query>
      select daily.dsp,
             daily.segment               as dsp_segment,
             min(daily_with_status.date) as min_date,
             max(daily_with_status.date) as max_date,
             max(daily.date)             as valid_until
      from data_health.dsp_status_daily daily
             left join data_health.dsp_status_daily daily_with_status
                       on daily.dsp = daily_with_status.dsp and daily.segment = daily_with_status.segment
                         and daily_with_status.status in
                             (SELECT UNNEST(cast(string_to_array(:statuses, ',') as data_health.data_health_status[])))
      where :dsps isnull
         or daily.dsp in (:dsps)
      group by daily.dsp, daily.segment
    </query>
  </named-native-query>

  <named-native-query name="SpotifyTrackEntity.findTracksWithSameIsrcByTrackIdStrings">
    <query>
      select distinct related_track.spotify_track_id
      from spotify.dim_spotify_track input_track
             inner join spotify.dim_spotify_track related_track
                        on related_track.isrc = input_track.isrc
      where input_track.spotify_track_id in :trackIds
    </query>
  </named-native-query>

  <named-native-query name="AppleMusicTrackEntity.findTracksWithSameIsrcByTrackIdStrings">
    <query>
      select distinct related_track.apple_music_track_id
      from apple.dim_apple_music_track input_track
             inner join apple.dim_apple_music_track related_track
                        on related_track.isrc = input_track.isrc
      where input_track.apple_music_track_id in :trackIds
    </query>
  </named-native-query>

  <named-native-query name="TrackEntity.findIsrcsWithRelated">
    <query>
      select input_isrc_track.isrc                  as isrc,
             array_agg(distinct related_track.isrc) as related_isrcs
      from track input_isrc_track
             inner join track related_track on related_track.prod_fam_no = input_isrc_track.prod_fam_no
      where input_isrc_track.config_cat_key = 'D'
        and input_isrc_track.isrc in (:isrcs)
      group by input_isrc_track.isrc
    </query>
  </named-native-query>
  <named-native-query name="TikTokTopSongEntity.getTikTokTopSongEntityByIsrc"
    result-set-mapping="TikTokTopSongEntityMapping">
    <query>
      SELECT *
      FROM (
        SELECT  isrc,
                tiktok_song_id,
                product_code,
                song_title,
                label_name,
                artist,
                sublabel,
                rank() OVER (PARTITION BY isrc
                ORDER BY tiktok_song_id
        ) AS platform_song_id_rank
        FROM tiktok.dim_tiktok_top_song
        where isrc in (:isrcs)
      ) p
      where p.platform_song_id_rank = 1
    </query>
  </named-native-query>

  <named-native-query name="SpotifyStreamsNewListenersEntity.findDistinctTopIsrcsWithTrackInfo">
    <query>
      with isrc_min_position as (
        select report_date, country_code, period, track_isrc, min(position) as min_pos
        from spotify.streams_new_listeners
        where report_date = :reportDate
          and country_code = :countryCode
          and period = :periodDays
          and track_isrc is not null
        group by report_date, country_code, period, track_isrc
        order by min_pos asc
        limit :limit
      )

      select
        snl.track_isrc,
        snl.track_id,
        snl.track_name,
        snl.total_discovered,
        snl.most_discoveries_source,
        isrc_min_position.min_pos as position
      from isrc_min_position
      inner join spotify.streams_new_listeners snl on
        snl.report_date = isrc_min_position.report_date
        and snl.country_code = isrc_min_position.country_code
        and snl.period = isrc_min_position.period
        and snl.position = isrc_min_position.min_pos
        and snl.track_isrc = isrc_min_position.track_isrc
    </query>
  </named-native-query>


  <named-native-query name="PlaylistEntity.getChartmetricToAmazonPlaylistIdMapping">
    <query>
      select cm_amazon_playlist_id, amazon_playlist_id
      from amazon.cm_amazon_playlist_id_mapping
      where cm_amazon_playlist_id in (:cmAmazonPlaylistIds)
    </query>
  </named-native-query>

  <named-native-query name="PlaylistEntity.getPlaylistCountries">
    <query>
      select playlist_id, country_code
      from public.playlist
      where playlist_id in (:playlistIds)
    </query>
  </named-native-query>

  <named-native-query name="AmazonChartsStatusDailyEntity.getStatusSummary">
    <query>
      with valid_until_data as (
        select chart_type, country_code, max(date) as date, max(source_table_updated_at) as date_time
        from data_health.amazon_charts_status_daily
        group by chart_type, country_code
      ),
      min_max_data as (
      select chart_type, country_code, min(date) as min_date, max(date) as max_date, min(source_table_updated_at) as min_time,
        max(source_table_updated_at) as max_time
        from data_health.amazon_charts_status_daily
        where status in (
          SELECT UNNEST(cast(string_to_array(:statuses, ',') as data_health.data_health_status[]))
        )
        group by chart_type, country_code
      ),
      all_data as (
        select chart_type, country_code
        from data_health.amazon_charts_status_daily
        where TRUE
        and (country_code in (:countryCodes) or :countryCodes is NULL or country_code is NULL)

        group by chart_type, country_code
      )

      select ad.chart_type, ad.country_code, mm.min_date, mm.max_date, vu.date as valid_until, mm.min_time as min_date_time,
      mm.max_time as max_date_time, vu.date_time as valid_until_time
      from all_data ad
      left join min_max_data mm on ((ad.chart_type = mm.chart_type) or (ad.chart_type is NULL and mm.chart_type is NULL))
      and ((ad.country_code = mm.country_code) or (ad.country_code is NULL and mm.country_code is NULL))

      left join valid_until_data vu on ((ad.chart_type = vu.chart_type) or (ad.chart_type is NULL and vu.chart_type is NULL))
      and ((ad.country_code = vu.country_code) or (ad.country_code is NULL and vu.country_code is NULL))
    </query>
  </named-native-query>

  <named-native-query name="SpotifyPlaylistTrackLifetimePublicEntity.findByRelatedIsrcsExcludeCurrentPositions">
    <query>
      with current_positions as (
        select ptlt.playlist_id
        from spotify.fact_public_spotify_playlist_track_lifetime ptlt
        left join spotify.fact_public_playlist_lifetime plt
        on ptlt.playlist_id=plt.playlist_id
        where ptlt.isrc in (:relatedIsrcs)
        and (
          plt.playlist_updated_at_date_time is NULL
          or (ptlt.latest_date_time + interval '1 minutes') >= plt.playlist_updated_at_date_time
        )
      )
      select
        'spotify' as dsp,
        lf.isrc,
        lf.playlist_id,
        sp.country_code as country_code,
        lf.earliest_position,
        lf.earliest_date_time,
        lf.latest_date_time
      from spotify.fact_public_spotify_playlist_track_lifetime lf
             left join spotify.dim_playlist sp on sp.playlist_id=lf.playlist_id
      where (cast(cast(:minLatestDate as text) as date) is NULL or date(lf.latest_date_time) >= cast(cast(:minLatestDate as text) as date))
      and lf.isrc in (:relatedIsrcs)
      and (lf.playlist_id in (:playlistIds) or :playlistIds is NULL)
      and lf.playlist_id not in (select playlist_id from current_positions)
      and (coalesce(:countryCode) is null or sp.country_code in (:countryCode))
    </query>
  </named-native-query>

  <named-native-query name="AppleMusicPlaylistTrackLifetimePublicEntity.findByRelatedIsrcsExcludeCurrentPositions">
    <query>
      with current_positions as (
        select ptlt.playlist_id, ptlt.country_code
        from apple.fact_public_apple_playlist_track_lifetime ptlt
        left join apple.fact_public_playlist_lifetime plt
        on ptlt.playlist_id=plt.playlist_id and ptlt.country_code=plt.country_code
        where ptlt.isrc in (:relatedIsrcs)
        and (
          plt.playlist_updated_at_date_time is NULL
          or (ptlt.latest_date_time + interval '1 minutes') >= plt.playlist_updated_at_date_time
        )
      )

      select
        'apple' as dsp,
        isrc,
        playlist_id,
        country_code,
        earliest_position,
        earliest_date_time,
        latest_date_time
      from apple.fact_public_apple_playlist_track_lifetime
      where (cast(cast(:minLatestDate as text) as date) is NULL or date(latest_date_time) >= cast(cast(:minLatestDate as text) as date))
      and isrc in (:relatedIsrcs)
      and (playlist_id in (:playlistIds) or :playlistIds is NULL)
      and (country_code in (:countryCode) or :countryCode is NULL)
      and (playlist_id, country_code) not in (select playlist_id, country_code from current_positions)
    </query>
  </named-native-query>

  <named-native-query name="FactTikTokTopVideoLifetimeEntity.findTikTokVideos">
    <query>
      select fact_tiktok_top_video_lifetime.video_id as video_id,
             v.posted_date                           as video_posted_date,
             v.username                              as video_username,

             views_growth_7_days                     as view_growth_7_days,
             views_growth_28_days                    as view_growth_28_days,
             views_growth_7_days_percent             as view_growth_7_days_percent,
             views_growth_28_days_percent            as view_growth_28_days_percent,
             views                                   as views,
             likes                                   as likes,
             comments                                as comments,
             row_number() over (order by
               case when :sort_by = 'views' then views end desc
               , case when :sort_by = 'views_growth_7_days' then views_growth_7_days end desc
               , case when :sort_by = 'views_growth_28_days' then views_growth_28_days end desc
               , v.video_id
               ) - 1                               as position

      from tiktok.fact_tiktok_top_video_lifetime
             left outer join tiktok.dim_tiktok_video v on v.video_id = fact_tiktok_top_video_lifetime.video_id
      where fact_tiktok_top_video_lifetime.video_id in (:video_ids)

      order by position
    </query>
  </named-native-query>

  <sql-result-set-mapping name="TikTokTopSongEntityMapping">
    <entity-result entity-class="io.delphiplatform.api.v3.rdb.entity.tiktok.TikTokTopSongEntity">
      <field-result name="id.isrc" column="isrc"/>
      <field-result name="id.songId" column="tiktok_song_id"/>
      <field-result name="isrc" column="isrc"/>
      <field-result name="songId" column="tiktok_song_id"/>
      <field-result name="artist" column="artist"/>
      <field-result name="labelName" column="label_name"/>
      <field-result name="productCode" column="product_code"/>
      <field-result name="sublabel" column="sublabel"/>
      <field-result name="songTitle" column="song_title"/>
    </entity-result>
  </sql-result-set-mapping>

  <!-- @formatter:on -->

</entity-mappings>
