package ru.yandex.webmaster3.worker.feeds.statistics;

import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import ru.yandex.webmaster3.core.worker.task.PeriodicTaskState;
import ru.yandex.webmaster3.core.worker.task.PeriodicTaskType;
import ru.yandex.webmaster3.core.worker.task.TaskResult;
import ru.yandex.webmaster3.storage.feeds.statistics.DomainOffersStatisticsYDao;
import ru.yandex.webmaster3.storage.host.CommonDataType;
import ru.yandex.webmaster3.storage.settings.SettingsService;
import ru.yandex.webmaster3.storage.settings.data.AbstractCommonDataState;
import ru.yandex.webmaster3.storage.util.ydb.YdbYqlService;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.worker.PeriodicTask;
import ru.yandex.webmaster3.worker.TaskSchedule;

/**
 * Created by Oleg Bazdyrev on 20/01/2022.
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class ImportFeedsOffersStatisticsTask extends PeriodicTask<PeriodicTaskState> {

    private final DomainOffersStatisticsYDao domainOffersStatisticsYDao;
    private final SettingsService settingsService;
    @Value("${webmaster3.worker.feeds.offer_base_full.path}")
    private final YtPath offerBaseTable;
    @Value("${external.yt.service.hahn}://home/webmaster/prod/export/feeds/native_feeds")
    private final YtPath feedsExportTable;
    private final YdbYqlService ydbYqlService;

    private static final String PREFIX_QUERY = """
            USE ${CLUSTER};
            $offerBaseWithWmcDomains = (
                SELECT nf.domain as domain,
                    nf.type as type,
                    obf.offer_id as offer_id,
                    ListMap(nvl(Yson::ConvertToList(`sets`), ListCreate(String)), ($s) -> { return Yson::ConvertToString($s.url);}) as set_urls
                FROM ${SOURCE_TABLE} as obf
                INNER JOIN ${FEEDS_EXPORT_TABLE} as nf
                ON obf.feed_url == nf.url
            );

            $offerStats = (
                SELECT domain, type, count(*) as offers
                FROM $offerBaseWithWmcDomains
                GROUP BY domain, type
            );

            $setStats = (
                SELECT domain, type, count(*) as sets FROM
                (
                    SELECT domain, type, set_url
                    FROM $offerBaseWithWmcDomains
                    FLATTEN LIST BY set_urls as set_url
                    GROUP BY domain, type, set_url
                )
                GROUP BY domain, type
            );
            """;

    public static final String DATA_SELECT_QUERY = """
            SELECT
                Date('${DATE}') as `date`,
                cast(o.domain as Utf8) as `domain`,
                cast(o.type as Utf8) as `type`,
                cast(o.offers as Int64) as `offers`,
                cast(s.sets as Int64) as `sets`
            FROM $offerStats as o
            full JOIN $setStats as s
            USING (domain, type)
            """;

    @Override
    public Result run(UUID runId) throws Exception {
        LocalDate today = LocalDate.now();
        LocalDate lastImport = Optional.ofNullable(settingsService.getSettingUncached(CommonDataType.LAST_FEEDS_OFFERS_STATISTICS_IMPORT))
                .map(AbstractCommonDataState::getValue).map(LocalDate::parse).orElse(today.minusDays(1));
        if (today.isAfter(lastImport)) {
            StrSubstitutor substitutor = new StrSubstitutor(Map.of(
                    "DATE", today.toString(),
                    "SOURCE_TABLE", offerBaseTable.toYqlPath(),
                    "FEEDS_EXPORT_TABLE", feedsExportTable.toYqlPath(),
                    "CLUSTER", offerBaseTable.getCluster()
            ));
            ydbYqlService.importToYdb(
                    domainOffersStatisticsYDao.getTablePath(),
                    substitutor.replace(DATA_SELECT_QUERY),
                    substitutor.replace(PREFIX_QUERY)
            );
            settingsService.update(CommonDataType.LAST_FEEDS_OFFERS_STATISTICS_IMPORT, today.toString());
        } else {
            log.info("Import already occurred today");
        }
        return new Result(TaskResult.SUCCESS);
    }

    @Override
    public PeriodicTaskType getType() {
        return PeriodicTaskType.IMPORT_FEEDS_OFFERS_STATISTICS;
    }

    @Override
    public TaskSchedule getSchedule() {
        return TaskSchedule.startByCron("0 17 */4 * * *");
    }
}
