"""
QA Checksheet & Station-Gating API routes.
"""
from fastapi import APIRouter, Depends, status, HTTPException, UploadFile, File
import os
import logging
import uuid as uuid_mod
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List, Optional
from uuid import UUID

logger = logging.getLogger(__name__)

from app.core.database import get_db
from app.core.security import get_current_user, user_has_permission
from app.models.core_models import LoginUsers
from . import schemas, service

from app.models.qa_models import QaChecksheetInstance
from app.models.station_work_models import QaResponsePhoto
from app.modules.station_work.routes import ensure_station_access

router = APIRouter()


async def verify_qa_checksheet_access(
    user: LoginUsers = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> LoginUsers:
    """
    Allow QA Inspectors, QA Supervisors, and Admins to view QA checksheets.
    Explicitly restrict station staff (operators, production staff without QA permissions).
    """
    role = (user.role_code or "").upper()
    if role in ('ADMIN', 'QA_SUPERVISOR', 'QA_INSPECTOR'):
        return user
    has_perm = await user_has_permission(db, user, 'QA', 'view')
    if has_perm:
        return user
    raise HTTPException(
        status_code=status.HTTP_403_FORBIDDEN,
        detail="Access restricted: Station staff are not permitted to view QA checksheets. QA Inspector or Supervisor access is required."
    )


async def verify_qa_checksheet_edit(
    user: LoginUsers = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> LoginUsers:
    """
    Allow QA Inspectors, QA Supervisors, and Admins to edit/create QA checksheets.
    Explicitly restrict station staff.
    """
    role = (user.role_code or "").upper()
    if role in ('ADMIN', 'QA_SUPERVISOR', 'QA_INSPECTOR'):
        return user
    has_perm = await user_has_permission(db, user, 'QA', 'edit')
    if has_perm:
        return user
    raise HTTPException(
        status_code=status.HTTP_403_FORBIDDEN,
        detail="Access restricted: Station staff cannot modify QA checksheets. QA Inspector or Supervisor access is required."
    )


# ── Dashboard & Analytics ─────────────────────────────────
@router.get("/dashboard", response_model=schemas.QADashboardResponse)
async def get_dashboard(
    db: AsyncSession = Depends(get_db),
    _=Depends(get_current_user),
):
    """QA overview: pending/in_progress/passed/failed inspections per station."""
    return await service.get_qa_dashboard(db)


@router.get("/supervisor-dashboard", response_model=schemas.SupervisorDashboardResponse)
async def get_supervisor_dashboard(
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_access),
):
    """Comprehensive real-time dashboard for QA Supervisors: chassis QA statuses, defect details, and station allocations."""
    return await service.get_supervisor_dashboard(db)


@router.get("/analytics/inspectors", response_model=schemas.InspectorAnalyticsResponse)
async def get_inspector_analytics(
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_access),
):
    """Individual QA inspector performance analytics: total inspected, pass rates, and defect counts by class."""
    return await service.get_inspector_analytics(db)


# ── Templates CRUD ─────────────────────────────────────────
@router.get("/templates", response_model=List[schemas.TemplateOut])
async def list_templates(
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_access),
):
    return await service.list_templates(db)


@router.post("/templates", response_model=schemas.TemplateOut, status_code=status.HTTP_201_CREATED)
async def create_template(
    req: schemas.TemplateCreate,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    return await service.create_template(db, req)


@router.put("/templates/{template_id}", response_model=schemas.TemplateOut)
async def update_template(
    template_id: UUID,
    req: schemas.TemplateUpdate,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    return await service.update_template(db, template_id, req)


@router.delete("/templates/{template_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_template(
    template_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    await service.delete_template(db, template_id)


@router.get("/templates/{template_id}/full", response_model=schemas.TemplateOut)
async def get_template_full(
    template_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_access),
):
    return await service.get_template_full(db, template_id)


# ── Sections CRUD ─────────────────────────────────────────
@router.post("/templates/{template_id}/sections", response_model=schemas.SectionOut, status_code=status.HTTP_201_CREATED)
async def add_section(
    template_id: UUID,
    req: schemas.SectionCreate,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    return await service.add_section(db, template_id, req)


@router.put("/templates/{template_id}/sections/{section_id}", response_model=schemas.SectionOut)
async def update_section(
    template_id: UUID,
    section_id: UUID,
    req: schemas.SectionUpdate,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    return await service.update_section(db, template_id, section_id, req)


@router.delete("/templates/{template_id}/sections/{section_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_section(
    template_id: UUID,
    section_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    await service.delete_section(db, template_id, section_id)


# ── Checkpoint Items CRUD ──────────────────────────────────
@router.post("/templates/{template_id}/sections/{section_id}/items", response_model=schemas.ItemOut, status_code=status.HTTP_201_CREATED)
async def add_item(
    template_id: UUID,
    section_id: UUID,
    req: schemas.ItemCreate,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    return await service.add_item(db, template_id, section_id, req)


@router.put("/templates/{template_id}/sections/{section_id}/items/{item_id}", response_model=schemas.ItemOut)
async def update_item(
    template_id: UUID,
    section_id: UUID,
    item_id: UUID,
    req: schemas.ItemUpdate,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    return await service.update_item(db, template_id, section_id, item_id, req)


@router.delete("/templates/{template_id}/sections/{section_id}/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(
    template_id: UUID,
    section_id: UUID,
    item_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    await service.delete_item(db, template_id, section_id, item_id)


# ── Station ↔ Template Mapping ───────────────────────────
@router.get("/station-mappings", response_model=List[schemas.StationMappingOut])
async def list_station_mappings(
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_access),
):
    return await service.list_station_mappings(db)


@router.post("/station-mappings", response_model=schemas.StationMappingOut, status_code=status.HTTP_201_CREATED)
async def create_station_mapping(
    req: schemas.StationMappingCreate,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    return await service.create_station_mapping(db, req)


@router.put("/station-mappings/{map_id}", response_model=schemas.StationMappingOut)
async def update_station_mapping(
    map_id: UUID,
    req: schemas.StationMappingUpdate,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    return await service.update_station_mapping(db, map_id, req)


@router.delete("/station-mappings/{map_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_station_mapping(
    map_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_edit),
):
    await service.delete_station_mapping(db, map_id)


@router.get("/stations/{station_id}/templates", response_model=List[schemas.StationMappingOut])
async def get_station_templates(
    station_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(verify_qa_checksheet_access),
):
    return await service.get_station_templates(db, station_id)


# ── Inspection Flow ────────────────────────────────────────
@router.post("/inspect/start", response_model=schemas.InspectStartResponse)
async def start_inspection(
    req: schemas.InspectStartRequest,
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    """Scan chassis at station → initialize/retrieve all checksheet instances for mapped templates."""
    try:
        await ensure_station_access(db, user, req.station_id, 'QA')
    except HTTPException:
        raise HTTPException(400, "Chassis has not arrived at your station.")
    return await service.start_inspection(db, req, user.user_id)


@router.get("/instances/{instance_id}", response_model=schemas.InstanceDetailOut)
async def get_instance_detail(
    instance_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(get_current_user),
):
    """Full instance view with sections, items, and current responses."""
    try:
        return await service.get_instance_detail(db, instance_id)
    except HTTPException:
        raise
    except Exception as e:
        logger.exception(f"Unhandled error loading QA instance {instance_id}: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error loading QA checksheet instance: {str(e)}"
        )


@router.post("/instances/{instance_id}/responses/bulk")
async def submit_responses_bulk(
    instance_id: UUID,
    req: schemas.ResponseBulkRequest,
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    """Submit responses for multiple checkpoint items at once."""
    return await service.submit_responses_bulk(db, instance_id, req, user.user_id)


@router.post("/instances/{instance_id}/signoff", response_model=schemas.SignoffResponse)
async def signoff_instance(
    instance_id: UUID,
    req: schemas.SignoffRequest,
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    """
    Sign off on an inspection instance.
    If result is PASSED and all mandatory templates for this station are PASSED,
    triggers automated inventory deduction for this station's BOM components.
    """
    return await service.signoff_instance(db, instance_id, req, user.user_id)


@router.post("/stations/{station_id}/chassis/{chassis_id}/clear-out", response_model=schemas.ClearanceForChassisOutResponse)
async def grant_qa_clearance_for_chassis_out(
    station_id: UUID,
    chassis_id: UUID,
    req: Optional[schemas.ClearanceForChassisOutRequest] = None,
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    """Grant QA clearance for Chassis Out after completing all station checklist items."""
    remarks = req.remarks if req else None
    return await service.grant_qa_clearance_for_chassis_out(db, station_id, chassis_id, user.user_id, remarks)


@router.get("/chassis/{chassis_no}/history", response_model=List[schemas.ChassisQAHistoryItem])
async def get_chassis_history(
    chassis_no: str,
    db: AsyncSession = Depends(get_db),
    _=Depends(get_current_user),
):
    """Full QA inspection audit trail across all stations for a chassis."""
    return await service.get_chassis_qa_history(db, chassis_no)


# ── Shortage Tracking ─────────────────────────────────────
@router.get("/shortage/{chassis_no}/{station_id}", response_model=List[schemas.ShortageOut])
async def get_shortages(
    chassis_no: str,
    station_id: UUID,
    db: AsyncSession = Depends(get_db),
    _=Depends(get_current_user),
):
    """Get list of shortages for a chassis at a station."""
    return await service.get_shortages(db, chassis_no, station_id)


@router.post("/shortage", response_model=schemas.ShortageOut, status_code=status.HTTP_201_CREATED)
async def create_shortage(
    req: schemas.ShortageCreate,
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    """Log a part shortage."""
    return await service.create_shortage(db, req, user.user_id)


@router.put("/shortage/{shortage_id}", response_model=schemas.ShortageOut)
async def update_shortage(
    shortage_id: UUID,
    req: schemas.ShortageUpdate,
    db: AsyncSession = Depends(get_db),
    _=Depends(get_current_user),
):
    """Update fitted quantity or remarks on an existing shortage."""
    return await service.update_shortage(db, shortage_id, req)


@router.put("/shortage/{shortage_id}/resolve", response_model=schemas.ShortageOut)
async def resolve_shortage(
    shortage_id: UUID,
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    """Mark a part shortage as resolved."""
    return await service.resolve_shortage(db, shortage_id, user.user_id)


# ── Checkpoint photos ─────────────────────────────────────
QA_UPLOAD_DIR = os.path.join('uploads', 'qa')
ALLOWED_PHOTO_TYPES = {'image/jpeg', 'image/png', 'image/webp', 'image/heic', 'image/heif'}


@router.post("/instances/{instance_id}/items/{item_id}/photos", response_model=schemas.ResponsePhotoOut, status_code=status.HTTP_201_CREATED)
async def upload_checkpoint_photo(
    instance_id: UUID,
    item_id: UUID,
    file: UploadFile = File(...),
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    """Attach a photo to one checkpoint of an inspection."""
    inst = await db.get(QaChecksheetInstance, instance_id)
    if not inst:
        raise HTTPException(404, "Inspection not found")
    await ensure_station_access(db, user, inst.station_id, 'QA')
    if file.content_type not in ALLOWED_PHOTO_TYPES:
        raise HTTPException(400, "Only photos (JPEG, PNG, WebP or HEIC) can be attached")
    contents = await file.read()
    if len(contents) > 15 * 1024 * 1024:
        raise HTTPException(400, "Photo is larger than 15 MB")
    folder = os.path.join(QA_UPLOAD_DIR, str(instance_id))
    os.makedirs(folder, exist_ok=True)
    ext = os.path.splitext(file.filename or '')[1].lower() or '.jpg'
    fname = f"{item_id.hex[:8]}_{uuid_mod.uuid4().hex[:8]}{ext}"
    with open(os.path.join(folder, fname), 'wb') as fh:
        fh.write(contents)
    photo = QaResponsePhoto(instance_id=instance_id, item_id=item_id,
                            photo_url=f"/uploads/qa/{instance_id}/{fname}", uploaded_by=user.user_id)
    db.add(photo)
    await db.commit()
    await db.refresh(photo)
    return schemas.ResponsePhotoOut(photo_id=photo.photo_id, photo_url=photo.photo_url, uploaded_at=photo.uploaded_at)


@router.delete("/photos/{photo_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_checkpoint_photo(
    photo_id: UUID,
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    photo = await db.get(QaResponsePhoto, photo_id)
    if not photo:
        raise HTTPException(404, "Photo not found")
    inst = await db.get(QaChecksheetInstance, photo.instance_id)
    if inst:
        await ensure_station_access(db, user, inst.station_id, 'QA')
    await db.delete(photo)
    await db.commit()


@router.put("/instances/{instance_id}/remarks")
async def save_instance_remarks(
    instance_id: UUID,
    req: schemas.InstanceRemarksIn,
    db: AsyncSession = Depends(get_db),
    user: LoginUsers = Depends(get_current_user),
):
    """Remarks on the whole checksheet and on each section."""
    inst = await db.get(QaChecksheetInstance, instance_id)
    if not inst:
        raise HTTPException(404, "Inspection not found")
    await ensure_station_access(db, user, inst.station_id, 'QA')
    return await service.save_instance_remarks(db, instance_id, req, user.user_id)


# ── Reference Diagram / Blueprint Upload ───────────────────
DIAGRAM_UPLOAD_DIR = os.path.join("uploads", "qa_diagrams")
ALLOWED_DIAGRAM_EXTS = {".jpg", ".jpeg", ".png", ".webp", ".svg"}

@router.post("/diagrams/upload")
async def upload_qa_diagram(
    file: UploadFile = File(...),
    user: LoginUsers = Depends(get_current_user),
):
    """Upload a reference schematic or diagram for checkpoints."""
    os.makedirs(DIAGRAM_UPLOAD_DIR, exist_ok=True)
    ext = os.path.splitext(file.filename or "")[1].lower()
    if ext not in ALLOWED_DIAGRAM_EXTS:
        raise HTTPException(400, "Only images or SVGs (PNG, JPG, WebP, SVG) can be attached as diagrams")
    contents = await file.read()
    if len(contents) > 15 * 1024 * 1024:
        raise HTTPException(400, "Diagram exceeds 15 MB")
    
    clean_base = "".join(c for c in os.path.splitext(file.filename or "diagram")[0] if c.isalnum() or c in ("-", "_")).strip() or "diagram"
    fname = f"{clean_base}_{uuid_mod.uuid4().hex[:6]}{ext}"
    with open(os.path.join(DIAGRAM_UPLOAD_DIR, fname), "wb") as fh:
        fh.write(contents)
    
    return {"diagram_url": f"/uploads/qa_diagrams/{fname}", "filename": fname}

