from datetime import date
from pathlib import Path

from fastapi.testclient import TestClient

from app.main import create_app
from app.service import DashboardService, resolve_period


class FakeRepository:
    def latest_date(self):
        return "2026-05-31"

    def available_dates(self):
        return ["2026-05-29", "2026-05-30", "2026-05-31"]

    def store_summary(self, start_date, end_date):
        return [
            {
                "source_platform": "taobao_tmall",
                "store_name": "良渚文化旗舰店",
                "visitor_count": 100,
                "page_view_count": 300,
                "payment_amount": 1200,
                "refund_amount": 100,
                "net_payment_amount": 1100,
                "payment_buyer_count": 10,
                "payment_item_count": 12,
            },
            {
                "source_platform": "jd",
                "store_name": "良渚京东店",
                "visitor_count": 50,
                "page_view_count": 120,
                "payment_amount": 600,
                "refund_amount": 0,
                "net_payment_amount": 600,
                "payment_buyer_count": 4,
                "payment_item_count": 4,
            },
        ]

    def trend(self, start_date, end_date):
        return [
            {"stat_date": "2026-05-30", "visitor_count": 80, "net_payment_amount": 900},
            {"stat_date": "2026-05-31", "visitor_count": 150, "net_payment_amount": 1700},
        ]

    def product_rank(self, start_date, end_date, limit=20):
        return [
            {"store_name": "良渚文化旗舰店", "product_name": "玉鸟咕咕", "net_payment_amount": 500, "payment_item_count": 5, "product_visitor_count": 30}
        ]

    def traffic_rank(self, start_date, end_date, limit=20):
        return [
            {"store_name": "良渚文化旗舰店", "source_name": "搜索", "visitor_count": 70, "payment_amount": 800}
        ]


def test_resolve_period_supports_day_week_month():
    assert resolve_period("day", date(2026, 5, 31)) == (date(2026, 5, 31), date(2026, 5, 31), "2026-05-31")
    assert resolve_period("week", date(2026, 5, 31)) == (date(2026, 5, 25), date(2026, 5, 31), "2026-05-25 至 2026-05-31")
    assert resolve_period("month", date(2026, 5, 31)) == (date(2026, 5, 1), date(2026, 5, 31), "2026-05")


def test_dashboard_api_returns_visualization_payload():
    app = create_app(service=DashboardService(FakeRepository()))
    client = TestClient(app)

    resp = client.get("/api/dashboard?grain=week&date=2026-05-31")

    assert resp.status_code == 200
    data = resp.json()
    assert data["grain"] == "week"
    assert data["period"]["start"] == "2026-05-25"
    assert data["kpis"]["net_payment_amount"] == 1700
    assert data["kpis"]["visitor_count"] == 150
    assert data["sections"]["stores"][0]["store_name"] == "良渚文化旗舰店"
    assert data["sections"]["products"][0]["product_name"] == "玉鸟咕咕"
    assert data["sections"]["traffic"][0]["source_name"] == "搜索"
    assert data["charts"]["trend"][1]["stat_date"] == "2026-05-31"


def test_meta_api_exposes_available_dates_and_dimensions():
    app = create_app(service=DashboardService(FakeRepository()))
    client = TestClient(app)
    data = client.get("/api/meta").json()
    assert data["latest_date"] == "2026-05-31"
    assert data["available_dates"][-1] == "2026-05-31"
    assert data["grains"] == ["day", "week", "month"]


def test_frontend_contains_date_picker_and_grain_tabs():
    html = Path(__file__).resolve().parents[1].joinpath("static", "index.html").read_text(encoding="utf-8")
    assert 'type="date"' in html
    assert 'data-grain="day"' in html
    assert 'data-grain="week"' in html
    assert 'data-grain="month"' in html
    assert 'id="trendChart"' in html
