"""Tests für DSGVO-Löschkonzept (retention_service.py)."""
from datetime import date, datetime, timedelta, timezone

import pytest
import pytest_asyncio
from httpx import AsyncClient
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession

from app.services.retention_service import run_retention_purge


@pytest_asyncio.fixture(scope="session", loop_scope="session")
async def retention_headers(client: AsyncClient):
    resp = await client.post("/api/v1/auth/register", json={
        "company_name": "Retention GmbH",
        "first_name": "Rita",
        "last_name": "Tention",
        "email": "admin@retentiongmbh.de",
        "password": "Secret123",
    })
    assert resp.status_code == 201, resp.text
    data = resp.json()
    headers = {"Authorization": f"Bearer {data['access_token']}"}
    me = await client.get("/api/v1/users/me", headers=headers)
    return headers, me.json()["company_id"]


@pytest.mark.asyncio(loop_scope="session")
async def test_purge_deletes_old_time_entries_respects_retention(
    client: AsyncClient, db_session: AsyncSession, retention_headers
):
    headers, company_id = retention_headers
    me = await client.get("/api/v1/users/me", headers=headers)
    user_id = me.json()["id"]

    old_date = date.today() - timedelta(days=11 * 365)  # älter als Default 10 Jahre
    recent_date = date.today() - timedelta(days=30)

    await db_session.execute(text("SET LOCAL app.bypass_rls = 'on'"))
    await db_session.execute(text(
        "INSERT INTO time_entries (id, user_id, date, start_time, end_time, break_minutes, status, source) "
        "VALUES (gen_random_uuid(), :uid, :d, '08:00', '16:00', 0, 'approved', 'web')"
    ), {"uid": user_id, "d": old_date})
    await db_session.execute(text(
        "INSERT INTO time_entries (id, user_id, date, start_time, end_time, break_minutes, status, source) "
        "VALUES (gen_random_uuid(), :uid, :d, '08:00', '16:00', 0, 'approved', 'web')"
    ), {"uid": user_id, "d": recent_date})
    await db_session.commit()

    await db_session.execute(text("SET LOCAL app.bypass_rls = 'on'"))
    result = await run_retention_purge(db_session, company_id=company_id)
    await db_session.commit()
    assert result["time_entries"] == 1

    await db_session.execute(text("SET LOCAL app.bypass_rls = 'on'"))
    remaining = await db_session.execute(text(
        "SELECT date FROM time_entries WHERE user_id = :uid"
    ), {"uid": user_id})
    dates = [r[0] for r in remaining]
    assert old_date not in dates
    assert recent_date in dates


@pytest.mark.asyncio(loop_scope="session")
async def test_purge_configurable_retention_years(
    client: AsyncClient, db_session: AsyncSession, retention_headers
):
    headers, company_id = retention_headers
    up = await client.patch("/api/v1/companies/me",
                            json={"settings": {"retention_lohn_years": 2}}, headers=headers)
    assert up.status_code == 200, up.text

    me = await client.get("/api/v1/users/me", headers=headers)
    user_id = me.json()["id"]
    three_years_ago = date.today() - timedelta(days=3 * 365)

    await db_session.execute(text("SET LOCAL app.bypass_rls = 'on'"))
    await db_session.execute(text(
        "INSERT INTO time_entries (id, user_id, date, start_time, end_time, break_minutes, status, source) "
        "VALUES (gen_random_uuid(), :uid, :d, '08:00', '16:00', 0, 'approved', 'web')"
    ), {"uid": user_id, "d": three_years_ago})
    await db_session.commit()

    await db_session.execute(text("SET LOCAL app.bypass_rls = 'on'"))
    result = await run_retention_purge(db_session, company_id=company_id)
    await db_session.commit()
    assert result["time_entries"] >= 1


@pytest.mark.asyncio(loop_scope="session")
async def test_purge_expired_sessions_and_audit_logs_global(
    client: AsyncClient, db_session: AsyncSession, retention_headers
):
    headers, company_id = retention_headers
    me = await client.get("/api/v1/users/me", headers=headers)
    user_id = me.json()["id"]

    expired = datetime.now(timezone.utc) - timedelta(days=1)
    old_audit = datetime.now(timezone.utc) - timedelta(days=4 * 365)

    await db_session.execute(text("SET LOCAL app.bypass_rls = 'on'"))
    await db_session.execute(text(
        "INSERT INTO sessions (id, user_id, refresh_token_hash, expires_at) "
        "VALUES (gen_random_uuid(), :uid, :h, :exp)"
    ), {"uid": user_id, "h": "expired-hash-retention-test", "exp": expired})
    await db_session.execute(text(
        "INSERT INTO audit_logs (id, company_id, user_id, action, created_at) "
        "VALUES (gen_random_uuid(), :cid, :uid, 'test_old_action', :ts)"
    ), {"cid": company_id, "uid": user_id, "ts": old_audit})
    await db_session.commit()

    await db_session.execute(text("SET LOCAL app.bypass_rls = 'on'"))
    result = await run_retention_purge(db_session, company_id=None)
    await db_session.commit()
    assert result["sessions"] >= 1
    assert result["audit_logs"] >= 1
