"""
Goal Types Router - Custom Goal Type Definitions

Endpoints for managing goal type definitions (admin-only):
- CRUD for goal type definitions
- Schema info for building custom types

Part of v9h Goal System.
"""
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from typing import Optional
import traceback

from db import get_db, get_cursor, r2d
from auth import require_auth

router = APIRouter(prefix="/api/goals", tags=["goal-types"])

# ============================================================================
# Pydantic Models
# ============================================================================

class GoalTypeCreate(BaseModel):
    """Create custom goal type definition"""
    type_key: str
    label_de: str
    label_en: Optional[str] = None
    unit: str
    icon: Optional[str] = None
    category: Optional[str] = 'custom'
    source_table: Optional[str] = None
    source_column: Optional[str] = None
    aggregation_method: Optional[str] = 'latest'
    calculation_formula: Optional[str] = None
    filter_conditions: Optional[dict] = None
    description: Optional[str] = None

class GoalTypeUpdate(BaseModel):
    """Update goal type definition"""
    label_de: Optional[str] = None
    label_en: Optional[str] = None
    unit: Optional[str] = None
    icon: Optional[str] = None
    category: Optional[str] = None
    source_table: Optional[str] = None
    source_column: Optional[str] = None
    aggregation_method: Optional[str] = None
    calculation_formula: Optional[str] = None
    filter_conditions: Optional[dict] = None
    description: Optional[str] = None
    is_active: Optional[bool] = None

# ============================================================================
# Endpoints
# ============================================================================

@router.get("/schema-info")
def get_schema_info(session: dict = Depends(require_auth)):
    """
    Get available tables and columns for goal type creation.

    Admin-only endpoint for building custom goal types.
    Returns structure with descriptions for UX guidance.
    """
    pid = session['profile_id']

    # Check admin role
    with get_db() as conn:
        cur = get_cursor(conn)
        cur.execute("SELECT role FROM profiles WHERE id = %s", (pid,))
        profile = cur.fetchone()

        if not profile or profile['role'] != 'admin':
            raise HTTPException(status_code=403, detail="Admin-Zugriff erforderlich")

    # Define relevant tables with descriptions
    # Only include tables that make sense for goal tracking
    schema = {
        "weight_log": {
            "description": "Gewichtsverlauf",
            "columns": {
                "weight": {"type": "DECIMAL", "description": "Körpergewicht in kg"}
            }
        },
        "caliper_log": {
            "description": "Caliper-Messungen (Hautfalten)",
            "columns": {
                "body_fat_pct": {"type": "DECIMAL", "description": "Körperfettanteil in %"},
                "sum_mm": {"type": "DECIMAL", "description": "Summe Hautfalten in mm"}
            }
        },
        "circumference_log": {
            "description": "Umfangsmessungen",
            "columns": {
                "c_neck": {"type": "DECIMAL", "description": "Nackenumfang in cm"},
                "c_chest": {"type": "DECIMAL", "description": "Brustumfang in cm"},
                "c_waist": {"type": "DECIMAL", "description": "Taillenumfang in cm"},
                "c_hips": {"type": "DECIMAL", "description": "Hüftumfang in cm"},
                "c_thigh_l": {"type": "DECIMAL", "description": "Oberschenkel links in cm"},
                "c_thigh_r": {"type": "DECIMAL", "description": "Oberschenkel rechts in cm"},
                "c_calf_l": {"type": "DECIMAL", "description": "Wade links in cm"},
                "c_calf_r": {"type": "DECIMAL", "description": "Wade rechts in cm"},
                "c_bicep_l": {"type": "DECIMAL", "description": "Bizeps links in cm"},
                "c_bicep_r": {"type": "DECIMAL", "description": "Bizeps rechts in cm"}
            }
        },
        "activity_log": {
            "description": "Trainingseinheiten",
            "columns": {
                "id": {"type": "UUID", "description": "ID (für Zählung von Einheiten)"},
                "duration_minutes": {"type": "INTEGER", "description": "Trainingsdauer in Minuten"},
                "perceived_exertion": {"type": "INTEGER", "description": "Belastungsempfinden (1-10)"},
                "quality_rating": {"type": "INTEGER", "description": "Qualitätsbewertung (1-10)"}
            }
        },
        "nutrition_log": {
            "description": "Ernährungstagebuch",
            "columns": {
                "calories": {"type": "INTEGER", "description": "Kalorien in kcal"},
                "protein_g": {"type": "DECIMAL", "description": "Protein in g"},
                "carbs_g": {"type": "DECIMAL", "description": "Kohlenhydrate in g"},
                "fat_g": {"type": "DECIMAL", "description": "Fett in g"}
            }
        },
        "sleep_log": {
            "description": "Schlafprotokoll",
            "columns": {
                "total_minutes": {"type": "INTEGER", "description": "Gesamtschlafdauer in Minuten"}
            }
        },
        "vitals_baseline": {
            "description": "Vitalwerte (morgens)",
            "columns": {
                "resting_hr": {"type": "INTEGER", "description": "Ruhepuls in bpm"},
                "hrv_rmssd": {"type": "INTEGER", "description": "Herzratenvariabilität (RMSSD) in ms"},
                "vo2_max": {"type": "DECIMAL", "description": "VO2 Max in ml/kg/min"},
                "spo2": {"type": "INTEGER", "description": "Sauerstoffsättigung in %"},
                "respiratory_rate": {"type": "INTEGER", "description": "Atemfrequenz pro Minute"}
            }
        },
        "blood_pressure_log": {
            "description": "Blutdruckmessungen",
            "columns": {
                "systolic": {"type": "INTEGER", "description": "Systolischer Blutdruck in mmHg"},
                "diastolic": {"type": "INTEGER", "description": "Diastolischer Blutdruck in mmHg"},
                "pulse": {"type": "INTEGER", "description": "Puls in bpm"}
            }
        },
        "rest_days": {
            "description": "Ruhetage",
            "columns": {
                "id": {"type": "UUID", "description": "ID (für Zählung von Ruhetagen)"}
            }
        }
    }

    return schema

@router.get("/goal-types")
def list_goal_type_definitions(session: dict = Depends(require_auth)):
    """
    Get all active goal type definitions.

    Public endpoint - returns all available goal types for dropdown.
    """
    try:
        with get_db() as conn:
            cur = get_cursor(conn)

            cur.execute("""
                SELECT id, type_key, label_de, label_en, unit, icon, category,
                       source_table, source_column, aggregation_method,
                       calculation_formula, filter_conditions, description, is_system, is_active,
                       created_at, updated_at
                FROM goal_type_definitions
                WHERE is_active = true
                ORDER BY
                    CASE
                        WHEN is_system = true THEN 0
                        ELSE 1
                    END,
                    label_de
            """)

            results = [r2d(row) for row in cur.fetchall()]
            print(f"[DEBUG] Loaded {len(results)} goal types")
            return results

    except Exception as e:
        print(f"[ERROR] list_goal_type_definitions failed: {e}")
        print(traceback.format_exc())
        raise HTTPException(
            status_code=500,
            detail=f"Fehler beim Laden der Goal Types: {str(e)}"
        )

@router.post("/goal-types")
def create_goal_type_definition(
    data: GoalTypeCreate,
    session: dict = Depends(require_auth)
):
    """
    Create custom goal type definition.

    Admin-only endpoint for creating new goal types.
    Users with admin role can define custom metrics.
    """
    pid = session['profile_id']

    # Check admin role
    with get_db() as conn:
        cur = get_cursor(conn)
        cur.execute("SELECT role FROM profiles WHERE id = %s", (pid,))
        profile = cur.fetchone()

        if not profile or profile['role'] != 'admin':
            raise HTTPException(
                status_code=403,
                detail="Admin-Zugriff erforderlich"
            )

        # Validate type_key is unique
        cur.execute(
            "SELECT id FROM goal_type_definitions WHERE type_key = %s",
            (data.type_key,)
        )
        if cur.fetchone():
            raise HTTPException(
                status_code=400,
                detail=f"Goal Type '{data.type_key}' existiert bereits"
            )

        # Insert new goal type
        import json as json_lib
        filter_json = json_lib.dumps(data.filter_conditions) if data.filter_conditions else None

        cur.execute("""
            INSERT INTO goal_type_definitions (
                type_key, label_de, label_en, unit, icon, category,
                source_table, source_column, aggregation_method,
                calculation_formula, filter_conditions, description, is_active, is_system
            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            RETURNING id
        """, (
            data.type_key, data.label_de, data.label_en, data.unit, data.icon,
            data.category, data.source_table, data.source_column,
            data.aggregation_method, data.calculation_formula, filter_json, data.description,
            True, False  # is_active=True, is_system=False
        ))

        goal_type_id = cur.fetchone()['id']

        return {
            "id": goal_type_id,
            "message": f"Goal Type '{data.label_de}' erstellt"
        }

@router.put("/goal-types/{goal_type_id}")
def update_goal_type_definition(
    goal_type_id: str,
    data: GoalTypeUpdate,
    session: dict = Depends(require_auth)
):
    """
    Update goal type definition.

    Admin-only. System goal types can be updated but not deleted.
    """
    pid = session['profile_id']

    with get_db() as conn:
        cur = get_cursor(conn)

        # Check admin role
        cur.execute("SELECT role FROM profiles WHERE id = %s", (pid,))
        profile = cur.fetchone()

        if not profile or profile['role'] != 'admin':
            raise HTTPException(
                status_code=403,
                detail="Admin-Zugriff erforderlich"
            )

        # Check goal type exists
        cur.execute(
            "SELECT id FROM goal_type_definitions WHERE id = %s",
            (goal_type_id,)
        )
        if not cur.fetchone():
            raise HTTPException(status_code=404, detail="Goal Type nicht gefunden")

        # Build update query
        updates = []
        params = []

        if data.label_de is not None:
            updates.append("label_de = %s")
            params.append(data.label_de)

        if data.label_en is not None:
            updates.append("label_en = %s")
            params.append(data.label_en)

        if data.unit is not None:
            updates.append("unit = %s")
            params.append(data.unit)

        if data.icon is not None:
            updates.append("icon = %s")
            params.append(data.icon)

        if data.category is not None:
            updates.append("category = %s")
            params.append(data.category)

        if data.source_table is not None:
            updates.append("source_table = %s")
            params.append(data.source_table)

        if data.source_column is not None:
            updates.append("source_column = %s")
            params.append(data.source_column)

        if data.aggregation_method is not None:
            updates.append("aggregation_method = %s")
            params.append(data.aggregation_method)

        if data.calculation_formula is not None:
            updates.append("calculation_formula = %s")
            params.append(data.calculation_formula)

        if data.filter_conditions is not None:
            import json as json_lib
            filter_json = json_lib.dumps(data.filter_conditions) if data.filter_conditions else None
            updates.append("filter_conditions = %s")
            params.append(filter_json)

        if data.description is not None:
            updates.append("description = %s")
            params.append(data.description)

        if data.is_active is not None:
            updates.append("is_active = %s")
            params.append(data.is_active)

        if not updates:
            raise HTTPException(status_code=400, detail="Keine Änderungen angegeben")

        updates.append("updated_at = NOW()")
        params.append(goal_type_id)

        cur.execute(
            f"UPDATE goal_type_definitions SET {', '.join(updates)} WHERE id = %s",
            tuple(params)
        )

        return {"message": "Goal Type aktualisiert"}

@router.delete("/goal-types/{goal_type_id}")
def delete_goal_type_definition(
    goal_type_id: str,
    session: dict = Depends(require_auth)
):
    """
    Delete (deactivate) goal type definition.

    Admin-only. System goal types cannot be deleted, only deactivated.
    Custom goal types can be fully deleted if no goals reference them.
    """
    pid = session['profile_id']

    with get_db() as conn:
        cur = get_cursor(conn)

        # Check admin role
        cur.execute("SELECT role FROM profiles WHERE id = %s", (pid,))
        profile = cur.fetchone()

        if not profile or profile['role'] != 'admin':
            raise HTTPException(
                status_code=403,
                detail="Admin-Zugriff erforderlich"
            )

        # Get goal type info
        cur.execute(
            "SELECT id, type_key, is_system FROM goal_type_definitions WHERE id = %s",
            (goal_type_id,)
        )
        goal_type = cur.fetchone()

        if not goal_type:
            raise HTTPException(status_code=404, detail="Goal Type nicht gefunden")

        # Check if any goals use this type
        cur.execute(
            "SELECT COUNT(*) as count FROM goals WHERE goal_type = %s",
            (goal_type['type_key'],)
        )
        count = cur.fetchone()['count']

        if count > 0:
            # Deactivate instead of delete
            cur.execute(
                "UPDATE goal_type_definitions SET is_active = false WHERE id = %s",
                (goal_type_id,)
            )
            return {
                "message": f"Goal Type deaktiviert ({count} Ziele nutzen diesen Typ)"
            }
        else:
            if goal_type['is_system']:
                # System types: only deactivate
                cur.execute(
                    "UPDATE goal_type_definitions SET is_active = false WHERE id = %s",
                    (goal_type_id,)
                )
                return {"message": "System Goal Type deaktiviert"}
            else:
                # Custom types: delete
                cur.execute(
                    "DELETE FROM goal_type_definitions WHERE id = %s",
                    (goal_type_id,)
                )
                return {"message": "Goal Type gelöscht"}
