@router.get("/list")
async def list_settings(db: AsyncSession = Depends(get_db),
                        user: User = Depends(get_current_user)):
    """All settings with current values (DB overrides) and metadata for the UI."""
    rows = (await db.execute(
        select(ApplicationSettings).where(ApplicationSettings.key.in_(SETTING_DEFS.keys()))
    )).scalars().all()
    stored = {r.key: r.value for r in rows}
    out = []
    for key, d in SETTING_DEFS.items():
        out.append({
            "key": key,
            "label": d["label"],
            "category": d["category"],
            "type": d["type"],
            "value": stored.get(key, d["default"]),
            "default": d["default"],
            "is_default": key not in stored,
        })
    return {"settings": out}


@router.post("/save")
async def save_setting(payload: SettingIn, db: AsyncSession = Depends(get_db),
                       user: User = Depends(get_current_user),
                       _: None = Depends(require_csrf)):
    ok, value = _validate_value(payload.key, payload.value)
    if not ok:
        raise HTTPException(status_code=400, detail=value)
    row = await db.execute(
        select(ApplicationSettings).where(ApplicationSettings.key == payload.key))
    row = row.scalar()
    if row:
        row.value = value
        row.description = payload.description or row.description
    else:
        db.add(ApplicationSettings(key=payload.key, value=value,
                                   description=payload.description or SETTING_DEFS[payload.key]["label"],
                                   category=SETTING_DEFS[payload.key]["category"]))
    await db.commit()
    await log_audit(db, user.id, "settings.save", "application_setting", None,
                    {"key": payload.key})
    return {"key": payload.key, "value": value}


@router.post("/save-batch")
async def save_batch(payload: BatchSettingsIn, db: AsyncSession = Depends(get_db),
                     user: User = Depends(get_current_user),
                     _: None = Depends(require_csrf)):
    """Save multiple settings at once (Settings page form)."""
    applied, errors = {}, {}
===PHONES-IMPORT===
@router.post("/import")
async def import_phones(file: UploadFile = None, db: AsyncSession = Depends(get_db),
                        user: User = Depends(get_current_user),
                        _: None = Depends(require_csrf)):
    """Import phone numbers from CSV (phone[,label]) or TXT (one per line).
    Supports bulk import of 10+ numbers at once."""
    if file is None:
        raise HTTPException(status_code=400, detail="No file uploaded")
    raw = await file.read()
    if len(raw) > 2 * 1024 * 1024:
        raise HTTPException(status_code=413, detail="File exceeds 2MB")
    try:
        text = raw.decode("utf-8-sig")
    except UnicodeDecodeError:
        raise HTTPException(status_code=400, detail="File must be UTF-8 text")

    # reject JSON-style input explicitly (CSV/TXT only per spec)
    stripped = text.lstrip()
    if stripped.startswith("{") or stripped.startswith("["):
        raise HTTPException(status_code=400, detail="Only CSV or TXT files are accepted")

    entries: list[dict] = []
    invalid: list[str] = []
    if "," in "\n".join(text.splitlines()[:50]) or file.filename.lower().endswith(".csv"):
        reader = csv.reader(io.StringIO(text))
        for row in reader:
            if not row or not any(c.strip() for c in row):
                continue
            phone = (row[0] or "").strip()
            label = (row[1] or "").strip() if len(row) > 1 else ""
            if not phone or phone.lower().startswith(("phone", "number", "#")):
                continue  # header
            if PHONE_RE.match(phone):
                entries.append({"phone": phone, "label": label})
            else:
                invalid.append(phone)
    else:
        for line in text.splitlines():
            phone = line.strip()
            if not phone or phone.lower().startswith(("phone", "number", "#")):
                continue
            if PHONE_RE.match(phone):
                entries.append({"phone": phone, "label": ""})
            else:
                invalid.append(phone)

    if not entries:
        raise HTTPException(status_code=400,
                            detail=f"No valid phone numbers found. Invalid: {invalid[:10]}")

    existing = set((await db.execute(
        select(CompanyPhoneNumber.phone).where(CompanyPhoneNumber.user_id == user.id))).scalars())
    added, duplicates = 0, 0
    for e in entries:
        if e["phone"] in existing:
            duplicates += 1
            continue
        db.add(CompanyPhoneNumber(user_id=user.id, phone=e["phone"], label=e["label"]))
        existing.add(e["phone"])
        added += 1
    await db.commit()
    await log_audit(db, user.id, "phone.import", "company_phone", None,
                    {"added": added, "duplicates": duplicates, "invalid": len(invalid)})
    return {"added": added, "duplicates": duplicates,
            "invalid": invalid[:20], "total_valid": len(entries)}


@router.post("/{pid}/patch")
