import logging
from datetime import datetime, timedelta

from fastapi import APIRouter, Request, Form
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse, RedirectResponse
from app.core.database import execute_query, execute_query_single
from app.core.config import settings
from app.core.auth_service import AuthService
import jwt

router = APIRouter()
templates = Jinja2Templates(directory="app")
logger = logging.getLogger(__name__)

_DISALLOWED_DASHBOARD_PATHS = {
    "/dashboard/default",
    "/dashboard/default/clear",
}


def _sanitize_dashboard_path(value: str) -> str:
    if not value:
        return ""
    candidate = value.strip()
    if not candidate.startswith("/"):
        return ""
    if candidate.startswith("/api"):
        return ""
    if candidate.startswith("//"):
        return ""
    if candidate in _DISALLOWED_DASHBOARD_PATHS:
        return ""
    return candidate


def _get_user_default_dashboard(user_id: int) -> str:
    try:
        row = execute_query_single(
            """
            SELECT default_dashboard_path
            FROM user_dashboard_preferences
            WHERE user_id = %s
            """,
            (user_id,)
        )
        return _sanitize_dashboard_path((row or {}).get("default_dashboard_path", ""))
    except Exception as exc:
        if "user_dashboard_preferences" in str(exc):
            logger.warning("⚠️ user_dashboard_preferences table not found; using fallback default dashboard")
            return ""
        raise


def _get_user_group_names(user_id: int):
    rows = execute_query(
        """
        SELECT LOWER(g.name) AS name
        FROM user_groups ug
        JOIN groups g ON g.id = ug.group_id
        WHERE ug.user_id = %s
        """,
        (user_id,)
    )
    return [r["name"] for r in (rows or []) if r.get("name")]


def _is_technician_group(group_names) -> bool:
    return any(
        "technician" in group or "teknik" in group
        for group in (group_names or [])
    )


def _is_sales_group(group_names) -> bool:
    return any(
        "sales" in group or "salg" in group
        for group in (group_names or [])
    )


def _get_mission_access_pin() -> str:
    row = execute_query_single("SELECT value FROM settings WHERE key = %s", ("mission_access_pin",))
    db_pin = str((row or {}).get("value") or "").strip()
    env_pin = str(getattr(settings, "MISSION_ACCESS_PIN", "") or "").strip()
    return db_pin or env_pin


def _has_valid_mission_pin_token(request: Request) -> bool:
    token = request.cookies.get("mission_pin_token")
    payload = AuthService.verify_token(token) if token else None
    return bool(payload and payload.get("scope") == "mission_pin")


def _create_mission_pin_token() -> str:
    payload = {
        "sub": "0",
        "username": "mission-kiosk",
        "shadow_admin": True,
        "scope": "mission_pin",
        "iat": datetime.utcnow(),
        "exp": datetime.utcnow() + timedelta(hours=12),
    }
    return jwt.encode(payload, settings.JWT_SECRET_KEY, algorithm="HS256")


def _sanitize_mission_next(value: str) -> str:
    if not value:
        return "/dashboard/mission-control"
    candidate = value.strip()
    if candidate in {
        "/dashboard/mission-control",
        "/dashboard/mission-control/",
        "/dashboard/mission-control/projects",
        "/dashboard/mission-control/projects/",
        "/dashboard/mission-control.old",
        "/dashboard/mission-control.old/",
    }:
        return candidate
    if candidate.startswith("/api/v1/mission/"):
        return candidate
    return "/dashboard/mission-control"


def _render_mission_pin_page(error_text: str = "", next_path: str = "/dashboard/mission-control") -> HTMLResponse:
    safe_next = _sanitize_mission_next(next_path)
    error_html = f'<div style="margin:0.75rem 0;color:#ffb4b4;">{error_text}</div>' if error_text else ""
    html = f"""
    <!DOCTYPE html>
    <html lang=\"da\">
    <head>
      <meta charset=\"utf-8\" />
      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />
      <title>Mission Control PIN</title>
      <style>
        body {{ margin: 0; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif; background: #0b1320; color: #e9f1ff; display: grid; place-items: center; min-height: 100vh; }}
        .card {{ width: min(92vw, 420px); padding: 1.2rem; border: 1px solid #2c3c58; border-radius: 14px; background: #121d2f; }}
        .title {{ font-size: 1.2rem; font-weight: 700; margin: 0 0 0.5rem 0; }}
        .hint {{ color: #9fb3d1; font-size: 0.9rem; margin: 0 0 0.9rem 0; }}
        input {{ width: 100%; box-sizing: border-box; border: 1px solid #2c3c58; border-radius: 10px; background: #0f1a2b; color: #e9f1ff; padding: 0.7rem; font-size: 1rem; }}
        button {{ width: 100%; margin-top: 0.75rem; border: 1px solid #3b82f6; border-radius: 10px; background: #1f5bb8; color: #fff; font-weight: 600; padding: 0.65rem; cursor: pointer; }}
      </style>
    </head>
    <body>
      <div class=\"card\">
        <p class=\"title\">Mission Control</p>
        <p class=\"hint\">Indtast PIN-kode for at fortsætte.</p>
        {error_html}
        <form method=\"post\" action=\"/mission/pin/verify\">
          <input type=\"hidden\" name=\"next\" value=\"{safe_next}\" />
          <input type=\"password\" name=\"pin\" inputmode=\"numeric\" autocomplete=\"one-time-code\" placeholder=\"PIN-kode\" required />
          <button type=\"submit\">Åbn Mission Control</button>
        </form>
      </div>
    </body>
    </html>
    """
    return HTMLResponse(content=html)


@router.get("/mission/pin", response_class=HTMLResponse)
async def mission_pin_page(request: Request, next: str = "/dashboard/mission-control"):
    if _has_valid_mission_pin_token(request):
        return RedirectResponse(url=_sanitize_mission_next(next), status_code=302)
    return _render_mission_pin_page(next_path=next)


@router.get("/mission/pin/", response_class=HTMLResponse)
async def mission_pin_page_trailing_slash(request: Request, next: str = "/dashboard/mission-control"):
    return await mission_pin_page(request, next)


@router.post("/mission/pin/verify")
async def mission_pin_verify(pin: str = Form(...), next: str = Form("/dashboard/mission-control")):
    configured_pin = _get_mission_access_pin()
    if not configured_pin:
        return _render_mission_pin_page("PIN er ikke konfigureret på serveren.", next)

    if pin.strip() != configured_pin:
        return _render_mission_pin_page("Forkert PIN-kode.", next)

    token = _create_mission_pin_token()
    redirect_target = _sanitize_mission_next(next)
    response = RedirectResponse(url=redirect_target, status_code=302)
    response.set_cookie(
        key="mission_pin_token",
        value=token,
        httponly=True,
        samesite="Lax",
        max_age=60 * 60 * 12,
    )
    return response


@router.post("/mission/pin/logout")
async def mission_pin_logout():
    response = RedirectResponse(url="/mission/pin", status_code=302)
    response.delete_cookie("mission_pin_token")
    return response

@router.get("/", response_class=HTMLResponse)
async def dashboard(request: Request):
    """
    Render the dashboard page
    """
    user_id = getattr(request.state, "user_id", None)
    preferred_dashboard = ""

    if user_id:
        preferred_dashboard = _get_user_default_dashboard(int(user_id))

    if not preferred_dashboard:
        preferred_dashboard = _sanitize_dashboard_path(request.cookies.get("bmc_default_dashboard", ""))

    if preferred_dashboard and preferred_dashboard != "/":
        return RedirectResponse(url=preferred_dashboard, status_code=302)

    if user_id:
        group_names = _get_user_group_names(int(user_id))
        if _is_technician_group(group_names):
            return RedirectResponse(
                url=f"/ticket/dashboard/technician/v1?technician_user_id={int(user_id)}",
                status_code=302
            )
        if _is_sales_group(group_names):
            return RedirectResponse(url="/dashboard/sales", status_code=302)

    # Fetch count of unknown billing worklogs
    unknown_query = """
        SELECT COUNT(*) as count 
        FROM tticket_worklog 
        WHERE billing_method = 'unknown' 
        AND status NOT IN ('billed', 'rejected')
    """
    # Fetch active bankruptcy alerts
    # Finds emails classified as 'bankruptcy' that are not processed
    bankruptcy_query = """
        SELECT e.id, e.subject, e.received_date, 
               v.name as vendor_name, v.id as vendor_id,
               c.name as customer_name, c.id as customer_id
        FROM email_messages e
        LEFT JOIN vendors v ON e.supplier_id = v.id
        LEFT JOIN customers c ON e.customer_id = c.id
        WHERE e.classification = 'bankruptcy' 
        AND e.status NOT IN ('archived')
        AND (e.customer_id IS NOT NULL OR e.supplier_id IS NOT NULL)
        ORDER BY e.received_date DESC
    """
    
    from app.core.database import execute_query
    
    try:
        result = execute_query_single(unknown_query)
        unknown_count = result['count'] if result else 0
    except Exception as exc:
        if "tticket_worklog" in str(exc):
            logger.warning("⚠️ tticket_worklog table not found; defaulting unknown worklog count to 0")
            unknown_count = 0
        else:
            raise

    try:
        raw_alerts = execute_query(bankruptcy_query) or []
    except Exception as exc:
        if "email_messages" in str(exc):
            logger.warning("⚠️ email_messages table not found; skipping bankruptcy alerts")
            raw_alerts = []
        else:
            raise
    bankruptcy_alerts = []

    for alert in raw_alerts:
        item = dict(alert)
        # Determine display name
        if item.get('customer_name'):
            item['display_name'] = f"Kunde: {item['customer_name']}"
        elif item.get('vendor_name'):
            item['display_name'] = item['vendor_name']
        elif 'statstidende' in item.get('subject', '').lower():
            item['display_name'] = 'Statstidende'
        else:
            item['display_name'] = 'Ukendt Afsender'
        bankruptcy_alerts.append(item)

    return templates.TemplateResponse("dashboard/frontend/index.html", {
        "request": request,
        "unknown_worklog_count": unknown_count,
        "bankruptcy_alerts": bankruptcy_alerts
    })


@router.get("/dashboard/sales", response_class=HTMLResponse)
async def sales_dashboard(request: Request):
    pipeline_stats_query = """
        SELECT
            COUNT(*) FILTER (WHERE s.status = 'åben') AS open_count,
            COUNT(*) FILTER (WHERE s.status = 'lukket') AS closed_count,
            COALESCE(SUM(COALESCE(s.pipeline_amount, 0)) FILTER (WHERE s.status = 'åben'), 0) AS open_value,
            COALESCE(AVG(COALESCE(s.pipeline_probability, 0)) FILTER (WHERE s.status = 'åben'), 0) AS avg_probability
        FROM sag_sager s
        WHERE s.deleted_at IS NULL
          AND (
            s.template_key = 'pipeline'
            OR EXISTS (
                SELECT 1
                FROM entity_tags et
                JOIN tags t ON t.id = et.tag_id
                WHERE et.entity_type = 'case'
                  AND et.entity_id = s.id
                  AND LOWER(t.name) = 'pipeline'
            )
            OR EXISTS (
                SELECT 1
                FROM sag_tags st
                WHERE st.sag_id = s.id
                  AND st.deleted_at IS NULL
                  AND LOWER(st.tag_navn) = 'pipeline'
            )
          )
    """

    recent_opportunities_query = """
        SELECT
            s.id,
            s.titel,
            s.status,
            s.pipeline_amount,
            s.pipeline_probability,
            ps.name AS pipeline_stage,
            s.deadline,
            s.created_at,
            COALESCE(c.name, 'Ukendt kunde') AS customer_name,
            COALESCE(u.full_name, u.username, 'Ingen') AS owner_name
        FROM sag_sager s
        LEFT JOIN customers c ON c.id = s.customer_id
        LEFT JOIN users u ON u.user_id = s.ansvarlig_bruger_id
        LEFT JOIN pipeline_stages ps ON ps.id = s.pipeline_stage_id
        WHERE s.deleted_at IS NULL
          AND (
            s.template_key = 'pipeline'
            OR EXISTS (
                SELECT 1
                FROM entity_tags et
                JOIN tags t ON t.id = et.tag_id
                WHERE et.entity_type = 'case'
                  AND et.entity_id = s.id
                  AND LOWER(t.name) = 'pipeline'
            )
            OR EXISTS (
                SELECT 1
                FROM sag_tags st
                WHERE st.sag_id = s.id
                  AND st.deleted_at IS NULL
                  AND LOWER(st.tag_navn) = 'pipeline'
            )
          )
        ORDER BY s.created_at DESC
        LIMIT 12
    """

    due_soon_query = """
        SELECT
            s.id,
            s.titel,
            s.deadline,
            COALESCE(c.name, 'Ukendt kunde') AS customer_name,
            COALESCE(u.full_name, u.username, 'Ingen') AS owner_name
        FROM sag_sager s
        LEFT JOIN customers c ON c.id = s.customer_id
        LEFT JOIN users u ON u.user_id = s.ansvarlig_bruger_id
        WHERE s.deleted_at IS NULL
          AND s.deadline IS NOT NULL
          AND s.deadline BETWEEN CURRENT_DATE AND (CURRENT_DATE + INTERVAL '14 days')
          AND (
            s.template_key = 'pipeline'
            OR EXISTS (
                SELECT 1
                FROM entity_tags et
                JOIN tags t ON t.id = et.tag_id
                WHERE et.entity_type = 'case'
                  AND et.entity_id = s.id
                  AND LOWER(t.name) = 'pipeline'
            )
            OR EXISTS (
                SELECT 1
                FROM sag_tags st
                WHERE st.sag_id = s.id
                  AND st.deleted_at IS NULL
                  AND LOWER(st.tag_navn) = 'pipeline'
            )
          )
        ORDER BY s.deadline ASC
        LIMIT 8
    """

    pipeline_stats = execute_query_single(pipeline_stats_query) or {}
    recent_opportunities = execute_query(recent_opportunities_query) or []
    due_soon = execute_query(due_soon_query) or []

    return templates.TemplateResponse(
        "dashboard/frontend/sales.html",
        {
            "request": request,
            "pipeline_stats": pipeline_stats,
            "recent_opportunities": recent_opportunities,
            "due_soon": due_soon,
            "default_dashboard": _get_user_default_dashboard(getattr(request.state, "user_id", 0) or 0)
                or request.cookies.get("bmc_default_dashboard", "")
        }
    )


@router.post("/dashboard/default")
async def set_default_dashboard(
    request: Request,
    dashboard_path: str = Form(...),
    redirect_to: str = Form(default="/")
):
    safe_path = _sanitize_dashboard_path(dashboard_path)
    safe_redirect = _sanitize_dashboard_path(redirect_to) or "/"
    user_id = getattr(request.state, "user_id", None)

    response = RedirectResponse(url=safe_redirect, status_code=303)
    if safe_path:
        if user_id:
            try:
                execute_query(
                    """
                    INSERT INTO user_dashboard_preferences (user_id, default_dashboard_path, updated_at)
                    VALUES (%s, %s, CURRENT_TIMESTAMP)
                    ON CONFLICT (user_id)
                    DO UPDATE SET
                        default_dashboard_path = EXCLUDED.default_dashboard_path,
                        updated_at = CURRENT_TIMESTAMP
                    """,
                    (int(user_id), safe_path)
                )
            except Exception as exc:
                if "user_dashboard_preferences" in str(exc):
                    logger.warning("⚠️ Could not persist dashboard preference in DB (table missing); cookie fallback still active")
                else:
                    raise
        response.set_cookie(
            key="bmc_default_dashboard",
            value=safe_path,
            httponly=True,
            samesite="Lax"
        )
    return response


@router.get("/dashboard/default")
async def set_default_dashboard_get_fallback():
    return RedirectResponse(url="/settings#system", status_code=303)


@router.post("/dashboard/default/clear")
async def clear_default_dashboard(
    request: Request,
    redirect_to: str = Form(default="/")
):
    safe_redirect = _sanitize_dashboard_path(redirect_to) or "/"
    user_id = getattr(request.state, "user_id", None)
    if user_id:
        try:
            execute_query(
                "DELETE FROM user_dashboard_preferences WHERE user_id = %s",
                (int(user_id),)
            )
        except Exception as exc:
            if "user_dashboard_preferences" in str(exc):
                logger.warning("⚠️ Could not clear DB dashboard preference (table missing); cookie fallback still active")
            else:
                raise

    response = RedirectResponse(url=safe_redirect, status_code=303)
    response.delete_cookie("bmc_default_dashboard")
    return response


@router.get("/dashboard/default/clear")
async def clear_default_dashboard_get_fallback():
    return RedirectResponse(url="/settings#system", status_code=303)


@router.get("/dashboard/mission-control", response_class=HTMLResponse)
async def mission_control_dashboard(request: Request):
    return templates.TemplateResponse(
        "dashboard/frontend/mission_control_v2.html",
        {
            "request": request,
            "hide_top_nav": True,
            "mission_control_version": "v2",
            "mission_initial_view": "project",
        }
    )


@router.get("/dashboard/mission-control/", response_class=HTMLResponse)
async def mission_control_dashboard_trailing_slash(request: Request):
    return await mission_control_dashboard(request)


@router.get("/dashboard/mission-control/projects", response_class=HTMLResponse)
async def mission_control_projects_dashboard(request: Request):
    return templates.TemplateResponse(
        "dashboard/frontend/mission_control_v2.html",
        {
            "request": request,
            "hide_top_nav": True,
            "mission_control_version": "v2",
            "mission_initial_view": "project",
            "mission_project_only": True,
        }
    )


@router.get("/dashboard/mission-control/projects/", response_class=HTMLResponse)
async def mission_control_projects_dashboard_trailing_slash(request: Request):
    return await mission_control_projects_dashboard(request)


@router.get("/dashboard/mission-control.old", response_class=HTMLResponse)
async def mission_control_dashboard_legacy(request: Request):
    return templates.TemplateResponse(
        "dashboard/frontend/mission_control_legacy.html",
        {
            "request": request,
            "mission_control_version": "v1",
        }
    )


@router.get("/dashboard/mission-control.old/", response_class=HTMLResponse)
async def mission_control_dashboard_legacy_trailing_slash(request: Request):
    return await mission_control_dashboard_legacy(request)

