"""
Office Router — Lawyer Virtual Office
Fully fixed: uses same get_lawyer_for_user() as dashboard so email matching is not required.
"""
from fastapi import APIRouter, Depends, Request, Form, HTTPException, UploadFile, File
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from pathlib import Path
from typing import Optional
import os

from ..models.models import Case, Appointment, User
from ..models.fyp2_models import CaseMessage, CaseDocument, DraftedPetition, LawyerNote, CourtFiling
from ..services.database import get_db
from ..services.auth_service import require_lawyer
from ..services.lawyer_service import get_lawyer_for_user
from ..services.ocr_service import extract_text
from ..services.petition_service import draft_petition, get_petition_versions, PETITION_TYPES
from ..services.filing_service import file_case_in_court, get_filings_for_case, generate_filing_package_text, COURT_TYPES, DISTRICTS
from ..services.notification_service import notify_court_filed

router = APIRouter()
BASE_DIR = Path(__file__).resolve().parent.parent.parent
templates = Jinja2Templates(directory=str(BASE_DIR / "frontend" / "templates"))
UPLOADS_DIR = BASE_DIR / "uploads"
UPLOADS_DIR.mkdir(exist_ok=True)


def require_case_access(db: Session, user: User, case_id: int) -> Case:
    """
    Return the case only if it is linked to this lawyer via an appointment.
    Raises 404 if the case doesn't exist, 403 if it belongs to another lawyer.
    """
    case = db.query(Case).filter(Case.id == case_id).first()
    if not case:
        raise HTTPException(status_code=404, detail="Case not found")
    lawyer = get_lawyer_for_user(db, user)
    linked = lawyer and db.query(Appointment).filter(
        Appointment.case_id == case_id,
        Appointment.lawyer_id == lawyer.id,
    ).first()
    if not linked:
        raise HTTPException(status_code=403, detail="This case is not linked to you")
    return case


# ── Virtual Office Dashboard ──────────────────────────────────────────────────

@router.get("/office", response_class=HTMLResponse)
async def lawyer_office(request: Request, user=Depends(require_lawyer), db: Session = Depends(get_db)):
    lawyer = get_lawyer_for_user(db, user)
    appointments = []
    cases = []
    if lawyer:
        appointments = db.query(Appointment).filter(
            Appointment.lawyer_id == lawyer.id
        ).order_by(Appointment.created_at.desc()).all()
        # Get unique cases linked to appointments
        case_ids = list({a.case_id for a in appointments if a.case_id})
        cases = db.query(Case).filter(Case.id.in_(case_ids)).all() if case_ids else []
        # Enrich cases with client name
        for case in cases:
            client = db.query(User).filter(User.id == case.client_id).first()
            case.client_name = client.full_name if client else f"Client #{case.client_id}"
    return templates.TemplateResponse("lawyer/office.html", {
        "request": request, "user": user, "lawyer": lawyer,
        "appointments": appointments, "cases": cases,
    })


# ── Case Workspace ────────────────────────────────────────────────────────────

@router.get("/office/case/{case_id}", response_class=HTMLResponse)
async def office_case_detail(case_id: int, request: Request, user=Depends(require_lawyer), db: Session = Depends(get_db)):
    case = require_case_access(db, user, case_id)
    messages  = db.query(CaseMessage).filter(CaseMessage.case_id == case_id).order_by(CaseMessage.sent_at.asc()).all()
    documents = db.query(CaseDocument).filter(CaseDocument.case_id == case_id).order_by(CaseDocument.uploaded_at.desc()).all()
    petitions = get_petition_versions(db, case_id)
    notes     = db.query(LawyerNote).filter(LawyerNote.case_id == case_id).order_by(LawyerNote.created_at.desc()).all()
    filings   = get_filings_for_case(db, case_id)
    client    = db.query(User).filter(User.id == case.client_id).first()
    return templates.TemplateResponse("lawyer/case_workspace.html", {
        "request": request, "user": user, "case": case, "client": client,
        "messages": messages, "documents": documents, "petitions": petitions,
        "notes": notes, "filings": filings,
        "petition_types": PETITION_TYPES, "court_types": COURT_TYPES, "districts": DISTRICTS,
    })


# ── Messaging ─────────────────────────────────────────────────────────────────

@router.post("/office/case/{case_id}/message")
async def send_message(case_id: int, content: str = Form(...), user=Depends(require_lawyer), db: Session = Depends(get_db)):
    require_case_access(db, user, case_id)
    msg = CaseMessage(case_id=case_id, sender_id=user.id, sender_role="lawyer", content=content.strip())
    db.add(msg); db.commit()
    return RedirectResponse(url=f"/lawyer/office/case/{case_id}", status_code=303)


# ── Notes ─────────────────────────────────────────────────────────────────────

@router.post("/office/case/{case_id}/note")
async def add_note(case_id: int, content: str = Form(...), user=Depends(require_lawyer), db: Session = Depends(get_db)):
    require_case_access(db, user, case_id)
    note = LawyerNote(case_id=case_id, lawyer_id=user.id, content=content.strip())
    db.add(note); db.commit()
    return RedirectResponse(url=f"/lawyer/office/case/{case_id}", status_code=303)


# ── Document Upload ───────────────────────────────────────────────────────────

ALLOWED_UPLOAD_EXTENSIONS = {".pdf", ".jpg", ".jpeg", ".png", ".bmp", ".tiff", ".tif",
                             ".webp", ".doc", ".docx", ".txt"}
MAX_UPLOAD_MB = 20


@router.post("/office/case/{case_id}/upload")
async def upload_document(case_id: int, doc_type: str = Form(""), file: UploadFile = File(...), user=Depends(require_lawyer), db: Session = Depends(get_db)):
    require_case_access(db, user, case_id)

    # Sanitize the filename — keep only the basename so a crafted name
    # like "..\..\x.py" can't escape the uploads directory
    safe_name = Path(file.filename or "document").name
    if not safe_name or safe_name in (".", ".."):
        raise HTTPException(status_code=400, detail="Invalid filename")
    if Path(safe_name).suffix.lower() not in ALLOWED_UPLOAD_EXTENSIONS:
        raise HTTPException(status_code=400, detail="File type not allowed")

    case_dir = UPLOADS_DIR / f"case_{case_id}"
    case_dir.mkdir(exist_ok=True)
    dest = case_dir / safe_name
    size = 0
    with open(dest, "wb") as f:
        while chunk := file.file.read(1024 * 1024):
            size += len(chunk)
            if size > MAX_UPLOAD_MB * 1024 * 1024:
                f.close()
                os.remove(dest)
                raise HTTPException(status_code=413, detail=f"File exceeds {MAX_UPLOAD_MB} MB limit")
            f.write(chunk)

    # Extract text (PDF text layer or OCR) — returns "" if deps are missing
    ocr_text = extract_text(str(dest))

    doc = CaseDocument(case_id=case_id, uploaded_by_id=user.id, uploader_role="lawyer",
                       filename=safe_name, file_path=str(dest), doc_type=doc_type or "Document",
                       ocr_text=ocr_text or None, file_size_kb=round(size / 1024, 1))
    db.add(doc); db.commit()
    return RedirectResponse(url=f"/lawyer/office/case/{case_id}", status_code=303)


# ── AI Petition Drafting ──────────────────────────────────────────────────────

@router.post("/office/case/{case_id}/draft-petition")
async def draft_petition_route(case_id: int, petition_type: str = Form("Civil Suit"),
                                additional_instructions: str = Form(""), user=Depends(require_lawyer), db: Session = Depends(get_db)):
    require_case_access(db, user, case_id)
    draft_petition(db=db, case_id=case_id, lawyer_id=user.id,
                   petition_type=petition_type, additional_instructions=additional_instructions)
    return RedirectResponse(url=f"/lawyer/office/case/{case_id}", status_code=303)


@router.post("/office/case/{case_id}/petition/{petition_id}/update")
async def update_petition(case_id: int, petition_id: int, content: str = Form(...), user=Depends(require_lawyer), db: Session = Depends(get_db)):
    require_case_access(db, user, case_id)
    petition = db.query(DraftedPetition).filter(DraftedPetition.id == petition_id, DraftedPetition.case_id == case_id).first()
    if petition:
        petition.content = content; db.commit()
    return RedirectResponse(url=f"/lawyer/office/case/{case_id}", status_code=303)


# ── Court Filing ──────────────────────────────────────────────────────────────

@router.post("/office/case/{case_id}/file-in-court")
async def file_in_court(case_id: int, court_type: str = Form(...), court_district: str = Form(...),
                         petition_id: Optional[int] = Form(default=None), court_notes: str = Form(""),
                         user=Depends(require_lawyer), db: Session = Depends(get_db)):
    case = require_case_access(db, user, case_id)
    filing = file_case_in_court(db=db, case_id=case_id, lawyer_id=user.id, court_type=court_type,
                                 court_district=court_district, petition_id=petition_id or None, court_notes=court_notes)
    notify_court_filed(db, case.client_id, filing.filing_number, court_type, case_id)
    return RedirectResponse(url=f"/lawyer/office/case/{case_id}", status_code=303)


@router.get("/office/case/{case_id}/filing-package", response_class=HTMLResponse)
async def view_filing_package(case_id: int, request: Request, user=Depends(require_lawyer), db: Session = Depends(get_db)):
    case = require_case_access(db, user, case_id)
    filing = db.query(CourtFiling).filter(CourtFiling.case_id == case_id).order_by(CourtFiling.filing_date.desc()).first()
    if not filing:
        raise HTTPException(status_code=404, detail="No filing found for this case")
    petition = db.query(DraftedPetition).filter(DraftedPetition.id == filing.petition_id).first() if filing.petition_id else None
    package_text = generate_filing_package_text(filing, case, petition)
    return templates.TemplateResponse("lawyer/filing_package.html", {
        "request": request, "user": user, "filing": filing, "case": case, "package_text": package_text,
    })
