import datetime as dt
import json
from multiprocessing import Process

import uvicorn
from apscheduler.schedulers.blocking import BlockingScheduler
from fastapi import FastAPI
from py_jftech import prev_workday, filter_weekend, autowired

import main
from api import DatumType, PortfoliosRisk, Datum

app = FastAPI()

REC_GID = 'E3886FBA-123B-7890-123E-123456BEEED'


def get_today_rec():
    from portfolios.dao import robo_mpt_portfolios as rmp
    from api import PortfoliosType, PortfoliosRisk
    day = prev_workday(filter_weekend(dt.date.today()))
    portfolio = rmp.get_one(day, PortfoliosType.NORMAL, PortfoliosRisk.FT3)
    return portfolio


def get_last_signal():
    from rebalance.dao import robo_rebalance_signal as rrs

    day = prev_workday(filter_weekend(dt.date.today()))
    last_re = rrs.get_last_one(max_date=day, risk=PortfoliosRisk.FT3, effective=True)
    return last_re


@autowired
def get_fund_infos(datum: Datum = None):
    return datum.get_datums(DatumType.FUND)


@app.get("/recommend")
async def root():
    portfolio = get_today_rec()
    if portfolio:
        fund_infos = get_fund_infos()
        id_ticker_map = {str(info['id']): info for info in fund_infos}
        funds = json.loads(portfolio['portfolio'])
        rec_list = []
        portfolios = {'recomm_guid': REC_GID}
        data = {'recomm_guid': REC_GID}
        data['data_date'] = portfolio['date'].strftime('%Y-%m-%d')
        data['funds'] = [{'weight': round(weight * 100), 'fund_id': id_ticker_map[key]['ftTicker']} for key, weight in
                         funds.items()]
        data['creat_date'] = portfolio['create_time'].strftime('%Y-%m-%d %H:%M:%S')
        # todo 补全
        # returns = round(datas.pct_change(), 5)
        # data['cp'] = sharpe_ratio(returns, risk_free=0, period='daily', annualization=None),
        data['rr'] = 0.81
        data['roi'] = 0.81
        data['risk'] = round(sum([id_ticker_map[key]['risk'] * weight for key, weight in funds.items()]), 2)
        note = {}
        sig = get_last_signal()
        note['last_reg_reb'] = sig['date'].strftime('%Y-%m-%d')
        data['note'] = json.dumps(note)
        portfolios['data'] = data
        rec_list.append(portfolios)
        return rec_list
    else:
        return {'msg': '当日投组未产生,待10:00后获取'}


def start_robo():
    # 异常情况可以重启跑当天投组
    current_time = dt.datetime.now()
    target_time = dt.time(10, 0)
    if current_time.time() > target_time:
        main.start()

    # 开启定时任务,执行实盘
    scheduler = BlockingScheduler()
    scheduler.add_job(main.start, 'cron', day_of_week='0-4', hour=10, minute=00)
    scheduler.start()


def start_web():
    uvicorn.run("robo_controller:app", reload=True, port=8080)


if __name__ == "__main__":
    # 开启一个进程执行start_robo()
    p1 = Process(target=start_robo)
    p1.start()

    # 启动进程2
    p2 = Process(target=start_web)
    p2.start()