"""
Location Module - Frontend Views (Jinja2 Rendering)

Phase 3 Implementation: Jinja2 Template Views
Views: 5 total
1. GET /app/locations - List view (HTML)
2. GET /app/locations/create - Create form (HTML)
3. GET /app/locations/{id} - Detail view (HTML)
4. GET /app/locations/{id}/edit - Edit form (HTML)
5. GET /app/locations/map - Map view (HTML)

Each view:
- Loads Jinja2 template from templates/ directory
- Calls backend API endpoints (/api/v1/locations/...)
- Passes context to template for rendering
- Handles errors (404, template not found)
- Supports dark mode and responsive design
"""

from fastapi import APIRouter, Query, HTTPException, Path, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
from pathlib import Path as PathlibPath
import logging
from typing import Optional
from app.core.database import execute_query, execute_update

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

# Initialize Jinja2 environment pointing to templates directory
# Jinja2 loaders use the root directory for template lookups
# Since templates reference shared/frontend/base.html, root should be /app/app
app_root = PathlibPath(__file__).parent.parent.parent.parent  # /app/app

# Create a single FileSystemLoader rooted at app_root so that both relative paths work
loader = FileSystemLoader(str(app_root))

env = Environment(
    loader=loader,
    autoescape=True,
    trim_blocks=True,
    lstrip_blocks=True
)

# Use direct database access instead of API calls to avoid auth issues

# Location type options for dropdowns
LOCATION_TYPES = [
    {"value": "kompleks", "label": "Kompleks"},
    {"value": "bygning", "label": "Bygning"},
    {"value": "etage", "label": "Etage"},
    {"value": "customer_site", "label": "Kundesite"},
    {"value": "rum", "label": "Rum"},
    {"value": "kantine", "label": "Kantine"},
    {"value": "moedelokale", "label": "Mødelokale"},
    {"value": "vehicle", "label": "Køretøj"},
]


def render_template(template_name: str, **context) -> str:
    """
    Load and render a Jinja2 template with context.
    
    Args:
        template_name: Name of template file in templates/ directory
        **context: Variables to pass to template
    
    Returns:
        Rendered HTML string
    
    Raises:
        HTTPException: If template not found
    """
    try:
        template = env.get_template(template_name)
        return template.render(**context)
    except TemplateNotFound as e:
        logger.error(f"❌ Template not found: {template_name}")
        raise HTTPException(status_code=500, detail=f"Template {template_name} not found")
    except Exception as e:
        logger.error(f"❌ Error rendering template {template_name}: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error rendering template: {str(e)}")



def calculate_pagination(total: int, limit: int, skip: int) -> dict:
    """
    Calculate pagination metadata.
    
    Args:
        total: Total number of records
        limit: Records per page
        skip: Number of records to skip
    
    Returns:
        Dict with pagination info
    """
    total_pages = (total + limit - 1) // limit  # Ceiling division
    page_number = (skip // limit) + 1
    
    return {
        "total": total,
        "limit": limit,
        "skip": skip,
        "page_number": page_number,
        "total_pages": total_pages,
        "has_prev": skip > 0,
        "has_next": skip + limit < total,
    }


# ============================================================================
# 1. GET /app/locations - List view (HTML)
# ============================================================================

@router.get("/app/locations", response_class=HTMLResponse)
def list_locations_view(
    location_type: Optional[str] = Query(None, description="Filter by type"),
    is_active: Optional[str] = Query(None, description="Filter by active status"),
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=100)
):
    """
    Render the locations list page.
    
    Displays all locations in a table with:
    - Columns: Name, Type (badge), City, Status, Actions
    - Filters: by type, by active status
    - Pagination controls
    - Create button
    - Bulk select & delete
    
    Features:
    - Dark mode support (CSS variables)
    - Mobile responsive (table → cards at 768px)
    - Real-time search (optional)
    """
    try:
        logger.info(f"🔍 Rendering locations list view (skip={skip}, limit={limit})")
        
        # Convert is_active from string to boolean or None
        is_active_bool = None
        if is_active and is_active.lower() in ('true', '1', 'yes'):
            is_active_bool = True
        elif is_active and is_active.lower() in ('false', '0', 'no'):
            is_active_bool = False
        
        # Query locations directly from database
        where_clauses = ["deleted_at IS NULL"]
        query_params = []
        
        if location_type:
            where_clauses.append("location_type = %s")
            query_params.append(location_type)
        if is_active_bool is not None:
            where_clauses.append("is_active = %s")
            query_params.append(is_active_bool)
        
        where_sql = " AND ".join(where_clauses) if where_clauses else "1=1"
        
        query = f"""
            SELECT * FROM locations_locations
            WHERE {where_sql}
            ORDER BY name
            LIMIT %s OFFSET %s
        """
        query_params.extend([limit, skip])
        
        locations = execute_query(query, tuple(query_params))

        def build_tree(items: list) -> list:
            nodes = {}
            roots = []

            for loc in items or []:
                if not isinstance(loc, dict):
                    continue
                loc_id = loc.get("id")
                if loc_id is None:
                    continue
                nodes[loc_id] = {
                    "id": loc_id,
                    "name": loc.get("name"),
                    "location_type": loc.get("location_type"),
                    "parent_location_id": loc.get("parent_location_id"),
                    "address_city": loc.get("address_city"),
                    "is_active": loc.get("is_active", True)
                }

            for node in nodes.values():
                parent_id = node.get("parent_location_id")
                if parent_id and parent_id in nodes:
                    nodes[parent_id].setdefault("children", []).append(node)
                else:
                    roots.append(node)

            def sort_nodes(node_list: list) -> None:
                node_list.sort(key=lambda n: (n.get("name") or "").lower())
                for n in node_list:
                    if n.get("children"):
                        sort_nodes(n["children"])

            sort_nodes(roots)
            return roots

        location_tree = build_tree(locations if isinstance(locations, list) else [])
        
        # Get total count (API returns full list, so count locally)
        # In production, the API should return {data: [...], total: N}
        total = len(locations) if isinstance(locations, list) else locations.get("total", 0)
        
        # Calculate pagination info
        pagination = calculate_pagination(total, limit, skip)
        
        # Render template with context
        html = render_template(
            "modules/locations/templates/list.html",
            locations=locations,
            total=total,
            skip=skip,
            limit=limit,
            location_type=location_type,
            is_active=is_active_bool,  # Use boolean value for template
            page_number=pagination["page_number"],
            total_pages=pagination["total_pages"],
            has_prev=pagination["has_prev"],
            has_next=pagination["has_next"],
            location_types=LOCATION_TYPES,
            location_tree=location_tree,
            create_url="/app/locations/create",
            map_url="/app/locations/map",
        )
        
        logger.info(f"✅ Rendered locations list (showing {len(locations)} of {total})")
        return HTMLResponse(content=html)
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"❌ Error rendering locations list: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error rendering list view: {str(e)}")


# ============================================================================
# 2. GET /app/locations/create - Create form (HTML)
# ============================================================================

@router.get("/app/locations/create", response_class=HTMLResponse)
def create_location_view():
    """
    Render the location creation form.
    
    Form fields:
    - Name (required)
    - Type (required, dropdown)
    - Address (street, city, postal code, country)
    - Contact info (phone, email)
    - Coordinates (latitude, longitude)
    - Notes
    - Active toggle
    
    Form submission:
    - POST to /api/v1/locations
    - Redirect to detail page on success
    - Show errors inline on validation fail
    """
    try:
        logger.info("🆕 Rendering create location form")

        # Query parent locations
        parent_locations = execute_query("""
            SELECT id, name, location_type
            FROM locations_locations
            WHERE deleted_at IS NULL AND is_active = true
            ORDER BY name
            LIMIT 1000
        """)

        # Query customers
        customers = execute_query("""
            SELECT id, name, email, phone
            FROM customers
            WHERE deleted_at IS NULL AND is_active = true
            ORDER BY name
            LIMIT 1000
        """)
        
        # Render template with context
        html = render_template(
            "modules/locations/templates/create.html",
            form_action="/api/v1/locations",
            form_method="POST",
            submit_text="Create Location",
            cancel_url="/app/locations",
            location_types=LOCATION_TYPES,
            parent_locations=parent_locations,
            customers=customers,
            location=None,  # No location data for create form
        )
        
        logger.info("✅ Rendered create location form")
        return HTMLResponse(content=html)
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"❌ Error rendering create form: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error rendering create form: {str(e)}")


# =========================================================================
# 2b. GET /app/locations/wizard - Wizard for floors and rooms
# =========================================================================

@router.get("/app/locations/wizard", response_class=HTMLResponse)
def location_wizard_view():
    """
    Render the location wizard form.
    """
    try:
        logger.info("🧭 Rendering location wizard")

        parent_locations = execute_query("""
                SELECT id, name, location_type
                FROM locations_locations
                WHERE deleted_at IS NULL AND is_active = true
                ORDER BY name
                LIMIT 1000
            """)

        customers = execute_query("""
            SELECT id, name, email, phone
            FROM customers
            WHERE deleted_at IS NULL AND is_active = true
            ORDER BY name
            LIMIT 1000
        """)

        html = render_template(
            "modules/locations/templates/wizard.html",
            location_types=LOCATION_TYPES,
            parent_locations=parent_locations,
            customers=customers,
            cancel_url="/app/locations",
        )

        logger.info("✅ Rendered location wizard")
        return HTMLResponse(content=html)

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"❌ Error rendering wizard: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error rendering wizard: {str(e)}")


# ============================================================================
# 3. GET /app/locations/{id} - Detail view (HTML)
# ============================================================================

@router.get("/app/locations/{id}", response_class=HTMLResponse)
def detail_location_view(id: int = Path(..., gt=0)):
    """
    Render the location detail page.
    
    Displays:
    - Location basic info (name, type, address, contact)
    - Contact persons (list + add form)
    - Operating hours (table + add form)
    - Services (list + add form)
    - Capacity tracking (list + add form)
    - Map (if lat/long available)
    - Audit trail (collapsible)
    - Action buttons (Edit, Delete, Back)
    """
    try:
        logger.info(f"📍 Rendering detail view for location {id}")
        
        # Query location details directly
        location = execute_query(
            "SELECT * FROM locations_locations WHERE id = %s",
            (id,)
        )
        
        if not location:
            logger.warning(f"⚠️ Location {id} not found")
            raise HTTPException(status_code=404, detail=f"Location {id} not found")
        
        location = location[0]  # Get first result

        hierarchy = []
        current_parent_id = location.get("parent_location_id")
        while current_parent_id:
            parent = execute_query(
                "SELECT id, name, location_type, parent_location_id FROM locations_locations WHERE id = %s",
                (current_parent_id,)
            )
            if not parent:
                break
            parent_row = parent[0]
            hierarchy.insert(0, parent_row)
            current_parent_id = parent_row.get("parent_location_id")

        children = execute_query(
            """
            SELECT id, name, location_type
            FROM locations_locations
            WHERE parent_location_id = %s AND deleted_at IS NULL
            ORDER BY name
            """,
            (id,)
        )

        contacts = execute_query(
            """
            SELECT id, location_id, related_contact_id, contact_name, contact_email, contact_phone,
                   role, is_primary, created_at
            FROM locations_contacts
            WHERE location_id = %s AND deleted_at IS NULL
            ORDER BY is_primary DESC, contact_name ASC
            """,
            (id,)
        )

        operating_hours = execute_query(
            """
            SELECT id, location_id, day_of_week,
                   CASE day_of_week
                       WHEN 0 THEN 'Mandag'
                       WHEN 1 THEN 'Tirsdag'
                       WHEN 2 THEN 'Onsdag'
                       WHEN 3 THEN 'Torsdag'
                       WHEN 4 THEN 'Fredag'
                       WHEN 5 THEN 'Lørdag'
                       WHEN 6 THEN 'Søndag'
                   END AS day_name,
                   open_time, close_time, is_open, notes
            FROM locations_hours
            WHERE location_id = %s
            ORDER BY day_of_week ASC
            """,
            (id,)
        )

        services = execute_query(
            """
            SELECT id, location_id, service_name, is_available, created_at
            FROM locations_services
            WHERE location_id = %s AND deleted_at IS NULL
            ORDER BY service_name ASC
            """,
            (id,)
        )

        capacity = execute_query(
            """
            SELECT id, location_id, capacity_type, total_capacity, used_capacity, last_updated
            FROM locations_capacity
            WHERE location_id = %s
            ORDER BY capacity_type ASC
            """,
            (id,)
        )

        hardware = execute_query(
            """
            SELECT id, asset_type, brand, model, serial_number, status
            FROM hardware_assets
            WHERE current_location_id = %s AND deleted_at IS NULL
            ORDER BY brand ASC, model ASC, serial_number ASC
            """,
            (id,)
        )

        audit_log = execute_query(
            """
            SELECT id, location_id, event_type, user_id, changes, created_at
            FROM locations_audit_log
            WHERE location_id = %s
            ORDER BY created_at DESC
            """,
            (id,)
        )

        location["hierarchy"] = hierarchy
        location["children"] = children
        location["contacts"] = contacts or []
        location["operating_hours"] = operating_hours or []
        location["services"] = services or []
        location["capacity"] = capacity or []
        location["hardware"] = hardware or []
        location["audit_log"] = audit_log or []

        # Query customers
        customers = execute_query("""
            SELECT id, name, email, phone
            FROM customers
            WHERE deleted_at IS NULL AND is_active = true
            ORDER BY name
            LIMIT 1000
        """)
        
        # Optionally fetch related data if available from API
        # contacts = call_api("GET", f"/api/v1/locations/{id}/contacts")
        # hours = call_api("GET", f"/api/v1/locations/{id}/hours")
        
        # Render template with context
        html = render_template(
            "modules/locations/templates/detail.html",
            location=location,
            edit_url=f"/app/locations/{id}/edit",
            list_url="/app/locations",
            map_url="/app/locations/map",
            location_types=LOCATION_TYPES,
            customers=customers,
        )
        
        logger.info(f"✅ Rendered detail view for location {id}: {location.get('name', 'Unknown')}")
        return HTMLResponse(content=html)
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"❌ Error rendering detail view for location {id}: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error rendering detail view: {str(e)}")


# ============================================================================
# 4. GET /app/locations/{id}/edit - Edit form (HTML)
# ============================================================================

@router.get("/app/locations/{id}/edit", response_class=HTMLResponse)
def edit_location_view(id: int = Path(..., gt=0)):
    """
    Render the location edit form.
    
    Pre-filled with current data.
    Form submission:
    - PATCH to /api/v1/locations/{id}
    - Redirect to detail page on success
    """
    try:
        logger.info(f"✏️ Rendering edit form for location {id}")
        
        # Query location details
        location = execute_query(
            "SELECT * FROM locations_locations WHERE id = %s",
            (id,)
        )
        
        if not location:
            logger.warning(f"⚠️ Location {id} not found for edit")
            raise HTTPException(status_code=404, detail=f"Location {id} not found")
        
        location = location[0]  # Get first result

        # Query parent locations (exclude self)
        parent_locations = execute_query("""
            SELECT id, name, location_type
            FROM locations_locations
            WHERE is_active = true AND id != %s
            ORDER BY name
            LIMIT 1000
        """, (id,))

        # Query customers
        customers = execute_query("""
            SELECT id, name, email, phone
            FROM customers
            WHERE deleted_at IS NULL AND is_active = true
            ORDER BY name
            LIMIT 1000
        """)
        
        # Render template with context
        # Note: HTML forms don't support PATCH, so we use POST with a hidden _method field
        html = render_template(
            "modules/locations/templates/edit.html",
            location=location,
            form_action=f"/app/locations/{id}/edit",
            form_method="POST",  # HTML forms only support GET and POST
            submit_text="Update Location",
            cancel_url=f"/app/locations/{id}",
            location_types=LOCATION_TYPES,
            parent_locations=parent_locations,
            customers=customers,
            http_method="PATCH",  # Pass actual HTTP method for form to use via JavaScript/hidden field
        )
        
        logger.info(f"✅ Rendered edit form for location {id}: {location.get('name', 'Unknown')}")
        return HTMLResponse(content=html)
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"❌ Error rendering edit form for location {id}: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error rendering edit form: {str(e)}")


# ============================================================================
# 4b. POST /app/locations/{id}/edit - Handle form submission (fallback)
# ============================================================================

@router.post("/app/locations/{id}/edit")
async def update_location_view(request: Request, id: int = Path(..., gt=0)):
    """Handle edit form submission and redirect to detail page."""
    try:
        form = await request.form()
        
        # Update location directly in database
        execute_update("""
            UPDATE locations_locations SET
                name = %s,
                location_type = %s,
                parent_location_id = %s,
                customer_id = %s,
                is_active = %s,
                address_street = %s,
                address_city = %s,
                address_postal_code = %s,
                address_country = %s,
                phone = %s,
                email = %s,
                latitude = %s,
                longitude = %s,
                notes = %s,
                updated_at = CURRENT_TIMESTAMP
            WHERE id = %s
        """, (
            form.get("name"),
            form.get("location_type"),
            int(form.get("parent_location_id")) if form.get("parent_location_id") else None,
            int(form.get("customer_id")) if form.get("customer_id") else None,
            form.get("is_active") == "on",
            form.get("address_street"),
            form.get("address_city"),
            form.get("address_postal_code"),
            form.get("address_country"),
            form.get("phone"),
            form.get("email"),
            float(form.get("latitude")) if form.get("latitude") else None,
            float(form.get("longitude")) if form.get("longitude") else None,
            form.get("notes"),
            id
        ))
        
        return RedirectResponse(url=f"/app/locations/{id}", status_code=303)

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"❌ Error updating location {id}: {str(e)}")
        raise HTTPException(status_code=500, detail="Failed to update location")


# ============================================================================
# 5. GET /app/locations/map - Map view (HTML) [Optional]
# ============================================================================

@router.get("/app/locations/map", response_class=HTMLResponse)
def map_locations_view(
    location_type: Optional[str] = Query(None, description="Filter by type")
):
    """
    Render interactive map showing all locations.
    
    Features:
    - Leaflet.js map
    - Location markers with popups
    - Filter by type dropdown
    - Click marker to go to detail page
    - Center on first location or default coordinates
    """
    try:
        logger.info("🗺️ Rendering map view")
        
        # Query all locations with filters
        where_clauses = []
        query_params = []
        
        if location_type:
            where_clauses.append("location_type = %s")
            query_params.append(location_type)
        
        where_sql = " AND ".join(where_clauses) if where_clauses else "1=1"
        
        query = f"""
            SELECT * FROM locations_locations
            WHERE {where_sql}
            ORDER BY name
            LIMIT 1000
        """
        
        locations = execute_query(query, tuple(query_params) if query_params else None)
        
        # Filter to locations with coordinates
        locations_with_coords = [
            loc for loc in locations
            if isinstance(loc, dict) and loc.get("latitude") and loc.get("longitude")
        ]
        
        logger.info(f"📍 Found {len(locations_with_coords)} locations with coordinates")
        
        # Determine center coordinates (first location or default Copenhagen)
        if locations_with_coords:
            center_lat = locations_with_coords[0].get("latitude", 55.6761)
            center_lng = locations_with_coords[0].get("longitude", 12.5683)
        else:
            # Default to Copenhagen
            center_lat = 55.6761
            center_lng = 12.5683
        
        # Render template with context
        html = render_template(
            "modules/locations/templates/map.html",
            locations=locations_with_coords,
            center_lat=center_lat,
            center_lng=center_lng,
            zoom_level=6,  # Denmark zoom level
            location_type=location_type,
            location_types=LOCATION_TYPES,
            list_url="/app/locations",
        )
        
        logger.info(f"✅ Rendered map view with {len(locations_with_coords)} locations")
        return HTMLResponse(content=html)
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"❌ Error rendering map view: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error rendering map view: {str(e)}")
