from collections import Counter, defaultdict

from . import states
from .app import get_error_topic, get_reporting_app, get_reporting_topic
from .web import env

app = get_reporting_app()

error_topic = get_error_topic(app)
reporting_topic = get_reporting_topic(app)

report_index = {}
report_by_category = defaultdict(lambda: defaultdict(dict))
unique_servers = set()
state_counts = Counter()

errors = defaultdict(lambda: defaultdict(list))

color_for_state = {
    states.OK: "#007BFF",
    states.FAIL: "#19A9D5",
    states.SLOW: "#8fc9fb",
    states.STALL: "#1909E5",
    states.UNASSIGNED: "#003f3c",
    states.REBALANCING: "#005f3c",
    states.PAUSED: "#003f3c",
}


@app.agent(reporting_topic)
async def process_report(reports):
    async for r in reports:
        report_by_category[r.app_id][r.category][r.hostname] = r.details
        previous = report_index.get(r.key)
        report_index[r.key] = r
        if previous is not None and previous.state != r.state:
            print(f"{r.key} changed {previous.state} -> {r.state}")
        unique_servers.add((r.app_id, r.hostname))
        state_counts[r.state] += 1


@app.agent(error_topic)
async def process_error(stream):
    async for error in stream:
        errors[error.app_id][error.hostname].append(error)


@app.page("/dashboard/")
async def dashboard(web, request, template_name="dashboard.html"):
    template = env.get_template(template_name)
    return web.html(
        template.render(
            {
                "total_workers": len(unique_servers),
                "report": report_by_category,
                "errors": errors,
                "state_counts": [
                    {
                        "name": state,
                        "count": count,
                        "color": color_for_state[state],
                    }
                    for state, count in state_counts.items()
                ],
            }
        )
    )


@app.page("/dashboard/api/")
async def dashboard_json(web, request):
    return web.json({"status": report_by_category})


if __name__ == "__main__":
    app.main()
