import logging
import os
from datetime import datetime

from asgiref.sync import async_to_sync
from django.views.decorators.csrf import csrf_exempt
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

from accounts.views import _session_user, _user_permissions
from app.config import settings
from app.config.config_storage import get_config_storage
from app.services.xero_cache import xero_cache
from app.config.xero_config import is_xero_enabled
from app.services.avg_time_to_invoice_service import get_avg_time_to_invoice_for_branch
from dashboard_api.demo_data import (
    build_branch_payload as build_demo_branch_payload,
    build_gp_violations_payload as build_demo_gp_violations_payload,
    build_kpi_month_payload as build_demo_kpi_month_payload,
    build_kpi_quarter_payload as build_demo_kpi_quarter_payload,
    build_misc_payload as build_demo_misc_payload,
    build_overview_payload as build_demo_overview_payload,
)
from app.services.google_reviews_service import get_google_review_counts_for_month
from app.services.job_efficiency_service import load_job_efficiency_for_branch
from app.services.kpi_sheets_service import kpi_sheets_service
from app.services.simpro_job_stats_service import get_job_stats_for_company
from app.services.simpro_quotes_service import get_quote_data_for_branch
from app.services.sheets_service import sheets_service
from app.services.time_utilisation_service import load_time_utilisation_for_branch
from app.services.whatconverts_service import whatconverts_service
from app.services.wip_jobs_service import get_wip_jobs_for_branch

try:
    from app.routers.directors import build_directors_payload
except ImportError:
    build_directors_payload = None
from integrations.adapters import get_sheets_service, get_simpro_client, get_xero_service
from integrations.capabilities import job_efficiency_csv_enabled
from integrations.client_context import get_current_client, get_resolved_workspace_client
from integrations.models import Client

logger = logging.getLogger(__name__)

_LOGO_MAX_BYTES = 2 * 1024 * 1024
_LOGO_EXTS = {".png", ".jpg", ".jpeg", ".webp", ".svg"}


def _client_branding_payload(client):
    logo_url = None
    if client.logo:
        try:
            logo_url = client.logo.url
        except ValueError:
            logo_url = None
    return {
        "company_display_name": (client.company_display_name or "").strip(),
        "client_name": client.name,
        "logo_url": logo_url,
        "display_company_name": client.branding_company_name(),
    }


BRANCH_ID_TO_NAME = {
    "branch1": "Busselton",
    "branch2": "Bunbury",
    "branch3": "Mandurah",
}
_google_review_totals_cache = None


def _parse_int(value, default):
    try:
        return int(value)
    except Exception:
        return default


def _optional_month_year_from_query(request):
    """Return (month (1–12)|None, year|None) only when both query params present."""
    m_raw = request.query_params.get("month")
    y_raw = request.query_params.get("year")
    if m_raw is None or y_raw is None or str(m_raw).strip() == "" or str(y_raw).strip() == "":
        return None, None
    month = _parse_int(str(m_raw).strip(), None)
    year = _parse_int(str(y_raw).strip(), None)
    if month is None or year is None:
        return None, None
    return month, year


def _parse_date(value):
    if not value:
        return None
    try:
        return datetime.strptime(value, "%Y-%m-%d").date()
    except ValueError:
        return None


def _get_google_review_totals_by_branch(year: int, month: int):
    global _google_review_totals_cache
    key = (year, month)
    if _google_review_totals_cache and _google_review_totals_cache[0] == key:
        return _google_review_totals_cache[1]
    try:
        raw = get_google_review_counts_for_month(year, month)
        out = {b: int(d.get("total") or 0) for b, d in raw.items()}
    except Exception as exc:
        logger.warning("Could not load Google review totals for marketing: %s", exc)
        out = {}
    _google_review_totals_cache = (key, out)
    return out


def _get_user_or_401(request):
    _, user = _session_user(request)
    if not user:
        return None, Response({"detail": "Not authenticated"}, status=401)
    return user, None


def _current_client_uses_demo_data() -> bool:
    client = get_current_client()
    return bool(client and getattr(client, "use_demo_data", False))


def _inject_branch_whatconverts(payload: dict, year: int, month: int) -> dict:
    """
    Ensure branch marketing payload includes WhatConverts channel summary,
    even when the response originated from demo data builders.
    """
    if not isinstance(payload, dict):
        return payload

    def _attach_for_branch(branch_obj: dict) -> None:
        branch_name = branch_obj.get("name")
        if not branch_name:
            return
        try:
            wc_rows = whatconverts_service.get_monthly_channel_summary(branch_name, year, month)
        except Exception as exc:
            logger.warning("Could not fetch WhatConverts monthly summary for %s: %s", branch_name, exc)
            wc_rows = []
        if not wc_rows:
            return
        marketing = branch_obj.get("marketing") or {}
        marketing["wc_channel_summary"] = wc_rows
        branch_obj["marketing"] = marketing

    # overview payload shape
    branches = payload.get("branches")
    if isinstance(branches, list):
        for branch in branches:
            if isinstance(branch, dict):
                _attach_for_branch(branch)
        return payload

    # branch_data payload shape
    if payload.get("name"):
        _attach_for_branch(payload)
    return payload


def _require_permission(request, permission_key: str):
    user, err = _get_user_or_401(request)
    if err:
        return None, err
    if permission_key not in _user_permissions(user):
        return None, Response({"detail": f"Missing permission: {permission_key}"}, status=403)
    return user, None


def _dept_type(name: str):
    if "Air" in name:
        return "Air"
    if "Residential" in name or "Electrical" in name:
        return "Electrics"
    if "Commercial" in name:
        return "Commercial"
    if "Solar" in name:
        return "Solar"
    return None


def _user_has_branch_access(user, branch_id: str) -> bool:
    perms = _user_permissions(user)
    if "directors.access" in perms:
        return True
    if f"branch.{branch_id}" in perms or f"kpi.{branch_id}" in perms:
        return True
    if any(p.startswith(f"department.{branch_id}_") for p in perms):
        return True
    return False


def _branch_data_payload(branch_id, month, year, from_date=None, to_date=None):
    if branch_id not in settings.BRANCHES:
        raise ValueError(f"Invalid branch_id: {branch_id}")
    from_dt = _parse_date(from_date)
    to_dt = _parse_date(to_date)
    use_date_range = bool(from_dt and to_dt and from_dt <= to_dt)

    branch_config = settings.BRANCHES[branch_id]
    departments = []
    xero_service = get_xero_service()
    use_xero = bool(is_xero_enabled(branch_id))

    branch_gp_margin = None
    gp_metrics_by_company = {}
    if use_xero:
        try:
            gp_metrics_by_company = (
                xero_service.get_business_group_gp_metrics_for_date_range(from_dt, to_dt, branch_id)
                if use_date_range else xero_service.get_business_group_gp_metrics(year, month, branch_id)
            )
            if gp_metrics_by_company:
                total_gp = sum((m.get("gross_profit", 0.0) or 0.0) for m in gp_metrics_by_company.values())
                total_revenue = sum((m.get("total_revenue", 0.0) or 0.0) for m in gp_metrics_by_company.values())
                if total_revenue > 0:
                    branch_gp_margin = (total_gp / total_revenue) * 100
        except Exception as exc:
            logger.warning("Could not fetch GP margin for %s: %s", branch_id, exc)

    total_gp_violations = 0
    if use_xero:
        try:
            xero_revenue = (
                xero_service.get_revenue_for_date_range_by_company(from_dt, to_dt, branch_id)
                if use_date_range else xero_service.get_revenue_for_month(year, month, branch_id)
            )
            for company_id, company_info in branch_config["companies"].items():
                revenue = max(0, xero_revenue.get(company_id, 0.0))
                gp_margin = None
                gp_dollars = None
                gp_color = None
                if gp_metrics_by_company:
                    gp_metrics = gp_metrics_by_company.get(company_id, {})
                    gp_margin = gp_metrics.get("gross_profit_margin")
                    raw_gp = gp_metrics.get("gross_profit")
                    gp_dollars = float(raw_gp) if raw_gp is not None else None
                if gp_margin is not None:
                    gp_color = get_config_storage().get_gp_color(company_info["name"], gp_margin)
                gp_violations = 0
                dept_type = _dept_type(company_info["name"])
                if dept_type:
                    try:
                        gp_violations = (
                            sheets_service.get_gp_violations_for_date_range(from_date=from_dt, to_date=to_dt, branch=branch_config["name"], department=dept_type)
                            if use_date_range else sheets_service.get_gp_violations_for_month(year=year, month=month, branch=branch_config["name"], department=dept_type)
                        )
                        total_gp_violations += gp_violations
                    except Exception as exc:
                        logger.warning("Could not fetch GP violations for %s %s: %s", branch_config["name"], dept_type, exc)

                departments.append(
                    {
                        "name": company_info["name"],
                        "current": revenue,
                        "breakeven": company_info["breakeven"],
                        "target": company_info["target"],
                        "gross_profit_margin": gp_margin,
                        "gross_profit": gp_dollars,
                        "gp_color": gp_color,
                        "gp_violations": gp_violations,
                    }
                )
        except Exception as exc:
            logger.exception("Error fetching Xero data for %s: %s", branch_id, exc)
            for _, company_info in branch_config["companies"].items():
                departments.append(
                    {
                        "name": company_info["name"],
                        "current": 0.0,
                        "breakeven": company_info["breakeven"],
                        "target": company_info["target"],
                        "gross_profit_margin": None,
                        "gross_profit": None,
                    }
                )
    else:
        for _, company_info in branch_config["companies"].items():
            departments.append(
                {
                    "name": company_info["name"],
                    "current": 0.0,
                    "breakeven": company_info["breakeven"],
                    "target": company_info["target"],
                }
            )

    marketing = None
    try:
        marketing_by_location = kpi_sheets_service.get_marketing_numbers(year, month)
        raw = marketing_by_location.get(branch_config["name"])
        if raw:
            marketing = {
                "google_cost": raw.get("google_cost", 0.0),
                "google_clicks": int(raw.get("google_clicks", 0)),
                "google_leads": int(raw.get("google_leads", 0)),
                "google_cost_per_lead": float(raw.get("google_cost_per_lead", 0.0)),
                "meta_cost": raw.get("meta_cost", 0.0),
                "meta_clicks": int(raw.get("meta_clicks", 0)),
                "meta_leads": int(raw.get("meta_leads", 0)),
                "meta_cost_per_lead": float(raw.get("meta_cost_per_lead", 0.0)),
                "total_quote_value": raw.get("total_quote_value", 0.0),
                "total_sales_value": raw.get("total_sales_value", 0.0),
            }
    except Exception as exc:
        logger.warning("Could not fetch marketing numbers for %s: %s", branch_id, exc)

    try:
        wc_rows = whatconverts_service.get_monthly_channel_summary(branch_config["name"], year, month)
        if wc_rows:
            marketing = marketing or {}
            marketing["wc_channel_summary"] = wc_rows
    except Exception as exc:
        logger.warning("Could not fetch WhatConverts monthly summary for %s: %s", branch_id, exc)

    return {
        "id": branch_id,
        "name": branch_config["name"],
        "departments": departments,
        "gross_profit_margin": branch_gp_margin,
        "gp_violations_total": total_gp_violations,
        "marketing": marketing,
        "google_review_totals_by_branch": _get_google_review_totals_by_branch(year, month),
    }


@api_view(["GET"])
def branch_data(request, branch_id):
    user, err = _get_user_or_401(request)
    if err:
        return err
    month = _parse_int(request.query_params.get("month"), 1)
    year = _parse_int(request.query_params.get("year"), datetime.utcnow().year)
    if _current_client_uses_demo_data():
        try:
            payload = build_demo_branch_payload(get_current_client(), branch_id, month, year)
            payload = _inject_branch_whatconverts(payload, year, month)
            return Response(payload)
        except ValueError as exc:
            return Response({"detail": str(exc)}, status=404)
    try:
        payload = _branch_data_payload(
            branch_id,
            month,
            year,
            request.query_params.get("from_date"),
            request.query_params.get("to_date"),
        )
        return Response(payload)
    except ValueError as exc:
        return Response({"detail": str(exc)}, status=404)


@api_view(["GET"])
def overview(request):
    user, err = _get_user_or_401(request)
    if err:
        return err
    month = _parse_int(request.query_params.get("month"), 1)
    year = _parse_int(request.query_params.get("year"), datetime.utcnow().year)
    if _current_client_uses_demo_data():
        payload = build_demo_overview_payload(get_current_client(), month, year)
        payload = _inject_branch_whatconverts(payload, year, month)
        return Response(payload)
    from_date = request.query_params.get("from_date")
    to_date = request.query_params.get("to_date")
    branches = []
    total_revenue = 0.0
    total_gp = 0.0
    for branch_id in settings.BRANCHES.keys():
        try:
            b = _branch_data_payload(branch_id, month, year, from_date, to_date)
        except Exception as exc:
            logger.exception("Overview failed for branch %s: %s", branch_id, exc)
            branch_config = settings.BRANCHES[branch_id]
            b = {
                "id": branch_id,
                "name": branch_config["name"],
                "departments": [
                    {
                        "name": c["name"],
                        "current": 0.0,
                        "breakeven": c["breakeven"],
                        "target": c["target"],
                    }
                    for c in branch_config["companies"].values()
                ],
                "gross_profit_margin": None,
                "gp_violations_total": 0,
                "google_review_totals_by_branch": _get_google_review_totals_by_branch(year, month),
            }
        branches.append(b)
        branch_revenue = sum((d.get("current", 0.0) or 0.0) for d in b["departments"])
        total_revenue += branch_revenue
        if b.get("gross_profit_margin") is not None and branch_revenue > 0:
            total_gp += branch_revenue * (b["gross_profit_margin"] / 100)
    overall_gp_margin = None
    overall_gp_color = None
    if total_revenue > 0:
        overall_gp_margin = (total_gp / total_revenue) * 100
        try:
            overall_gp_color = get_config_storage().get_gp_color("Electrical", overall_gp_margin)
        except Exception as exc:
            logger.warning("Could not compute overall GP color: %s", exc)
    return Response(
        {
            "branches": branches,
            "month": month,
            "year": year,
            "gross_profit_margin": overall_gp_margin,
            "overall_gp_color": overall_gp_color,
        }
    )


@api_view(["GET"])
def gp_violations(request):
    user, err = _get_user_or_401(request)
    if err:
        return err
    month = _parse_int(request.query_params.get("month"), 1)
    year = _parse_int(request.query_params.get("year"), datetime.utcnow().year)
    if _current_client_uses_demo_data():
        return Response(build_demo_gp_violations_payload(get_current_client(), month, year))
    from_date = _parse_date(request.query_params.get("from_date"))
    to_date = _parse_date(request.query_params.get("to_date"))
    use_date_range = bool(from_date and to_date and from_date <= to_date)
    branches = []
    company_total = 0
    for branch_id in settings.BRANCHES.keys():
        branch_config = settings.BRANCHES[branch_id]
        total_gp_violations = 0
        dept_violations = []
        for _, company_info in branch_config["companies"].items():
            dept_type = _dept_type(company_info["name"])
            if not dept_type:
                continue
            gp_v = 0
            try:
                gp_v = (
                    sheets_service.get_gp_violations_for_date_range(from_date=from_date, to_date=to_date, branch=branch_config["name"], department=dept_type)
                    if use_date_range else sheets_service.get_gp_violations_for_month(year=year, month=month, branch=branch_config["name"], department=dept_type)
                )
            except Exception:
                pass
            total_gp_violations += gp_v
            dept_violations.append({"name": company_info["name"], "gp_violations": gp_v})
        company_total += total_gp_violations
        branches.append({"id": branch_id, "gp_violations_total": total_gp_violations, "departments": dept_violations})
    return Response(
        {
            "month": month,
            "year": year,
            "from_date": request.query_params.get("from_date") if use_date_range else None,
            "to_date": request.query_params.get("to_date") if use_date_range else None,
            "branches": branches,
            "company_total": company_total,
        }
    )


@api_view(["GET"])
def kpi_month(request):
    user, err = _get_user_or_401(request)
    if err:
        return err
    month = _parse_int(request.query_params.get("month"), 1)
    year = _parse_int(request.query_params.get("year"), datetime.utcnow().year)
    if _current_client_uses_demo_data():
        return Response(build_demo_kpi_month_payload(get_current_client(), month, year))
    return Response(kpi_sheets_service.get_kpi_for_month(year=year, month=month))


@api_view(["GET"])
def kpi_quarter(request):
    user, err = _get_user_or_401(request)
    if err:
        return err
    month = _parse_int(request.query_params.get("month"), 1)
    year = _parse_int(request.query_params.get("year"), datetime.utcnow().year)
    if _current_client_uses_demo_data():
        return Response(build_demo_kpi_quarter_payload(get_current_client(), month, year))
    return Response(kpi_sheets_service.get_kpi_quarter(year=year, month=month))


@api_view(["GET"])
def kpi_targets(request):
    user, err = _get_user_or_401(request)
    if err:
        return err
    return Response(get_config_storage().get_kpi_targets())


@api_view(["GET"])
def misc_data(request, branch_id):
    user, err = _get_user_or_401(request)
    if err:
        return err
    branches_cfg = settings.BRANCHES
    if branch_id not in branches_cfg:
        return Response({"detail": f"Branch {branch_id} not found"}, status=404)
    if not _user_has_branch_access(user, branch_id):
        return Response({"detail": "Access denied to this branch"}, status=403)
    if _current_client_uses_demo_data():
        try:
            return Response(build_demo_misc_payload(get_current_client(), branch_id))
        except ValueError as exc:
            return Response({"detail": str(exc)}, status=404)
    branch_name = BRANCH_ID_TO_NAME.get(branch_id, branches_cfg[branch_id]["name"])
    wip_jobs = async_to_sync(get_wip_jobs_for_branch)(branch_id) or {}
    try:
        subscriber_totals = kpi_sheets_service.get_subscriber_totals()
        subscriber_count = subscriber_totals.get(branch_name, 0)
    except Exception:
        subscriber_count = 0
    job_efficiency = (
        load_job_efficiency_for_branch(branch_name)
        if job_efficiency_csv_enabled(get_current_client())
        else []
    )
    fd = _parse_date(request.query_params.get("from_date"))
    td = _parse_date(request.query_params.get("to_date"))
    quote_data = async_to_sync(get_quote_data_for_branch)(
        branch_id,
        fd if fd and td else None,
        td if fd and td else None,
    )
    return Response(
        {
            "quote_data": quote_data,
            "subscriber_count": subscriber_count,
            "time_utilisation": load_time_utilisation_for_branch(branch_name),
            "job_efficiency": job_efficiency,
            "wip_jobs": wip_jobs,
            "avg_time_to_invoice": get_avg_time_to_invoice_for_branch(branch_name),
        }
    )


@api_view(["GET"])
def branch_department_job_stats(request, branch_id):
    """
    Get Simpro job stats for a branch department:
    - jobs_completed
    - total_pending_jobs
    - pending_jobs_with_due_dates
    """
    user, err = _get_user_or_401(request)
    if err:
        return err
    if branch_id not in settings.BRANCHES:
        return Response({"detail": f"Branch {branch_id} not found"}, status=404)
    if not _user_has_branch_access(user, branch_id):
        return Response({"detail": "Access denied to this branch"}, status=403)

    department = (request.query_params.get("department") or "").strip()
    if not department:
        return Response({"detail": "department query parameter is required"}, status=400)

    branch_config = settings.BRANCHES[branch_id]
    company_id = None
    for cid, cinfo in branch_config["companies"].items():
        if cinfo.get("name", "").strip().lower() == department.lower():
            company_id = cid
            break
    if company_id is None:
        return Response(
            {"detail": f"Department '{department}' not found for branch {branch_id}"},
            status=404,
        )

    try:
        result = async_to_sync(get_job_stats_for_company)(branch_id, company_id)
        if not result:
            return Response({"detail": "Failed to fetch job stats from Simpro"}, status=502)
        return Response(result)
    except Exception as exc:
        logger.warning("Job stats fetch failed for %s %s: %s", branch_id, department, exc)
        return Response({"detail": "Failed to fetch job stats from Simpro"}, status=502)


@api_view(["GET"])
def directors_data(request):
    """
    Directors dashboard: revenue (weekly/MTD/FYTD), cash in bank, time utilisation, WIP, quotes, subscribers.
    Same payload as legacy FastAPI GET /api/directors. Requires directors.access.
    Optional query params: month (1–12), year — when both set, MTD = that calendar month.
    """
    _, err = _require_permission(request, "directors.access")
    if err:
        return err
    if not build_directors_payload:
        logger.error("build_directors_payload unavailable (directors router import failed)")
        return Response({"detail": "Directors data service unavailable"}, status=503)
    month, year = _optional_month_year_from_query(request)
    fd = _parse_date(request.query_params.get("from_date"))
    td = _parse_date(request.query_params.get("to_date"))
    try:
        payload = async_to_sync(build_directors_payload)(
            month=month,
            year=year,
            quote_from_date=fd,
            quote_to_date=td,
        )
        return Response(payload)
    except Exception as exc:
        logger.exception("Directors data failed: %s", exc)
        return Response({"detail": str(exc)}, status=500)


@api_view(["GET"])
def adapters_health(request):
    xero_ok = hasattr(get_xero_service(), "get_revenue_for_month")
    simpro_ok = hasattr(get_simpro_client(), "SimProClient")
    sheets_ok = hasattr(get_sheets_service(), "get_gp_violations_for_month")
    return Response({"xero": xero_ok, "simpro": simpro_ok, "sheets": sheets_ok})


@api_view(["GET"])
@authentication_classes([])
@permission_classes([AllowAny])
def public_branding(request):
    """Logo + company label for login/header. Optional ?subdomain= on apex hosts."""
    subdomain = (request.GET.get("subdomain") or "").strip().lower()
    client = None
    if subdomain:
        client = Client.objects.filter(subdomain=subdomain, is_active=True).first()
    if not client:
        client = get_resolved_workspace_client()
    if not client:
        return Response({"company_name": None, "logo_url": None})
    payload = _client_branding_payload(client)
    return Response({"company_name": payload["display_company_name"], "logo_url": payload["logo_url"]})


@csrf_exempt
@api_view(["GET", "PATCH"])
def admin_branding(request):
    _, err = _require_permission(request, "admin.access")
    if err:
        return err
    client = get_resolved_workspace_client()
    if not client:
        return Response({"detail": "No workspace resolved for this request"}, status=400)
    if request.method == "GET":
        return Response(_client_branding_payload(client))
    name = request.POST.get("company_display_name")
    if name is not None:
        client.company_display_name = (name or "")[:200]
    if request.POST.get("clear_logo") == "1":
        if client.logo:
            client.logo.delete(save=False)
        client.logo = None
    if "logo" in request.FILES:
        f = request.FILES["logo"]
        if getattr(f, "size", 0) > _LOGO_MAX_BYTES:
            return Response({"detail": "Logo too large (max 2MB)"}, status=400)
        ext = os.path.splitext(f.name)[1].lower()
        if ext not in _LOGO_EXTS:
            return Response({"detail": "Unsupported logo type. Use PNG, JPG, WebP, or SVG."}, status=400)
        if client.logo:
            client.logo.delete(save=False)
        client.logo = f
    client.save()
    return Response(_client_branding_payload(client))


@api_view(["GET"])
def admin_config(request):
    _, err = _require_permission(request, "admin.revenue_targets")
    if err:
        return err
    storage = get_config_storage()
    return Response(
        {
            "targets_breakevens": storage.get_targets_breakevens(),
            "gp_thresholds": storage.get_gp_thresholds(),
            "branches": {
                branch_id: {
                    "name": branch_config["name"],
                    "companies": {
                        str(company_id): company_info
                        for company_id, company_info in branch_config["companies"].items()
                    },
                }
                for branch_id, branch_config in settings.BRANCHES.items()
            },
        }
    )


@api_view(["PUT"])
def admin_update_target_breakeven(request, branch_id, company_id):
    _, err = _require_permission(request, "admin.revenue_targets")
    if err:
        return err
    if branch_id not in settings.BRANCHES:
        return Response({"detail": f"Branch {branch_id} not found"}, status=404)
    branch_cfg = settings.BRANCHES[branch_id]
    if company_id not in branch_cfg["companies"]:
        return Response(
            {"detail": f"Company {company_id} not found in branch {branch_id}"},
            status=404,
        )
    body = request.data if isinstance(request.data, dict) else {}
    target = body.get("target")
    breakeven = body.get("breakeven")
    get_config_storage().update_target_breakeven(
        branch_id=branch_id,
        company_id=company_id,
        target=target,
        breakeven=breakeven,
    )
    return Response(
        {
            "message": "Target/breakeven updated successfully",
            "branch_id": branch_id,
            "company_id": company_id,
            "target": target,
            "breakeven": breakeven,
        }
    )


@api_view(["GET"])
def admin_gp_thresholds(request):
    _, err = _require_permission(request, "admin.gp_thresholds")
    if err:
        return err
    return Response(get_config_storage().get_gp_thresholds())


@api_view(["PUT"])
def admin_update_gp_thresholds(request, department_type):
    _, err = _require_permission(request, "admin.gp_thresholds")
    if err:
        return err
    body = request.data if isinstance(request.data, dict) else {}
    try:
        green_min = float(body.get("green_min"))
        yellow_min = float(body.get("yellow_min"))
        yellow_max = float(body.get("yellow_max"))
        red_max = float(body.get("red_max"))
    except (TypeError, ValueError):
        return Response({"detail": "All threshold values must be numbers"}, status=400)

    if yellow_min >= yellow_max:
        return Response({"detail": "yellow_min must be less than yellow_max"}, status=400)
    if green_min < yellow_max:
        return Response(
            {"detail": "green_min must be greater than or equal to yellow_max"},
            status=400,
        )
    if red_max > yellow_min:
        return Response(
            {"detail": "red_max must be less than or equal to yellow_min"},
            status=400,
        )

    thresholds = {
        "green_min": green_min,
        "yellow_min": yellow_min,
        "yellow_max": yellow_max,
        "red_max": red_max,
    }
    get_config_storage().update_gp_thresholds(department_type=department_type, thresholds=thresholds)
    return Response(
        {
            "message": "GP thresholds updated successfully",
            "department_type": department_type,
            "thresholds": thresholds,
        }
    )


@api_view(["GET"])
def admin_cache_stats(request):
    _, err = _require_permission(request, "admin.access")
    if err:
        return err
    return Response(xero_cache.get_stats())


@api_view(["GET"])
def admin_kpi_targets(request):
    _, err = _require_permission(request, "admin.kpi_targets")
    if err:
        return err
    return Response(get_config_storage().get_kpi_targets())


@api_view(["PUT"])
def admin_update_kpi_target(request, branch, department, metric_key):
    _, err = _require_permission(request, "admin.kpi_targets")
    if err:
        return err
    body = request.data if isinstance(request.data, dict) else {}
    get_config_storage().update_kpi_targets(branch, department, metric_key, body)
    return Response({"status": "ok"})
