import json
from datetime import datetime as dt
from typing import List
from urllib.parse import urlencode

import pandas as pd
import requests
from py_jftech import component, filter_weekend, next_workday, get_config, format_date

from api import RoboReportor
from basic.sync import ths_token
from reports.dao import robo_benckmark as rb

config = get_config(__name__)


@component(bean_name='benckmark-report')
class BenchmarkAlligamReportor(RoboReportor):

    @property
    def report_name(self) -> str:
        return 'BENCHMARK_SPX'

    @property
    def module_name(self) -> str:
        return 'divrobo'

    @property
    def risk(self):
        return 'SPX'

    @property
    def base_params(self):
        return {
            'code': "SPX.GI",
        }


    def sync_benchmark(self, start_date=None):
        url = "https://quantapi.51ifind.com/api/v1/cmd_history_quotation"
        headers = {
            "Content-Type": "application/json",
            "access_token": ths_token(),
            "ifindlang": "cn"
        }
        params = {
            'codes': self.base_params['code'],
            'indicators': 'close',
            'startdate': format_date(start_date) if start_date else "2012-01-01",
            'enddate': format_date(dt.today())
        }
        response = requests.post(url, json=params, headers=headers)
        response = response.json()['tables']
        if len(response) == 0 or response[0].get('time') is None or len(response[0]['time']) == 0:
            return
        rb.batch_insert([{
            'date': time,
            'module': self.module_name,
            'risk': self.risk,
            'nav': close,
            'remarks': json.dumps({
                'av': close,
                'div': 0
            }, ensure_ascii=False)
        } for time,close in zip(response[0]['time'],response[0]['table']['close'])])

    def load_report(self, max_date=dt.today(), min_date=None) -> List[dict]:
        max_date = filter_weekend(max_date)
        min_date = filter_weekend(min_date) if min_date else None
        last = rb.get_last_one(module=self.module_name, risk=self.risk, max_date=max_date)
        if not last or last['date'] < max_date:
            self.sync_benchmark(start_date=next_workday(last['date']) if last else None)
        result = pd.DataFrame(rb.get_list(max_date=max_date, min_date=min_date))
        result['av'] = result['remarks'].apply(lambda x: json.loads(x)['av'])
        result['div'] = result['remarks'].apply(lambda x: json.loads(x)['div'])
        result['acc'] = result.apply(lambda row: result[result['date'] <= row['date']]['div'].sum() + row['av'], axis=1)
        result = result[['date', 'av', 'div', 'acc', 'nav']]
        result.rename(columns={'nav': f'{self.risk}_nav', 'av': f'{self.risk}_av', 'div': f'{self.risk}_div', 'acc': f'{self.risk}_acc'}, inplace=True)
        return result.to_dict('records')
