from __future__ import annotations
import uuid
import io
import base64
import socket
from datetime import datetime, date
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from sqlalchemy import or_
from pydantic import BaseModel
from typing import Optional, List
from app.database import get_db
from app.models.passport import (
    PlantPassport, PassportTimelineEvent, PassportPhoto,
    PassportScanLog, PassportCustomerView,
)
from app.models.production import ProductionBatch, SeedLot, GerminationRecord, TransplantRecord
from app.models.plant import Plant, PlantVariety, PlantCategory
from app.models.supplier import Supplier
from app.models.employee import Employee
from app.models.treatment import Treatment, TreatmentDetail, HealthRecord, DiseasePestRecord
from app.models.sale import Sale, SaleItem
from app.models.customer import Customer
from app.models.branch import Branch
from app.services.auth import get_current_user

router = APIRouter(prefix="/passports", tags=["passports"])


def _get_server_host() -> str:
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "localhost"


def _generate_passport_id(db: Session) -> str:
    year = datetime.now().year
    last = db.query(PlantPassport).filter(
        PlantPassport.passport_id.like(f"CHR-PLT-{year}-%")
    ).order_by(PlantPassport.passport_id.desc()).first()
    if last:
        seq = int(last.passport_id.split("-")[-1]) + 1
    else:
        seq = 1
    return f"CHR-PLT-{year}-{seq:06d}"


def _generate_barcode(passport_id: str) -> str:
    return passport_id.replace("-", "")


def _generate_qr_base64(data: str) -> str:
    import qrcode
    qr = qrcode.QRCode(version=2, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=8, border=2)
    qr.add_data(data)
    qr.make(fit=True)
    img = qr.make_image(fill_color="#166534", back_color="white")
    buf = io.BytesIO()
    img.save(buf, format="PNG")
    return base64.b64encode(buf.getvalue()).decode()


def _build_passport_from_batch(batch, db: Session, qr_base64: str = None, scan_url: str = None) -> dict:
    plant = db.query(Plant).filter(Plant.id == batch.plant_id).first() if batch.plant_id else None
    variety = db.query(PlantVariety).filter(PlantVariety.id == plant.variety_id).first() if plant and plant.variety_id else None
    category = db.query(PlantCategory).filter(PlantCategory.id == plant.category_id).first() if plant and plant.category_id else None
    seed_lot = db.query(SeedLot).filter(SeedLot.id == batch.seed_lot_id).first() if batch.seed_lot_id else None
    supplier = db.query(Supplier).filter(Supplier.id == seed_lot.supplier_id).first() if seed_lot and seed_lot.supplier_id else None

    germination = db.query(GerminationRecord).filter(GerminationRecord.batch_id == batch.id).order_by(GerminationRecord.date).all()
    transplants = db.query(TransplantRecord).filter(TransplantRecord.batch_id == batch.id).order_by(TransplantRecord.date).all()
    treatments = db.query(Treatment).filter(Treatment.batch_id == batch.id).order_by(Treatment.treatment_date).all()
    health_records = db.query(HealthRecord).filter(HealthRecord.batch_id == batch.id).order_by(HealthRecord.record_date).all()
    diseases = db.query(DiseasePestRecord).filter(DiseasePestRecord.batch_id == batch.id).order_by(DiseasePestRecord.record_date).all()

    germination_date = None
    germination_rate = None
    if germination:
        germination_date = germination[-1].date
        germination_rate = germination[-1].success_rate

    transplant_date = None
    if transplants:
        transplant_date = transplants[-1].date

    latest_health = health_records[-1] if health_records else None

    timeline = []
    timeline.append({
        "date": batch.sowing_date.isoformat(),
        "event_type": "sowing",
        "event_title": "Seed Sowing",
        "event_details": f"{batch.sown_quantity} seeds planted",
        "icon": "seed",
    })
    if seed_lot and seed_lot.purchase_date:
        timeline.append({
            "date": seed_lot.purchase_date.isoformat(),
            "event_type": "purchase",
            "event_title": "Seed Purchase",
            "event_details": f"Lot: {seed_lot.lot_number}",
            "icon": "purchase",
        })
    for g in germination:
        timeline.append({
            "date": g.date.isoformat(),
            "event_type": "germination",
            "event_title": "Germination Check",
            "event_details": f"{g.germinated_quantity} germinated ({g.success_rate}%)",
            "icon": "germination",
        })
    for t in transplants:
        timeline.append({
            "date": t.date.isoformat(),
            "event_type": "transplant",
            "event_title": "Transplant",
            "event_details": f"{t.from_container} → {t.to_container} ({t.quantity})",
            "icon": "transplant",
        })
    for tr in treatments:
        detail_data = None
        detail_obj = db.query(TreatmentDetail).filter(TreatmentDetail.treatment_id == tr.id).first()
        if detail_obj:
            detail_data = {k: v for k, v in detail_obj.__dict__.items()
                           if v is not None and k not in ('_sa_instance_state', 'id', 'treatment_id')}
        timeline.append({
            "date": tr.treatment_date.isoformat(),
            "event_type": "treatment",
            "event_title": tr.treatment_type.replace('_', ' ').title(),
            "event_details": tr.notes or str(detail_data) if detail_data else "",
            "icon": "treatment",
        })
    for h in health_records:
        timeline.append({
            "date": h.record_date.isoformat(),
            "event_type": "health_check",
            "event_title": "Health Check",
            "event_details": f"Score: {h.health_score}/100" if h.health_score else "",
            "icon": "health",
        })
    for d in diseases:
        timeline.append({
            "date": d.record_date.isoformat(),
            "event_type": "disease",
            "event_title": f"{d.type.title()}: {d.name}",
            "event_details": f"Severity: {d.severity} ({d.status})",
            "icon": "disease",
        })

    timeline.sort(key=lambda x: x["date"])

    return {
        "batch_id": batch.id,
        "batch_number": batch.batch_number,
        "status": batch.status,
        "sowing_date": batch.sowing_date.isoformat() if batch.sowing_date else None,
        "expected_ready_date": batch.expected_ready_date.isoformat() if batch.expected_ready_date else None,
        "sown_quantity": batch.sown_quantity,
        "current_quantity": batch.current_quantity,
        "tray_number": batch.tray_number,
        "location": batch.location,
        "plant_name": plant.name if plant else None,
        "plant_scientific": plant.scientific_name if plant else None,
        "variety_name": variety.name if variety else None,
        "category_name": category.name if category else None,
        "seed_lot_number": seed_lot.lot_number if seed_lot else None,
        "seed_supplier": supplier.name if supplier else None,
        "employee_name": None,
        "germination_records": [{"date": g.date.isoformat(), "quantity": g.germinated_quantity, "rate": g.success_rate} for g in germination],
        "transplant_records": [{"date": t.date.isoformat(), "from": t.from_container, "to": t.to_container, "quantity": t.quantity} for t in transplants],
        "treatments": [{"number": t.treatment_number, "type": t.treatment_type, "date": t.treatment_date.isoformat(), "status": t.status} for t in treatments],
        "health_records": [{"date": h.record_date.isoformat(), "score": h.health_score, "height": h.plant_height_cm, "mortality": h.mortality_rate} for h in health_records],
        "disease_pest_records": [{"date": d.record_date.isoformat(), "name": d.name, "type": d.type, "severity": d.severity, "status": d.status} for d in diseases],
        "timeline": timeline,
        "production_cost": plant.retail_price * 0.45 if plant else 0,
        "selling_price": plant.retail_price if plant else 0,
        "wholesale_price": plant.wholesale_price if plant else 0,
        "germination_date": germination_date.isoformat() if germination_date else None,
        "germination_rate": germination_rate,
        "transplant_date": transplant_date.isoformat() if transplant_date else None,
        "health_score": latest_health.health_score if latest_health else None,
        "plant_height_cm": latest_health.plant_height_cm if latest_health else None,
        "leaf_color": latest_health.plant_color if latest_health else None,
        "root_condition": latest_health.root_status if latest_health else None,
    }


# --- Pydantic Schemas ---

class PassportCreate(BaseModel):
    batch_id: str
    branch_id: Optional[str] = None
    nursery_zone: Optional[str] = None
    greenhouse: Optional[str] = None
    bed_number: Optional[str] = None
    pot_number: Optional[str] = None
    warehouse_location: Optional[str] = None
    production_cost: Optional[float] = None
    selling_price: Optional[float] = None
    wholesale_price: Optional[float] = None

class PassportUpdate(BaseModel):
    branch_id: Optional[str] = None
    nursery_zone: Optional[str] = None
    greenhouse: Optional[str] = None
    bed_number: Optional[str] = None
    tray_number: Optional[str] = None
    pot_number: Optional[str] = None
    warehouse_location: Optional[str] = None
    location: Optional[str] = None
    production_cost: Optional[float] = None
    selling_price: Optional[float] = None
    wholesale_price: Optional[float] = None
    discount_price: Optional[float] = None
    health_status: Optional[str] = None
    health_score: Optional[float] = None
    leaf_color: Optional[str] = None
    plant_height_cm: Optional[float] = None
    root_condition: Optional[str] = None
    stem_thickness_mm: Optional[float] = None
    disease_status: Optional[str] = None
    pest_status: Optional[str] = None
    mortality_risk: Optional[str] = None
    current_growth_stage: Optional[str] = None
    is_active: Optional[bool] = None

class PassportOut(BaseModel):
    id: str
    passport_id: str
    batch_id: str
    plant_id: str
    variety_id: Optional[str] = None
    category_id: Optional[str] = None
    branch_id: Optional[str] = None
    plant_name: Optional[str] = None
    scientific_name: Optional[str] = None
    local_name: Optional[str] = None
    variety_name: Optional[str] = None
    category_name: Optional[str] = None
    batch_number: Optional[str] = None
    seed_lot_number: Optional[str] = None
    seed_supplier: Optional[str] = None
    sowing_date: Optional[date] = None
    germination_date: Optional[date] = None
    germination_rate: Optional[float] = None
    transplant_date: Optional[date] = None
    current_growth_stage: str
    expected_ready_date: Optional[date] = None
    ready_for_sale_date: Optional[date] = None
    current_stock: int
    nursery_zone: Optional[str] = None
    greenhouse: Optional[str] = None
    bed_number: Optional[str] = None
    tray_number: Optional[str] = None
    pot_number: Optional[str] = None
    warehouse_location: Optional[str] = None
    location: Optional[str] = None
    production_cost: float
    selling_price: float
    wholesale_price: float
    discount_price: float
    profit_margin: float
    health_status: str
    health_score: Optional[float] = None
    leaf_color: Optional[str] = None
    plant_height_cm: Optional[float] = None
    root_condition: Optional[str] = None
    stem_thickness_mm: Optional[float] = None
    disease_status: Optional[str] = None
    pest_status: Optional[str] = None
    mortality_risk: str
    qr_code: Optional[str] = None
    barcode: Optional[str] = None
    scan_url: Optional[str] = None
    is_active: bool
    created_at: datetime
    updated_at: datetime
    model_config = {"from_attributes": True}

class TimelineEventOut(BaseModel):
    id: str
    passport_id: str
    event_date: date
    event_type: str
    event_title: str
    event_details: Optional[str] = None
    icon: Optional[str] = None
    photo_url: Optional[str] = None
    created_at: datetime
    model_config = {"from_attributes": True}

class TimelineEventCreate(BaseModel):
    event_date: date
    event_type: str
    event_title: str
    event_details: Optional[str] = None
    icon: Optional[str] = None
    photo_url: Optional[str] = None

class PhotoOut(BaseModel):
    id: str
    passport_id: str
    growth_stage: str
    photo_url: str
    caption: Optional[str] = None
    taken_date: Optional[date] = None
    created_at: datetime
    model_config = {"from_attributes": True}

class PhotoCreate(BaseModel):
    growth_stage: str
    photo_url: str
    caption: Optional[str] = None
    taken_date: Optional[date] = None

class CustomerViewCreate(BaseModel):
    customer_id: Optional[str] = None
    sale_id: Optional[str] = None
    sale_date: Optional[date] = None
    invoice_number: Optional[str] = None
    delivery_status: Optional[str] = "pending"
    warranty_expiry: Optional[date] = None

class CustomerViewOut(BaseModel):
    id: str
    passport_id: str
    customer_id: Optional[str] = None
    sale_id: Optional[str] = None
    sale_date: Optional[date] = None
    invoice_number: Optional[str] = None
    delivery_status: str
    warranty_expiry: Optional[date] = None
    created_at: datetime
    model_config = {"from_attributes": True}


# --- Endpoints ---

@router.get("", response_model=list[PassportOut])
def list_passports(
    search: Optional[str] = None,
    status: Optional[str] = None,
    branch_id: Optional[str] = None,
    plant_id: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(PlantPassport).filter(PlantPassport.is_active == True)
    if search:
        q = q.filter(or_(
            PlantPassport.passport_id.ilike(f"%{search}%"),
            PlantPassport.batch_number.ilike(f"%{search}%"),
            PlantPassport.plant_name.ilike(f"%{search}%"),
            PlantPassport.barcode.ilike(f"%{search}%"),
        ))
    if status:
        q = q.filter(PlantPassport.current_growth_stage == status)
    if branch_id:
        q = q.filter(PlantPassport.branch_id == branch_id)
    if plant_id:
        q = q.filter(PlantPassport.plant_id == plant_id)
    return q.order_by(PlantPassport.created_at.desc()).all()


@router.post("", response_model=PassportOut, status_code=201)
def create_passport(data: PassportCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    batch = db.query(ProductionBatch).filter(ProductionBatch.id == data.batch_id).first()
    if not batch:
        raise HTTPException(status_code=404, detail="Batch not found")

    existing = db.query(PlantPassport).filter(PlantPassport.batch_id == data.batch_id).first()
    if existing:
        raise HTTPException(status_code=400, detail="Passport already exists for this batch")

    plant = db.query(Plant).filter(Plant.id == batch.plant_id).first() if batch.plant_id else None
    variety = db.query(PlantVariety).filter(PlantVariety.id == plant.variety_id).first() if plant and plant.variety_id else None
    category = db.query(PlantCategory).filter(PlantCategory.id == plant.category_id).first() if plant and plant.category_id else None
    seed_lot = db.query(SeedLot).filter(SeedLot.id == batch.seed_lot_id).first() if batch.seed_lot_id else None
    supplier = db.query(Supplier).filter(Supplier.id == seed_lot.supplier_id).first() if seed_lot and seed_lot.supplier_id else None

    germination = db.query(GerminationRecord).filter(GerminationRecord.batch_id == batch.id).order_by(GerminationRecord.date).all()
    germination_date = germination[-1].date if germination else None
    germination_rate = germination[-1].success_rate if germination else None
    transplants = db.query(TransplantRecord).filter(TransplantRecord.batch_id == batch.id).order_by(TransplantRecord.date).all()
    transplant_date = transplants[-1].date if transplants else None

    host = _get_server_host()
    passport_id_str = _generate_passport_id(db)
    passport_page_url = f"http://{host}:8000/p/{passport_id_str}"
    qr_b64 = _generate_qr_base64(passport_page_url)
    barcode_str = _generate_barcode(passport_id_str)

    production_cost = data.production_cost or (plant.retail_price * 0.45 if plant else 0)
    selling_price = data.selling_price or (plant.retail_price if plant else 0)
    wholesale_price = data.wholesale_price or (plant.wholesale_price if plant else 0)

    passport = PlantPassport(
        passport_id=passport_id_str,
        batch_id=batch.id,
        plant_id=batch.plant_id,
        variety_id=plant.variety_id if plant else None,
        category_id=plant.category_id if plant else None,
        branch_id=data.branch_id,
        plant_name=plant.name if plant else None,
        scientific_name=plant.scientific_name if plant else None,
        local_name=plant.local_name if plant else None,
        variety_name=variety.name if variety else None,
        category_name=category.name if category else None,
        batch_number=batch.batch_number,
        seed_lot_number=seed_lot.lot_number if seed_lot else None,
        seed_supplier=supplier.name if supplier else None,
        sowing_date=batch.sowing_date,
        germination_date=germination_date,
        germination_rate=germination_rate,
        transplant_date=transplant_date,
        current_growth_stage=batch.status,
        expected_ready_date=batch.expected_ready_date,
        current_stock=batch.current_quantity,
        tray_number=batch.tray_number,
        pot_number=data.pot_number,
        warehouse_location=data.warehouse_location,
        location=batch.location,
        nursery_zone=data.nursery_zone,
        greenhouse=data.greenhouse,
        bed_number=data.bed_number,
        production_cost=production_cost,
        selling_price=selling_price,
        wholesale_price=wholesale_price,
        discount_price=data.selling_price or selling_price,
        profit_margin=round(selling_price - production_cost, 2) if selling_price and production_cost else 0,
        health_score=None,
        mortality_risk="low",
        qr_code=qr_b64,
        barcode=barcode_str,
        scan_url=passport_page_url,
    )
    db.add(passport)
    db.flush()

    for item in _build_passport_from_batch(batch, db, qr_b64, passport_page_url)["timeline"]:
        db.add(PassportTimelineEvent(
            passport_id=passport.id,
            event_date=datetime.fromisoformat(item["date"]).date(),
            event_type=item["event_type"],
            event_title=item["event_title"],
            event_details=item.get("event_details"),
            icon=item.get("icon"),
        ))

    db.commit()
    db.refresh(passport)
    return passport


@router.get("/search")
def search_passports(
    q: str = Query(..., min_length=1),
    db: Session = Depends(get_db),
):
    term = f"%{q}%"
    results = db.query(PlantPassport).filter(or_(
        PlantPassport.passport_id.ilike(term),
        PlantPassport.barcode.ilike(term),
        PlantPassport.batch_number.ilike(term),
        PlantPassport.plant_name.ilike(term),
    )).limit(50).all()
    return [
        {
            "id": p.id,
            "passport_id": p.passport_id,
            "plant_name": p.plant_name,
            "batch_number": p.batch_number,
            "current_growth_stage": p.current_growth_stage,
            "health_status": p.health_status,
            "qr_code": p.qr_code,
        }
        for p in results
    ]


@router.get("/reports/scan-history")
def scan_history_report(
    passport_id: Optional[str] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(PassportScanLog)
    if passport_id:
        q = q.filter(PassportScanLog.passport_id == passport_id)
    logs = q.order_by(PassportScanLog.scanned_at.desc()).limit(200).all()
    return [
        {
            "id": l.id,
            "passport_id": l.passport_id,
            "scanned_by": l.scanned_by,
            "scan_source": l.scan_source,
            "scanned_at": l.scanned_at.isoformat() if l.scanned_at else None,
        }
        for l in logs
    ]


@router.get("/reports/batch-traceability")
def batch_traceability_report(
    batch_number: str = Query(..., min_length=1),
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    passport = db.query(PlantPassport).filter(PlantPassport.batch_number == batch_number).first()
    if not passport:
        raise HTTPException(status_code=404, detail="No passport found for this batch")
    return {
        "passport_id": passport.passport_id,
        "batch_number": passport.batch_number,
        "plant_name": passport.plant_name,
        "timeline": [],
    }


@router.get("/{passport_id}", response_model=PassportOut)
def get_passport(passport_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    return passport


@router.put("/{passport_id}", response_model=PassportOut)
def update_passport(passport_id: str, data: PassportUpdate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    for k, v in data.model_dump(exclude_unset=True).items():
        setattr(passport, k, v)
    db.commit()
    db.refresh(passport)
    return passport


@router.delete("/{passport_id}")
def delete_passport(passport_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    db.delete(passport)
    db.commit()
    return {"detail": "Passport deleted"}


@router.get("/{passport_id}/timeline", response_model=list[TimelineEventOut])
def get_passport_timeline(passport_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    events = db.query(PassportTimelineEvent).filter(
        PassportTimelineEvent.passport_id == passport.id
    ).order_by(PassportTimelineEvent.event_date).all()
    return events


@router.post("/{passport_id}/timeline", response_model=TimelineEventOut, status_code=201)
def add_timeline_event(passport_id: str, data: TimelineEventCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    event = PassportTimelineEvent(
        passport_id=passport.id,
        event_date=data.event_date,
        event_type=data.event_type,
        event_title=data.event_title,
        event_details=data.event_details,
        icon=data.icon,
        photo_url=data.photo_url,
    )
    db.add(event)
    db.commit()
    db.refresh(event)
    return event


@router.get("/{passport_id}/photos", response_model=list[PhotoOut])
def get_passport_photos(passport_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    return db.query(PassportPhoto).filter(PassportPhoto.passport_id == passport.id).order_by(PassportPhoto.created_at).all()


@router.post("/{passport_id}/photos", response_model=PhotoOut, status_code=201)
def add_passport_photo(passport_id: str, data: PhotoCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    photo = PassportPhoto(
        passport_id=passport.id,
        growth_stage=data.growth_stage,
        photo_url=data.photo_url,
        caption=data.caption,
        taken_date=data.taken_date,
    )
    db.add(photo)
    db.commit()
    db.refresh(photo)
    return photo


@router.get("/{passport_id}/scan-logs")
def get_scan_logs(passport_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    logs = db.query(PassportScanLog).filter(PassportScanLog.passport_id == passport.id).order_by(PassportScanLog.scanned_at.desc()).all()
    return [
        {"id": l.id, "scanned_by": l.scanned_by, "scan_source": l.scan_source, "scanned_at": l.scanned_at.isoformat() if l.scanned_at else None}
        for l in logs
    ]


@router.get("/{passport_id}/customer-views", response_model=list[CustomerViewOut])
def get_customer_views(passport_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    return db.query(PassportCustomerView).filter(PassportCustomerView.passport_id == passport.id).all()


@router.post("/{passport_id}/customer-views", response_model=CustomerViewOut, status_code=201)
def add_customer_view(passport_id: str, data: CustomerViewCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    view = PassportCustomerView(
        passport_id=passport.id,
        customer_id=data.customer_id,
        sale_id=data.sale_id,
        sale_date=data.sale_date,
        invoice_number=data.invoice_number,
        delivery_status=data.delivery_status,
        warranty_expiry=data.warranty_expiry,
    )
    db.add(view)
    db.commit()
    db.refresh(view)
    return view


@router.get("/qr/{passport_id}")
def get_passport_qr(passport_id: str, db: Session = Depends(get_db)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    if not passport.qr_code:
        host = _get_server_host()
        passport_page_url = f"http://{host}:8000/p/{passport.passport_id}"
        qr_b64 = _generate_qr_base64(passport_page_url)
        barcode_str = _generate_barcode(passport.passport_id)
        passport.qr_code = qr_b64
        passport.barcode = barcode_str
        passport.scan_url = passport_page_url
        db.commit()
        db.refresh(passport)
    return {
        "passport_id": passport.passport_id,
        "qr_base64": passport.qr_code,
        "barcode": passport.barcode,
        "scan_url": passport.scan_url,
    }


@router.get("/qr/{passport_id}/print")
def get_passport_qr_print(passport_id: str, db: Session = Depends(get_db)):
    passport = db.query(PlantPassport).filter(
        (PlantPassport.id == passport_id) | (PlantPassport.passport_id == passport_id)
    ).first()
    if not passport:
        raise HTTPException(status_code=404, detail="Passport not found")
    if not passport.qr_code:
        host = _get_server_host()
        passport_page_url = f"http://{host}:8000/p/{passport.passport_id}"
        qr_b64 = _generate_qr_base64(passport_page_url)
        barcode_str = _generate_barcode(passport.passport_id)
        passport.qr_code = qr_b64
        passport.barcode = barcode_str
        passport.scan_url = passport_page_url
        db.commit()
        db.refresh(passport)
    return {
        "passport_id": passport.passport_id,
        "plant_name": passport.plant_name,
        "variety_name": passport.variety_name,
        "category_name": passport.category_name,
        "batch_number": passport.batch_number,
        "sowing_date": passport.sowing_date.isoformat() if passport.sowing_date else None,
        "current_growth_stage": passport.current_growth_stage,
        "current_stock": passport.current_stock,
        "selling_price": passport.selling_price,
        "qr_base64": passport.qr_code,
        "barcode": passport.barcode,
        "scan_url": passport.scan_url,
    }
