"""BAN YARO — Züchter-Fotos (Upload, Verwaltung, öffentliche Ansicht)"""
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
from fastapi.responses import FileResponse
from pydantic import BaseModel
from typing import Optional
import os, logging
from database import db
from auth import get_current_user, get_current_user_optional
from media_utils import validate_upload, generate_preview
import uuid

router = APIRouter()
logger = logging.getLogger(__name__)

MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")

_VALID_ENTITY_TYPES = {"breeder", "litter", "puppy", "parent"}


# ------------------------------------------------------------------
# Dependency: nur verifizierte Züchter + Admins
# ------------------------------------------------------------------
def _require_breeder(user=Depends(get_current_user)):
    if user["rolle"] not in ("breeder", "admin"):
        raise HTTPException(403, "Nur für Züchter.")
    return user


# ------------------------------------------------------------------
# Modelle
# ------------------------------------------------------------------
class VisibilityBody(BaseModel):
    visibility: str

class CaptionBody(BaseModel):
    caption: Optional[str] = None


# ------------------------------------------------------------------
# Hilfsfunktion: Züchter-Profil für User laden
# ------------------------------------------------------------------
def _get_breeder_profile(conn, user_id: int):
    row = conn.execute(
        "SELECT id FROM breeder_profiles WHERE user_id=?", (user_id,)
    ).fetchone()
    if not row:
        raise HTTPException(404, "Züchter-Profil nicht gefunden.")
    return row["id"]


# ------------------------------------------------------------------
# POST /api/breeder/photos/upload — Foto hochladen
# ------------------------------------------------------------------
@router.post("/breeder/photos/upload")
async def upload_photo(
    entity_type: str       = Form(...),
    entity_id:   int       = Form(...),
    visibility:  str       = Form("public"),
    caption:     str       = Form(""),
    is_primary:  int       = Form(0),
    file:        UploadFile = File(...),
    user=Depends(_require_breeder),
):
    if entity_type not in _VALID_ENTITY_TYPES:
        raise HTTPException(400, f"Ungültiger entity_type. Erlaubt: {', '.join(_VALID_ENTITY_TYPES)}")

    if visibility not in ("public", "inquiry", "private"):
        raise HTTPException(400, "Ungültige Sichtbarkeit.")

    raw_data = await file.read()
    filename = file.filename or "upload.jpg"

    try:
        validate_upload(raw_data, filename)
    except ValueError as e:
        raise HTTPException(400, str(e))

    ext = os.path.splitext(filename)[1].lower() or ".jpg"

    with db() as conn:
        breeder_id = _get_breeder_profile(conn, user["id"])

        # Ownership prüfen (für entity_type != 'breeder')
        if entity_type == "litter":
            row = conn.execute(
                "SELECT id FROM litters WHERE id=? AND breeder_id=?",
                (entity_id, breeder_id)
            ).fetchone()
            if not row and user["rolle"] != "admin":
                raise HTTPException(403, "Kein Zugriff auf diesen Wurf.")
        elif entity_type == "puppy":
            row = conn.execute(
                """SELECT p.id FROM litter_puppies p
                   JOIN litters l ON l.id=p.litter_id
                   WHERE p.id=? AND l.breeder_id=?""",
                (entity_id, breeder_id)
            ).fetchone()
            if not row and user["rolle"] != "admin":
                raise HTTPException(403, "Kein Zugriff auf diesen Welpen.")
        elif entity_type == "parent":
            # parent kann frei hochgeladen werden solange breeder stimmt
            pass
        elif entity_type == "breeder":
            # entity_id muss das eigene Profil sein
            if entity_id != breeder_id and user["rolle"] != "admin":
                raise HTTPException(403, "Kein Zugriff auf dieses Züchter-Profil.")

        # Speicherpfad anlegen
        save_dir = os.path.join(MEDIA_DIR, "breeders", str(breeder_id), entity_type)
        os.makedirs(save_dir, exist_ok=True)

        file_uuid = str(uuid.uuid4())
        file_path = os.path.join(save_dir, f"{file_uuid}.webp")

        # Thumbnail erzeugen
        thumb_bytes = generate_preview(raw_data, ext)
        thumb_path = None
        if thumb_bytes:
            thumb_path = os.path.join(save_dir, f"{file_uuid}_thumb.webp")
            with open(thumb_path, "wb") as f:
                f.write(thumb_bytes)

        # Originalbild konvertieren und speichern
        # generate_preview liefert WebP, für das Original nehmen wir Pillow direkt
        try:
            import io
            from PIL import Image, ImageOps
            img = Image.open(io.BytesIO(raw_data))
            img = ImageOps.exif_transpose(img)
            img = img.convert("RGB")
            img.save(file_path, format="WEBP", quality=85)
        except Exception:
            # Fallback: Rohdaten speichern
            with open(file_path, "wb") as f:
                f.write(raw_data)

        # Relative Pfade für DB (relativ zu MEDIA_DIR)
        rel_file  = os.path.relpath(file_path,  MEDIA_DIR)
        rel_thumb = os.path.relpath(thumb_path, MEDIA_DIR) if thumb_path else None

        # Falls is_primary: alle anderen auf 0 setzen
        if is_primary:
            conn.execute(
                "UPDATE breeder_photos SET is_primary=0 WHERE breeder_id=? AND entity_type=? AND entity_id=?",
                (breeder_id, entity_type, entity_id)
            )

        conn.execute(
            """INSERT INTO breeder_photos
               (breeder_id, entity_type, entity_id, file_path, thumbnail_path,
                caption, is_primary, visibility, sort_order, uploaded_at)
               VALUES (?,?,?,?,?,?,?,?,
                 (SELECT COALESCE(MAX(sort_order),0)+1 FROM breeder_photos
                  WHERE breeder_id=? AND entity_type=? AND entity_id=?),
                 datetime('now'))""",
            (breeder_id, entity_type, entity_id, rel_file, rel_thumb,
             caption.strip() or None, 1 if is_primary else 0,
             visibility,
             breeder_id, entity_type, entity_id)
        )
        photo_id = conn.execute("SELECT last_insert_rowid()").fetchone()[0]
        photo = conn.execute(
            "SELECT * FROM breeder_photos WHERE id=?", (photo_id,)
        ).fetchone()

    return _photo_dict(photo)


# ------------------------------------------------------------------
# GET /api/photos/{entity_type}/{entity_id} — Fotos abrufen
# ------------------------------------------------------------------
@router.get("/photos/{entity_type}/{entity_id}")
async def get_photos(
    entity_type: str,
    entity_id:   int,
    user=Depends(get_current_user_optional),
):
    if entity_type not in _VALID_ENTITY_TYPES:
        raise HTTPException(400, f"Ungültiger entity_type.")

    with db() as conn:
        # Prüfen ob anfragender User Besitzer oder Admin ist
        is_owner = False
        if user:
            if user["rolle"] == "admin":
                is_owner = True
            else:
                bp = conn.execute(
                    "SELECT id FROM breeder_profiles WHERE user_id=?", (user["id"],)
                ).fetchone()
                if bp:
                    # Besitzer wenn entity dem Züchter gehört
                    if entity_type == "breeder":
                        is_owner = (bp["id"] == entity_id)
                    elif entity_type == "litter":
                        row = conn.execute(
                            "SELECT id FROM litters WHERE id=? AND breeder_id=?",
                            (entity_id, bp["id"])
                        ).fetchone()
                        is_owner = bool(row)
                    elif entity_type == "puppy":
                        row = conn.execute(
                            """SELECT p.id FROM litter_puppies p
                               JOIN litters l ON l.id=p.litter_id
                               WHERE p.id=? AND l.breeder_id=?""",
                            (entity_id, bp["id"])
                        ).fetchone()
                        is_owner = bool(row)
                    elif entity_type == "parent":
                        row = conn.execute(
                            "SELECT id FROM breeder_photos WHERE entity_type='parent' AND entity_id=? AND breeder_id=?",
                            (entity_id, bp["id"])
                        ).fetchone()
                        is_owner = bool(row)

        if is_owner:
            photos = conn.execute(
                "SELECT * FROM breeder_photos WHERE entity_type=? AND entity_id=? ORDER BY sort_order, id",
                (entity_type, entity_id)
            ).fetchall()
        else:
            photos = conn.execute(
                "SELECT * FROM breeder_photos WHERE entity_type=? AND entity_id=? AND visibility='public' ORDER BY sort_order, id",
                (entity_type, entity_id)
            ).fetchall()

    return [_photo_dict(p) for p in photos]


# ------------------------------------------------------------------
# PATCH /api/breeder/photos/{id}/visibility
# ------------------------------------------------------------------
@router.patch("/breeder/photos/{photo_id}/visibility")
async def update_visibility(
    photo_id: int,
    body:     VisibilityBody,
    user=Depends(_require_breeder),
):
    if body.visibility not in ("public", "inquiry", "private"):
        raise HTTPException(400, "Ungültige Sichtbarkeit.")

    with db() as conn:
        photo = _get_own_photo(conn, photo_id, user)
        conn.execute(
            "UPDATE breeder_photos SET visibility=? WHERE id=?",
            (body.visibility, photo_id)
        )
        updated = conn.execute("SELECT * FROM breeder_photos WHERE id=?", (photo_id,)).fetchone()
    return _photo_dict(updated)


# ------------------------------------------------------------------
# PATCH /api/breeder/photos/{id}/primary
# ------------------------------------------------------------------
@router.patch("/breeder/photos/{photo_id}/primary")
async def set_primary(
    photo_id: int,
    user=Depends(_require_breeder),
):
    with db() as conn:
        photo = _get_own_photo(conn, photo_id, user)
        # Alle anderen auf 0
        conn.execute(
            "UPDATE breeder_photos SET is_primary=0 WHERE breeder_id=? AND entity_type=? AND entity_id=?",
            (photo["breeder_id"], photo["entity_type"], photo["entity_id"])
        )
        conn.execute(
            "UPDATE breeder_photos SET is_primary=1 WHERE id=?", (photo_id,)
        )
        updated = conn.execute("SELECT * FROM breeder_photos WHERE id=?", (photo_id,)).fetchone()
    return _photo_dict(updated)


# ------------------------------------------------------------------
# PATCH /api/breeder/photos/{id}/caption
# ------------------------------------------------------------------
@router.patch("/breeder/photos/{photo_id}/caption")
async def update_caption(
    photo_id: int,
    body:     CaptionBody,
    user=Depends(_require_breeder),
):
    with db() as conn:
        _get_own_photo(conn, photo_id, user)
        conn.execute(
            "UPDATE breeder_photos SET caption=? WHERE id=?",
            (body.caption, photo_id)
        )
        updated = conn.execute("SELECT * FROM breeder_photos WHERE id=?", (photo_id,)).fetchone()
    return _photo_dict(updated)


# ------------------------------------------------------------------
# DELETE /api/breeder/photos/{id}
# ------------------------------------------------------------------
@router.delete("/breeder/photos/{photo_id}")
async def delete_photo(
    photo_id: int,
    user=Depends(_require_breeder),
):
    with db() as conn:
        photo = _get_own_photo(conn, photo_id, user)

        # Dateien löschen
        for rel in (photo["file_path"], photo["thumbnail_path"]):
            if rel:
                abs_path = os.path.join(MEDIA_DIR, rel)
                try:
                    if os.path.isfile(abs_path):
                        os.unlink(abs_path)
                except OSError as e:
                    logger.warning("Konnte Datei nicht löschen: %s — %s", abs_path, e)

        conn.execute("DELETE FROM breeder_photos WHERE id=?", (photo_id,))

    return {"ok": True}


# ------------------------------------------------------------------
# Hilfsfunktionen
# ------------------------------------------------------------------
def _get_own_photo(conn, photo_id: int, user: dict):
    """Lädt das Foto und prüft Ownership. Wirft 403/404 bei Fehler."""
    photo = conn.execute(
        "SELECT * FROM breeder_photos WHERE id=?", (photo_id,)
    ).fetchone()
    if not photo:
        raise HTTPException(404, "Foto nicht gefunden.")

    if user["rolle"] == "admin":
        return photo

    # Prüfe ob Züchter-Profil dem User gehört
    bp = conn.execute(
        "SELECT id FROM breeder_profiles WHERE user_id=?", (user["id"],)
    ).fetchone()
    if not bp or bp["id"] != photo["breeder_id"]:
        raise HTTPException(403, "Kein Zugriff auf dieses Foto.")
    return photo


def _photo_dict(row) -> dict:
    """Konvertiert DB-Zeile in API-Response-Dict mit öffentlichen URLs."""
    if row is None:
        return {}
    d = dict(row)
    # Öffentliche URLs ableiten
    if d.get("file_path"):
        d["url"] = "/media/" + d["file_path"].replace("\\", "/")
    else:
        d["url"] = None
    if d.get("thumbnail_path"):
        d["thumbnail_url"] = "/media/" + d["thumbnail_path"].replace("\\", "/")
    else:
        d["thumbnail_url"] = d.get("url")
    return d
