# -*- coding: utf-8 -*-

"""
Скрипт, запускающий процесс обработки данных.

"""
import logging
import json
from datetime import datetime, timedelta
from pymongo import MongoClient, UpdateOne
from pprint import pprint
import sys
sys.path.append(".")
from stocks3.share.curl import second_load_url_data
from libs import xmltodict
from stocks3.core.common import get_field


url = "http://cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
post_template = """<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <GetReutersCursOnDate xmlns="http://web.cbr.ru/">
      <On_date>{}</On_date>
    </GetReutersCursOnDate>
  </soap12:Body>
</soap12:Envelope>"""

headers = (('Content-Type', 'application/soap+xml; charset=utf-8'),)

quote_map = {
    "8": 10050,
    "12": 10051,
    "32": 10052,
    "44": 10053,
    "48": 10054,
    "50": 10055,
    "52": 10056,
    "60": 10057,
    "64": 10058,
    "68": 10059,
    "72": 10060,
    "84": 10061,
    "90": 10062,
    "96": 10063,
    "108": 10064,
    "116": 10065,
    "132": 10066,
    "144": 10067,
    "152": 10068,
    "170": 10069,
    "174": 10070,
    "188": 10071,
    "191": 10072,
    "192": 10073,
    "214": 10074,
    "222": 10075,
    "230": 10076,
    "232": 10077,
    "238": 10078,
    "242": 10079,
    "262": 10080,
    "270": 10081,
    "292": 10082,
    "320": 10083,
    "324": 10084,
    "328": 10085,
    "332": 10086,
    "340": 10087,
    "344": 10088,
    "352": 10089,
    "360": 10090,
    "364": 10091,
    "368": 10092,
    "376": 10093,
    "388": 10094,
    "400": 10095,
    "404": 10096,
    "408": 10097,
    "414": 10098,
    "418": 10099,
    "422": 10100,
    "430": 10101,
    "434": 10102,
    "446": 10103,
    "454": 10104,
    "458": 10105,
    "462": 10106,
    "478": 10107,
    "480": 10108,
    "484": 10109,
    "496": 10110,
    "504": 10111,
    "512": 10112,
    "516": 10113,
    "524": 10114,
    "533": 10115,
    "548": 10116,
    "554": 10117,
    "558": 10118,
    "566": 10119,
    "586": 10120,
    "590": 10121,
    "598": 10122,
    "600": 10123,
    "604": 10124,
    "608": 10125,
    "634": 10126,
    "646": 10127,
    "654": 10128,
    "678": 10129,
    "682": 10130,
    "690": 10131,
    "694": 10132,
    "704": 10133,
    "706": 10134,
    "748": 10135,
    "760": 10136,
    "764": 10137,
    "776": 10138,
    "780": 10139,
    "784": 10140,
    "788": 10141,
    "800": 10142,
    "807": 10143,
    "818": 10144,
    "834": 10145,
    "858": 10146,
    "886": 10147,
    "901": 10148,
    "928": 10149,
    "929": 10150,
    "930": 10151,
    "936": 10152,
    "937": 10153,
    "938": 10154,
    "941": 10155,
    "943": 10156,
    "950": 10157,
    "951": 10158,
    "952": 10159,
    "967": 10160,
    "968": 10161,
    "969": 10162,
    "971": 10163,
    "973": 10164,
    "976": 10165,
    "977": 10166,
    "981": 10167,
}


class Database:
    def __init__(self, connectionstring):
        self.client = MongoClient(connectionstring, readPreference='secondary')
        self.stocks = self.client.stocksdb.stocks


class FakeSource:
    weight = 50


def make_database_write(saver, query, on_date):
    if len(query) > 0:
        try:
            res = saver.stocks.bulk_write(query)
            print("date:", on_date.strftime("%Y-%m-%d"), "modified_count:", res.modified_count, "upserted_count:", res.upserted_count)
        except Exception as e:
            print("date:", on_date.strftime("%Y-%m-%d"), "insert error:", e)
    else:
        print("date:", on_date.strftime("%Y-%m-%d"), "skip inserts")


def process(source, saver, logger):
    counter = 0
    query = []

    # date_from = datetime.strptime("2017-03-01", "%Y-%m-%d")
    date_from = datetime.today()
    date_to = datetime.strptime("2021-09-20", "%Y-%m-%d")

    on_date = date_from
    while on_date > date_to:
        date_str = on_date.strftime("%Y-%m-%d")
        post = post_template.format(date_str)
        data = second_load_url_data(url, additional_headers=headers, post_data=post)
        data = xmltodict.parse(data)

        quotes_array = get_field(data,
                                 'soap:Envelope.soap:Body.GetReutersCursOnDateResponse.GetReutersCursOnDateResult.'
                                 'diffgr:diffgram.ReutersValutesData.Currency',
                                 safe=True,
                                 default=[])
        for quote in quotes_array:
            print(quote['num_code'], quote_map[quote['num_code']], date_str, float(quote['val']), quote['dir'])
            stock_value = {
                '$set': {
                    'unixtime':int(on_date.timestamp()),
                    'time': '00:00:00',
                    'value': float(quote['val']),
                    'lastupdate': datetime.now(),
                },
                '$setOnInsert': {
                    'id': quote_map[quote['num_code']],
                    'source': source.weight,
                    'region': 0,
                    'date': date_str,
                },
            }
            find_conditions = {
                'id': quote_map[quote['num_code']],
                'region': 0,
                'date': date_str,
            }
            if quote['num_code'] in quote_map:
                query.append(UpdateOne(find_conditions, stock_value, upsert=True))
            else:
                print("warn:", quote['num_code'], "not found")

        counter += 1
        if counter % 100 == 0:
            make_database_write(saver, query, on_date)
            query = []

        on_date -= timedelta(days=1)
    make_database_write(saver, query, on_date)


def main():
    with open("config/config.json") as c:
        config = json.load(c)
        database = config["db"]["connectionstring"]
    logging.basicConfig(level=logging.WARNING)
    logger = logging.getLogger('IMPORT')
    saver = Database(database)
    source = FakeSource()
    process(source, saver, logger)


if __name__ == "__main__":
    main()

