# coding=utf-8
from __future__ import absolute_import, unicode_literals
from django.conf import settings
from rpc.decorators import bind_context
from rpc.tool.error_code import gen
from rpc.tool.error_code import CODES
from api.tool.user_tool import get_user_from_context
from api.models import User
from api.models import BuDanSettlement
from pay.models import Statement, StatementRefusedRecord
from pay.models import (
    ApplyOp, AuditOp, CheckOp, RefuseOp, SettleOp, CreateOp, NameDefaultOp,
    BankDefaultOp, FinResetOp,
)
from pay.tool import is_my_statement
from pay.tool.time_tool import DatetimeTool
from gm_types.trade import STATEMENT_OPERATION_TYPE, STATEMENT_STATUS


def _operate(operator, statement_id, operation_type):
    try:
        statement = Statement.objects.get(pk=statement_id)
    except Statement.DoesNotExist:
        raise gen(CODES.STATEMENT_NOT_EXIST)
    op_list = (
        CreateOp, ApplyOp, AuditOp, CheckOp, RefuseOp, SettleOp, NameDefaultOp,
        BankDefaultOp, FinResetOp,
    )
    opFactory = None
    for modelOp in op_list:
        if modelOp.optype == operation_type:
            opFactory = modelOp
            break
    op = opFactory(statement=statement, operator=operator)
    op.do()


@bind_context('trade/statement/apply')
def trade_statement_apply(ctx, statement_id):
    user = User.objects.get(pk=settings.BOSS)
    _operate(
        operator=user.person,
        statement_id=statement_id,
        operation_type=STATEMENT_OPERATION_TYPE.APPLY
    )


@bind_context('trade/statement/audit', login_required=True)
def trade_statement_audit(ctx, statement_id):
    user = get_user_from_context(ctx)
    _operate(
        operator=user.person,
        statement_id=statement_id,
        operation_type=STATEMENT_OPERATION_TYPE.AUDIT
    )


@bind_context('trade/statement/check', login_required=True)
def trade_statement_check(ctx, statement_id):
    user = get_user_from_context(ctx)
    is_my_statement(user, statement_id)
    _operate(
        operator=user.person,
        statement_id=statement_id,
        operation_type=STATEMENT_OPERATION_TYPE.CHECK
    )


@bind_context('trade/statement/refuse', login_required=True)
def trade_statement_refuse(ctx, statement_id, reason):
    user = get_user_from_context(ctx)
    statement = is_my_statement(user, statement_id)
    from django.db import transaction
    with transaction.atomic():
        _operate(
            operator=user.person,
            statement_id=statement_id,
            operation_type=STATEMENT_OPERATION_TYPE.REFUSE
        )
        StatementRefusedRecord.objects.create(statement=statement, reason=reason[:140])


@bind_context('trade/statement/settle', login_required=True)
def trade_statement_settle(ctx, statement_id):
    user = get_user_from_context(ctx)
    _operate(
        operator=user.person,
        statement_id=statement_id,
        operation_type=STATEMENT_OPERATION_TYPE.SETTLE
    )
    Statement.objects.get(id=statement_id)


@bind_context('trade/statement/bank_defeat', login_required=True)
def trade_statement_bank_default(ctx, statement_id):
    user = get_user_from_context(ctx)
    _operate(
        operator=user.person,
        statement_id=statement_id,
        operation_type=STATEMENT_OPERATION_TYPE.BANK_DEFEAT
    )


@bind_context('trade/statement/name_defeat', login_required=True)
def trade_statement_name_default(ctx, statement_id):
    user = get_user_from_context(ctx)
    _operate(
        operator=user.person,
        statement_id=statement_id,
        operation_type=STATEMENT_OPERATION_TYPE.NAME_DEFEAT
    )


@bind_context('trade/statement/fin_reset', login_required=True)
def trade_statement_fin_reset(ctx, statement_id):
    user = get_user_from_context(ctx)
    _operate(
        operator=user.person,
        statement_id=statement_id,
        operation_type=STATEMENT_OPERATION_TYPE.FIN_RESET
    )


@bind_context('trade/statement/one_key_audit')
def statement_one_key_audit(ctx):
    user = get_user_from_context(ctx)
    dt = DatetimeTool()
    last_month = dt.get_first_day_month(d_months=-1).strftime("%Y%m")
    statements = Statement.history_objects.filter(statement_date=last_month, status=STATEMENT_STATUS.APPLIED)
    for statement in statements:
        AuditOp(statement, operator=user.person).do()
