"""
Organization CRUD: Ports, Companies, BuoyOwnership.

GET  /org/ports                       → list ports
POST /org/ports                       → create port  (admin)
PUT  /org/ports/{id}                  → update port  (admin)

GET  /org/companies                   → list companies
POST /org/companies                   → create company (admin)
PUT  /org/companies/{id}              → update company (admin)

GET  /org/companies/{company_id}/buoys        → list owned buoys
POST /org/companies/{company_id}/buoys        → assign buoy to company (admin)
DELETE /org/companies/{company_id}/buoys/{id} → remove ownership     (admin)

GET  /org/me/company                  → current user's company + port (for homepage)
"""

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import Optional
import uuid
import os
import json

from database import get_db
from models.org import Port, Company, BuoyOwnership
from models.user import User
from models.aid import Aid
from routers.auth import get_current_user, require_admin

# Charts directory — one level above the backend package
_CHARTS_DIR = os.path.normpath(
    os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'charts')
)

def _read_chart_bbox(chart_name: str) -> list | None:
    """Return [west, south, east, north] from the chart's meta.json, or None."""
    if not chart_name:
        return None
    # Security: prevent path traversal — chart_name must not escape _CHARTS_DIR
    meta = os.path.normpath(os.path.join(_CHARTS_DIR, chart_name, 'meta.json'))
    if not meta.startswith(_CHARTS_DIR + os.sep):
        return None
    try:
        with open(meta, 'r', encoding='utf-8') as f:
            data = json.load(f)
        bbox = data.get('bbox')
        if bbox and len(bbox) == 4:
            return bbox   # [minLon, minLat, maxLon, maxLat]
    except Exception:
        pass
    return None

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


# ── Ports ─────────────────────────────────────────────────────────────────────

@router.get("/ports")
def list_ports(db: Session = Depends(get_db)):
    return [_port_dict(p) for p in db.query(Port).filter(Port.activo == True).all()]


@router.post("/ports", dependencies=[Depends(require_admin)])
def create_port(data: dict, db: Session = Depends(get_db)):
    if not data.get("name"):
        raise HTTPException(400, "name is required")
    port = Port(
        id=str(uuid.uuid4()),
        name=data["name"],
        country=data.get("country", "Colombia"),
        center_lat=data.get("center_lat"),
        center_lon=data.get("center_lon"),
        default_zoom=data.get("default_zoom", 12.0),
        chart_name=data.get("chart_name"),
    )
    db.add(port); db.commit()
    return _port_dict(port)


@router.put("/ports/{port_id}", dependencies=[Depends(require_admin)])
def update_port(port_id: str, data: dict, db: Session = Depends(get_db)):
    port = db.query(Port).filter(Port.id == port_id).first()
    if not port:
        raise HTTPException(404, "Port not found")
    for field in ("name", "country", "center_lat", "center_lon",
                  "default_zoom", "chart_name", "activo"):
        if field in data:
            setattr(port, field, data[field])
    db.commit()
    return _port_dict(port)


def _port_dict(p: Port) -> dict:
    return {
        "id": p.id, "name": p.name, "country": p.country,
        "center_lat": p.center_lat, "center_lon": p.center_lon,
        "default_zoom": p.default_zoom, "chart_name": p.chart_name,
        "chart_bbox": _read_chart_bbox(p.chart_name),  # [W,S,E,N] or null
        "activo": p.activo,
    }


# ── Companies ─────────────────────────────────────────────────────────────────

@router.get("/companies")
def list_companies(db: Session = Depends(get_db)):
    return [_company_dict(c) for c in db.query(Company).all()]


@router.post("/companies", dependencies=[Depends(require_admin)])
def create_company(data: dict, db: Session = Depends(get_db)):
    if not data.get("name"):
        raise HTTPException(400, "name is required")
    company = Company(
        id=str(uuid.uuid4()),
        name=data["name"],
        port_id=data.get("port_id"),
        contact_email=data.get("contact_email"),
        contact_phone=data.get("contact_phone"),
        notas=data.get("notas"),
    )
    db.add(company); db.commit()
    return _company_dict(company)


@router.put("/companies/{company_id}", dependencies=[Depends(require_admin)])
def update_company(company_id: str, data: dict, db: Session = Depends(get_db)):
    company = db.query(Company).filter(Company.id == company_id).first()
    if not company:
        raise HTTPException(404, "Company not found")
    for field in ("name", "port_id", "contact_email", "contact_phone", "notas", "activa"):
        if field in data:
            setattr(company, field, data[field])
    db.commit()
    return _company_dict(company)


def _company_dict(c: Company) -> dict:
    return {
        "id": c.id, "name": c.name, "port_id": c.port_id,
        "contact_email": c.contact_email, "contact_phone": c.contact_phone,
        "activa": c.activa, "notas": c.notas,
    }


# ── Buoy Ownership ────────────────────────────────────────────────────────────

@router.get("/companies/{company_id}/buoys")
def list_company_buoys(company_id: str, db: Session = Depends(get_db)):
    rows = db.query(BuoyOwnership).filter(BuoyOwnership.company_id == company_id).all()
    result = []
    for r in rows:
        entry = {"id": r.id, "company_id": r.company_id,
                 "aid_id": r.aid_id, "mmsi": r.mmsi, "notas": r.notas}
        # Enrich with aid name if available
        if r.aid_id:
            aid = db.query(Aid).filter(Aid.id == r.aid_id).first()
            if aid:
                entry["aid_nombre"] = aid.nombre
                entry["mmsi"] = entry["mmsi"] or aid.mmsi
        result.append(entry)
    return result


@router.post("/companies/{company_id}/buoys", dependencies=[Depends(require_admin)])
def assign_buoy(company_id: str, data: dict, db: Session = Depends(get_db)):
    """
    Assign a buoy to a company.  Provide either aid_id or mmsi (or both).
    If aid_id is given, mmsi is auto-filled from the Aid row.
    """
    company = db.query(Company).filter(Company.id == company_id).first()
    if not company:
        raise HTTPException(404, "Company not found")

    aid_id = data.get("aid_id")
    mmsi   = data.get("mmsi")

    if not aid_id and not mmsi:
        raise HTTPException(400, "Provide aid_id or mmsi")

    if aid_id:
        aid = db.query(Aid).filter(Aid.id == aid_id).first()
        if not aid:
            raise HTTPException(404, "Aid not found")
        mmsi = mmsi or aid.mmsi   # fill from aid if not explicitly given

    # Prevent duplicate
    existing = db.query(BuoyOwnership).filter(
        BuoyOwnership.company_id == company_id,
        BuoyOwnership.aid_id == aid_id,
    ).first()
    if existing:
        raise HTTPException(409, "Already assigned")

    row = BuoyOwnership(
        id=str(uuid.uuid4()),
        company_id=company_id,
        aid_id=aid_id,
        mmsi=mmsi,
        notas=data.get("notas"),
    )
    db.add(row); db.commit()
    return {"ok": True, "id": row.id, "mmsi": mmsi}


@router.delete("/companies/{company_id}/buoys/{ownership_id}",
               dependencies=[Depends(require_admin)])
def remove_ownership(company_id: str, ownership_id: str, db: Session = Depends(get_db)):
    row = db.query(BuoyOwnership).filter(
        BuoyOwnership.id == ownership_id,
        BuoyOwnership.company_id == company_id,
    ).first()
    if not row:
        raise HTTPException(404, "Ownership record not found")
    db.delete(row); db.commit()
    return {"ok": True}


# ── Current user's company / home port ───────────────────────────────────────

@router.get("/me/company")
def my_company(
    current_user: User = Depends(get_current_user),
    db: Session        = Depends(get_db),
):
    """
    Returns the company and port associated with the logged-in user.
    Used by the frontend to set the default map view on login.
    """
    company_id = getattr(current_user, "company_id", None)
    if not company_id:
        return {"company": None, "port": None}

    company = db.query(Company).filter(Company.id == company_id).first()
    port    = db.query(Port).filter(Port.id == company.port_id).first() \
              if company and company.port_id else None

    return {
        "company": _company_dict(company) if company else None,
        "port":    _port_dict(port) if port else None,
    }
