from datetime import datetime
import json
import os
from flask import Flask, request
from src.models.transaction_model import transaction_model
from src.errors.argument_exception import argument_exception
from src.export.exporter_factory import exporter_factory

from src.settings.settings_manager import settings_manager
from src.logic.start_factory import start_factory
from src.storage.storage import storage
from src.storage.storage_service import storage_service


setman = settings_manager()
start = None
strg = None

app = Flask(__name__)


@app.route("/api/export/<storage_key>/<format>", methods=["GET"])
def get_export_format(storage_key: str, format: str):
    global setman, start, strg

    try:
        exp = exporter_factory().create(format)
    except argument_exception as e:
        return "Wrong format: " + e.error.error_text, 400

    if storage_key not in strg.data:
        return "Key not found", 404

    return app.response_class(
        response=exp.export_by_key(storage_key),
        status=200,
        mimetype=exp.strategy.mimetype,
    )


@app.route("/api/export/<storage_key>", methods=["GET"])
def get_export(storage_key: str):
    global setman, start, strg
    format = setman.settings.export_format
    try:
        exp = exporter_factory().create(format)
    except argument_exception as e:
        return "Wrong format: " + e.error.error_text, 400

    if storage_key not in strg.data:
        return "Key not found", 404

    return app.response_class(
        response=exp.export_by_key(storage_key),
        status=200,
        mimetype=exp.strategy.mimetype,
    )


@app.route("/api/export/rests", methods=["GET"])
def get_rests():
    args = request.args
    if "start_period" not in args.keys() or "stop_period" not in args.keys():
        raise argument_exception("Нет дат!")

    start_date = datetime.strptime(args["start_period"], "%Y-%m-%d")
    stop_date = datetime.strptime(args["stop_period"], "%Y-%m-%d")

    service = storage_service(start.storage.data[storage.transaction_key()])
    result = service.create_turns_dt(strg, start_date, stop_date, strg)

    return storage_service.create_response(result, app)


@app.route("/api/storage/<nomenclature_name>/turns")
def get_nomens_rests(nomenclature_name):
    nomen = [
        nomen
        for nomen in start.storage.data[storage.nomenclature_key()]
        if nomen.name == nomenclature_name
    ]

    if len(nomen) == 0:
        return ""

    nomen = nomen[0]

    service = storage_service(start.storage.data[storage.transaction_key()])
    result = service.create_turns_nomen(strg, nomen)

    return storage_service.create_response(result, app)


@app.route("/api/storage/<recipe_name>/debits")
def debits_recipe(recipe_name):
    args = request.args
    if "storage" not in args:
        raise argument_exception("Не указан склад!")

    recipe = [
        recipe
        for recipe in start.storage.data[storage.recipe_key()]
        if recipe.name == recipe_name
    ]
    storage_ = [
        storage
        for storage in start.storage.data[storage.storage_key()]
        if storage.name == args["storage"]
    ]

    if len(recipe) == 0 or len(storage_) == 0:
        return ""

    recipe = recipe[0]
    storage_ = storage_[0]

    service = storage_service(start.storage.data[storage.transaction_key()])
    turns = service.create_turns(recipe, storage=storage_)

    service.take_recipe(recipe, turns, storage_, strg)

    return app.response_class(
        response=json.dumps({"success": True}),
        status=200,
        mimetype="application/json; charset=utf-8",
    )


# Инициализация приложения
def run():
    global setman, start, strg
    setman.open(os.path.dirname(__file__) + "/config/settings.json")
    strg = storage()
    start = start_factory(setman.settings, strg)
    start.create()
    start.create_transactions()
    app.run()


if __name__ == "__main__":
    run()