# backend/app/services/export_service.py — per-user 데이터 ZIP 번들(소유권) + 민감 필드 redact
import io
import json
import zipfile
from datetime import date, datetime

from sqlmodel import Session, select

from ..models import (
    ConnectorAccount,
    Email,
    InboxItem,
    Notification,
    Person,
    Task,
    Trip,
)

_REDACT_FIELDS = {"token_enc", "password_hash", "token_hash", "code_verifier", "scopes"}


def _ser(v):
    if isinstance(v, (datetime, date)):
        return v.isoformat()
    return v


def _dump(rows, user_id: str) -> list[dict]:
    out = []
    for r in rows:
        d = r.model_dump()
        if d.get("user_id") not in (None, user_id) and "user_id" in d:
            continue
        for k in list(d.keys()):
            if k in _REDACT_FIELDS and d[k]:
                d[k] = "[redacted]"
            else:
                d[k] = _ser(d[k])
        out.append(d)
    return out


def _scoped(session: Session, model, user_id: str):
    stmt = select(model)
    if hasattr(model, "user_id"):
        stmt = stmt.where(model.user_id == user_id)
    return session.exec(stmt).all()


def build_export(session: Session, user: Person) -> bytes:
    """사용자 전 데이터 ZIP(profile/tasks/inbox/emails/notifications/trips/connectors)."""
    buf = io.BytesIO()
    with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as z:
        profile = {"id": user.id, "name": user.name, "initial": user.initial, "email": user.email}
        z.writestr("profile.json", json.dumps(profile, ensure_ascii=False, indent=2))
        bundles = {
            "tasks.json": _dump(_scoped(session, Task, user.id), user.id),
            "inbox.json": _dump(_scoped(session, InboxItem, user.id), user.id),
            "emails.json": _dump(_scoped(session, Email, user.id), user.id),
            "notifications.json": _dump(_scoped(session, Notification, user.id), user.id),
            "trips.json": _dump(_scoped(session, Trip, user.id), user.id),
            "connectors.json": _dump(_scoped(session, ConnectorAccount, user.id), user.id),
        }
        for name, data in bundles.items():
            z.writestr(name, json.dumps(data, ensure_ascii=False, indent=2))
    return buf.getvalue()
