"""Idempotent seed: bootstrap admin, zones/areas, equipment types,
locations. Safe to re-run.

    python -m app.db.seed
"""
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.core.config import settings
from app.core.security import hash_password
from app.db.session import SessionLocal
from app.models.enums import EquipmentCondition, LocationType, UserRole
from app.models.reference import Area, EquipmentType, Location, Zone
from app.models.user import User

ZONES: list[tuple[str, str, list[tuple[str, str]]]] = [
    ("Bongram-Zone", "BNG", [("Bongram Bazar", "BGB")]),
    ("Madhpur-Zone", "MDP", [("Madhpur Bazar", "MDB")]),
    ("Jorgacha-Zone", "JRG", [("Jorgacha Bazar", "JGB")]),
    ("Pabna-Zone", "PBN", [("Pabna Sadar", "PBS")]),
]

EQUIPMENT_TYPES: list[tuple[str, str, str, bool, int | None, int]] = [
    # name, code, unit, is_serialized, default_return_days, reorder_level
    ("Fiber Cable", "FBC", "meter", False, None, 2000),
    ("Patch Cord", "PTC", "pcs", False, None, 100),
    ("ONU", "ONU", "pcs", True, 7, 20),
    ("Power Adapter", "ADP", "pcs", False, None, 30),
    ("TJ Box", "TJB", "pcs", False, None, 50),
    ("Splitter", "SPL", "pcs", False, None, 20),
    ("Package Router", "PRT", "pcs", True, 7, 20),
]

LOCATIONS: list[tuple[str, str, LocationType, bool]] = [
    ("Bongram-Office", "OF-BNG", LocationType.OFFICE, True),
    ("Madhpur-Office", "OF-MDP", LocationType.OFFICE, False),
    ("Jorgacha-Office", "OF-JRG", LocationType.OFFICE, False),
    ("Pabna-Office", "OF-PBN", LocationType.OFFICE, False),
]

DEMO_STAFF: list[tuple[str, str, UserRole, str]] = [
    ("Manager Karim", "manager@isp.local", UserRole.MANAGER, "EMP-M01"),
    ("Technician Rahim", "tech1@isp.local", UserRole.FIELD_STAFF, "EMP-T01"),
    ("Technician Jamal", "tech2@isp.local", UserRole.FIELD_STAFF, "EMP-T02"),
    ("Auditor Nasrin", "viewer@isp.local", UserRole.READ_ONLY, "EMP-R01"),
]


def _get_or_create(db: Session, model, defaults: dict | None = None, **lookup):
    obj = db.scalar(select(model).filter_by(**lookup))
    if obj:
        return obj, False
    obj = model(**lookup, **(defaults or {}))
    db.add(obj)
    db.flush()
    return obj, True


def seed(db: Session) -> None:
    created: dict[str, int] = {}

    # --- Admin ---
    admin, is_new = _get_or_create(
        db,
        User,
        {
            "full_name": settings.FIRST_ADMIN_NAME,
            "password_hash": hash_password(settings.FIRST_ADMIN_PASSWORD),
            "role": UserRole.ADMIN,
            "employee_code": "EMP-A01",
            "is_active": True,
        },
        email=settings.FIRST_ADMIN_EMAIL,
    )
    created["admin"] = int(is_new)

    # --- Demo staff ---
    # These four share the admin's password, so they are only created when explicitly
    # asked for. A production seed gets the admin and the reference data, nothing that
    # can be logged into by someone who read the README.
    n = 0
    if settings.SEED_DEMO_STAFF:
        for full_name, email, role, code in DEMO_STAFF:
            _, was_new = _get_or_create(
                db,
                User,
                {
                    "full_name": full_name,
                    "password_hash": hash_password(settings.FIRST_ADMIN_PASSWORD),
                    "role": role,
                    "employee_code": code,
                    "is_active": True,
                },
                email=email,
            )
            n += was_new
    created["staff"] = n

    # --- Zones + areas ---
    nz = na = 0
    for zone_name, zone_code, areas in ZONES:
        zone, was_new = _get_or_create(db, Zone, {"name": zone_name}, code=zone_code)
        nz += was_new
        for area_name, area_code in areas:
            _, a_new = _get_or_create(
                db, Area, {"name": area_name, "zone_id": zone.id}, code=area_code
            )
            na += a_new
    created["zones"], created["areas"] = nz, na

    # --- Equipment types ---
    n = 0
    for name, code, unit, serialized, return_days, reorder in EQUIPMENT_TYPES:
        _, was_new = _get_or_create(
            db,
            EquipmentType,
            {
                "name": name,
                "unit": unit,
                "is_serialized": serialized,
                "default_return_days": return_days,
                "reorder_level": reorder,
            },
            code=code,
        )
        n += was_new
    created["equipment_types"] = n

    # --- Locations ---
    n = 0
    for name, code, loc_type, is_default in LOCATIONS:
        _, was_new = _get_or_create(
            db, Location, {"name": name, "type": loc_type, "is_default": is_default}, code=code
        )
        n += was_new
    created["locations"] = n

    db.commit()

    print("Seed complete. Newly created rows:")
    for key, count in created.items():
        print(f"  {key:16s} {count}")
    # The password is deliberately not echoed: seed output lands in `docker compose
    # logs` and terminal scrollback, and this one belongs to an admin account.
    print(f"\nAdmin login: {settings.FIRST_ADMIN_EMAIL}")
    print("Password: the FIRST_ADMIN_PASSWORD you configured.")


def main() -> None:
    db = SessionLocal()
    try:
        seed(db)
    finally:
        db.close()


if __name__ == "__main__":
    main()
