import uuid
from datetime import date

import pytest

from app.tests.conftest import TENANT_A, TENANT_B, tenant_headers


@pytest.mark.asyncio
async def test_health(client):
    resp = await client.get("/health")
    assert resp.status_code == 200
    assert resp.json()["service"] == "accounting-service"


@pytest.mark.asyncio
async def test_create_chart_of_accounts(client):
    resp = await client.post(
        "/api/v1/accounts/charts",
        json={"name": "Default COA", "code": "COA-001", "is_default": True},
        headers=tenant_headers(TENANT_A),
    )
    assert resp.status_code == 201
    data = resp.json()
    assert data["code"] == "COA-001"
    assert data["tenant_id"] == str(TENANT_A)


@pytest.mark.asyncio
async def test_tenant_isolation_accounts(client):
    chart_resp = await client.post(
        "/api/v1/accounts/charts",
        json={"name": "Tenant A COA", "code": "COA-A"},
        headers=tenant_headers(TENANT_A),
    )
    assert chart_resp.status_code == 201
    chart_id = chart_resp.json()["id"]

    acc_resp = await client.post(
        "/api/v1/accounts",
        json={
            "chart_id": chart_id,
            "code": "1000",
            "name": "Test Account",
            "account_type": "asset",
            "account_category": "current_asset",
        },
        headers=tenant_headers(TENANT_A),
    )
    assert acc_resp.status_code == 201
    account_id = acc_resp.json()["id"]

    resp_b_list = await client.get(
        "/api/v1/accounts",
        headers=tenant_headers(TENANT_B),
    )
    assert resp_b_list.status_code == 200
    assert len(resp_b_list.json()) == 0

    resp_b_get = await client.get(
        f"/api/v1/accounts/{account_id}",
        headers=tenant_headers(TENANT_B),
    )
    assert resp_b_get.status_code == 404


@pytest.mark.asyncio
async def test_posting_engine_balanced_voucher(client):
    year_resp = await client.post(
        "/api/v1/fiscal/years",
        json={"name": "1403", "start_date": "2024-03-20", "end_date": "2025-03-19", "is_current": True},
        headers=tenant_headers(TENANT_A),
    )
    assert year_resp.status_code == 201
    year_id = year_resp.json()["id"]

    period_resp = await client.post(
        "/api/v1/fiscal/periods",
        json={
            "fiscal_year_id": year_id,
            "name": "Month 1",
            "period_number": 1,
            "start_date": "2024-03-20",
            "end_date": "2024-04-19",
            "is_current": True,
        },
        headers=tenant_headers(TENANT_A),
    )
    assert period_resp.status_code == 201
    period_id = period_resp.json()["id"]

    chart_resp = await client.post(
        "/api/v1/accounts/charts",
        json={"name": "COA", "code": "COA-POST"},
        headers=tenant_headers(TENANT_A),
    )
    chart_id = chart_resp.json()["id"]

    acc1_resp = await client.post(
        "/api/v1/accounts",
        json={
            "chart_id": chart_id,
            "code": "1101",
            "name": "Cash",
            "account_type": "asset",
            "account_category": "current_asset",
        },
        headers=tenant_headers(TENANT_A),
    )
    acc2_resp = await client.post(
        "/api/v1/accounts",
        json={
            "chart_id": chart_id,
            "code": "4101",
            "name": "Revenue",
            "account_type": "revenue",
            "account_category": "operating_revenue",
        },
        headers=tenant_headers(TENANT_A),
    )
    acc1_id = acc1_resp.json()["id"]
    acc2_id = acc2_resp.json()["id"]

    voucher_resp = await client.post(
        "/api/v1/posting/vouchers",
        json={
            "fiscal_period_id": period_id,
            "voucher_number": "V-001",
            "voucher_date": str(date.today()),
            "description": "Test voucher",
            "lines": [
                {"account_id": acc1_id, "debit": "1000.0000", "credit": "0"},
                {"account_id": acc2_id, "debit": "0", "credit": "1000.0000"},
            ],
        },
        headers=tenant_headers(TENANT_A),
    )
    assert voucher_resp.status_code == 201
    voucher_id = voucher_resp.json()["id"]

    post_resp = await client.post(
        f"/api/v1/posting/vouchers/{voucher_id}/post",
        json={},
        headers=tenant_headers(TENANT_A),
    )
    assert post_resp.status_code == 200
    assert post_resp.json()["status"] == "posted"


@pytest.mark.asyncio
async def test_unbalanced_voucher_rejected(client):
    year_resp = await client.post(
        "/api/v1/fiscal/years",
        json={"name": "1404", "start_date": "2025-03-20", "end_date": "2026-03-19"},
        headers=tenant_headers(TENANT_A),
    )
    year_id = year_resp.json()["id"]
    period_resp = await client.post(
        "/api/v1/fiscal/periods",
        json={
            "fiscal_year_id": year_id,
            "name": "P1",
            "period_number": 1,
            "start_date": "2025-03-20",
            "end_date": "2025-04-19",
            "is_current": True,
        },
        headers=tenant_headers(TENANT_A),
    )
    period_id = period_resp.json()["id"]

    chart_resp = await client.post(
        "/api/v1/accounts/charts",
        json={"name": "COA2", "code": "COA-UNBAL"},
        headers=tenant_headers(TENANT_A),
    )
    chart_id = chart_resp.json()["id"]

    acc_resp = await client.post(
        "/api/v1/accounts",
        json={
            "chart_id": chart_id,
            "code": "1102",
            "name": "Bank",
            "account_type": "asset",
            "account_category": "current_asset",
        },
        headers=tenant_headers(TENANT_A),
    )
    acc_id = acc_resp.json()["id"]

    voucher_resp = await client.post(
        "/api/v1/posting/vouchers",
        json={
            "fiscal_period_id": period_id,
            "voucher_number": "V-UNBAL",
            "voucher_date": str(date.today()),
            "lines": [
                {"account_id": acc_id, "debit": "500", "credit": "0"},
                {"account_id": acc_id, "debit": "0", "credit": "300"},
            ],
        },
        headers=tenant_headers(TENANT_A),
    )
    voucher_id = voucher_resp.json()["id"]

    validate_resp = await client.post(
        f"/api/v1/posting/vouchers/{voucher_id}/validate",
        headers=tenant_headers(TENANT_A),
    )
    assert validate_resp.status_code == 422


@pytest.mark.asyncio
async def test_trial_balance(client):
    tb_resp = await client.post(
        "/api/v1/ledger/trial-balance",
        params={"fiscal_period_id": str(uuid.uuid4())},
        headers=tenant_headers(TENANT_A),
    )
    assert tb_resp.status_code == 200
    assert "is_balanced" in tb_resp.json()


@pytest.mark.asyncio
async def test_subsidiary_ledger_report(client):
    year_resp = await client.post(
        "/api/v1/fiscal/years",
        json={
            "name": "1404-sub",
            "start_date": "2025-03-21",
            "end_date": "2026-03-20",
            "is_current": True,
        },
        headers=tenant_headers(TENANT_A),
    )
    assert year_resp.status_code == 201
    year_id = year_resp.json()["id"]

    period_resp = await client.post(
        "/api/v1/fiscal/periods",
        json={
            "fiscal_year_id": year_id,
            "name": "Farvardin",
            "period_number": 1,
            "start_date": "2025-03-21",
            "end_date": "2025-04-20",
            "is_current": True,
        },
        headers=tenant_headers(TENANT_A),
    )
    assert period_resp.status_code == 201
    period_id = period_resp.json()["id"]

    chart_resp = await client.post(
        "/api/v1/accounts/charts",
        json={"name": "COA Sub", "code": "COA-SUB"},
        headers=tenant_headers(TENANT_A),
    )
    chart_id = chart_resp.json()["id"]
    await client.post(
        "/api/v1/accounts",
        json={
            "chart_id": chart_id,
            "code": "1101",
            "name": "صندوق",
            "account_type": "asset",
            "account_category": "current_asset",
            "level": 3,
            "is_postable": True,
            "is_group": False,
        },
        headers=tenant_headers(TENANT_A),
    )

    resp = await client.post(
        "/api/v1/reporting/subsidiary-ledger",
        params={"fiscal_period_id": period_id},
        headers=tenant_headers(TENANT_A),
    )
    assert resp.status_code == 200
    body = resp.json()
    assert "id" in body
    data = body["data"]
    if isinstance(data, str):
        import json

        data = json.loads(data)
    assert data["mode"] == "summary"
    assert data["level_mode"] == "subsidiary"
    assert isinstance(data["rows"], list)
    assert any(r.get("account_code") == "1101" for r in data["rows"])


@pytest.mark.asyncio
async def test_requires_tenant_header(client):
    resp = await client.get("/api/v1/accounts")
    assert resp.status_code == 400
