"""RBS REGAL — Terms & Conditions Templates Master.

Central CRUD for reusable invoice T&C templates. Each invoice can pick
one of these templates at billing time; the chosen text gets printed
on the PDF and stored on the invoice row (terms_text field already exists).

Endpoints (mounted under /api/terms-templates):
    GET    /          — list templates (filterable by category)
    POST   /          — create a template
    PUT    /{id}      — edit a template
    DELETE /{id}      — delete (soft archive if used)
    POST   /{id}/clone — duplicate as a new draft
"""
from __future__ import annotations

from datetime import datetime, timezone
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Request
from pydantic import BaseModel, Field

from auth import get_current_user
from bson import ObjectId

router = APIRouter(prefix="/api/terms-templates", tags=["terms-templates"])

CATEGORIES = ["sales", "purchase", "quotation", "gst", "wholesale", "service", "delivery", "other"]

DEFAULT_TEMPLATES = [
    {
        "name": "Sales Invoice — Standard",
        "category": "sales",
        "body": "1. Goods once sold will not be taken back.\n2. Interest @ 18% p.a. will be charged on overdue bills.\n3. Subject to local jurisdiction.\n4. E. & O.E.",
        "is_default": True,
        "is_locked": False,
    },
    {
        "name": "Purchase Invoice — Standard",
        "category": "purchase",
        "body": "1. Payment within 30 days of invoice date.\n2. All disputes subject to local jurisdiction.\n3. Goods received in good condition.",
        "is_default": True,
        "is_locked": False,
    },
    {
        "name": "Quotation — Standard",
        "category": "quotation",
        "body": "1. This quotation is valid for 15 days.\n2. Prices are subject to change without notice.\n3. GST extra as applicable.\n4. Delivery within 7-10 working days from receipt of confirmed order.",
        "is_default": True,
        "is_locked": False,
    },
    {
        "name": "GST Invoice — Detailed",
        "category": "gst",
        "body": "1. Subject to GST as applicable.\n2. Reverse charge mechanism: NO.\n3. E-way bill generated where required.\n4. ITC eligible as per GST law.\n5. Subject to jurisdiction of local courts.",
        "is_default": False,
        "is_locked": False,
    },
    {
        "name": "Wholesale — Bulk",
        "category": "wholesale",
        "body": "1. Bulk discount as per agreement.\n2. Payment in advance / against delivery.\n3. Goods sold as inspected.\n4. No claims after 24 hours of delivery.\n5. Transport at buyer's risk.",
        "is_default": False,
        "is_locked": False,
    },
]


class TemplateIn(BaseModel):
    name: str
    category: str = "sales"
    body: str
    is_default: bool = False
    company_id: Optional[str] = None  # null = global to all companies of this account
    notes: Optional[str] = ""


class TemplateUpdate(BaseModel):
    name: Optional[str] = None
    category: Optional[str] = None
    body: Optional[str] = None
    is_default: Optional[bool] = None
    notes: Optional[str] = None


def _ser(d: dict) -> dict:
    d = dict(d)
    d["id"] = str(d.pop("_id"))
    return d


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


async def _seed_defaults(db, user_email: str):
    """Insert default templates once per user if they have none yet."""
    count = await db.terms_templates.count_documents({"created_by": user_email})
    if count > 0:
        return
    docs = []
    for d in DEFAULT_TEMPLATES:
        docs.append({**d,
                     "created_by": user_email,
                     "created_at": _now(),
                     "updated_at": _now(),
                     "usage_count": 0,
                     "is_archived": False})
    if docs:
        await db.terms_templates.insert_many(docs)


@router.get("")
async def list_templates(request: Request, category: str | None = None, company_id: str | None = None, user=Depends(get_current_user)):
    db = request.app.state.db
    email = user.get("email", "")
    await _seed_defaults(db, email)
    q: dict = {"created_by": email, "is_archived": {"$ne": True}}
    if category:
        q["category"] = category
    if company_id:
        # Either company-scoped OR global (null company_id)
        q["$or"] = [{"company_id": company_id}, {"company_id": None}, {"company_id": {"$exists": False}}]
    docs = await db.terms_templates.find(q).sort([("category", 1), ("is_default", -1), ("name", 1)]).to_list(500)
    return [_ser(d) for d in docs]


@router.get("/categories")
async def categories():
    return CATEGORIES


@router.post("")
async def create_template(payload: TemplateIn, request: Request, user=Depends(get_current_user)):
    if payload.category not in CATEGORIES:
        raise HTTPException(status_code=400, detail="Unknown category")
    db = request.app.state.db
    doc = payload.model_dump()
    doc["created_by"] = user.get("email", "")
    doc["created_at"] = _now()
    doc["updated_at"] = _now()
    doc["usage_count"] = 0
    doc["is_archived"] = False
    doc["is_locked"] = False
    if payload.is_default:
        await db.terms_templates.update_many(
            {"created_by": user.get("email", ""), "category": payload.category},
            {"$set": {"is_default": False}},
        )
    res = await db.terms_templates.insert_one(doc)
    return _ser(await db.terms_templates.find_one({"_id": res.inserted_id}))


@router.put("/{tid}")
async def update_template(tid: str, payload: TemplateUpdate, request: Request, user=Depends(get_current_user)):
    db = request.app.state.db
    try:
        oid = ObjectId(tid)
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid id")
    existing = await db.terms_templates.find_one({"_id": oid, "created_by": user.get("email", "")})
    if not existing:
        raise HTTPException(status_code=404, detail="Template not found")
    patch = {k: v for k, v in payload.model_dump(exclude_none=True).items()}
    patch["updated_at"] = _now()
    if payload.is_default:
        await db.terms_templates.update_many(
            {"created_by": user.get("email", ""), "category": existing["category"]},
            {"$set": {"is_default": False}},
        )
    await db.terms_templates.update_one({"_id": oid}, {"$set": patch})
    return _ser(await db.terms_templates.find_one({"_id": oid}))


@router.delete("/{tid}")
async def delete_template(tid: str, request: Request, user=Depends(get_current_user)):
    db = request.app.state.db
    try:
        oid = ObjectId(tid)
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid id")
    existing = await db.terms_templates.find_one({"_id": oid, "created_by": user.get("email", "")})
    if not existing:
        raise HTTPException(status_code=404, detail="Template not found")
    if (existing.get("usage_count") or 0) > 0:
        await db.terms_templates.update_one({"_id": oid}, {"$set": {"is_archived": True, "updated_at": _now()}})
        return {"deleted": False, "archived": True}
    await db.terms_templates.delete_one({"_id": oid})
    return {"deleted": True, "archived": False}


@router.post("/{tid}/clone")
async def clone_template(tid: str, request: Request, user=Depends(get_current_user)):
    db = request.app.state.db
    try:
        oid = ObjectId(tid)
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid id")
    src = await db.terms_templates.find_one({"_id": oid, "created_by": user.get("email", "")})
    if not src:
        raise HTTPException(status_code=404, detail="Template not found")
    src.pop("_id", None)
    src["name"] = f"{src.get('name', '')} (Copy)"
    src["created_at"] = _now()
    src["updated_at"] = _now()
    src["usage_count"] = 0
    src["is_default"] = False
    res = await db.terms_templates.insert_one(src)
    return _ser(await db.terms_templates.find_one({"_id": res.inserted_id}))


@router.post("/{tid}/touch-usage")
async def touch_usage(tid: str, request: Request, user=Depends(get_current_user)):
    """Increment usage_count when an invoice uses this template."""
    db = request.app.state.db
    try:
        oid = ObjectId(tid)
    except Exception:
        return {"ok": False}
    await db.terms_templates.update_one({"_id": oid}, {"$inc": {"usage_count": 1}})
    return {"ok": True}
