from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from pydantic import BaseModel, EmailStr
from typing import Optional
import bcrypt

from database import get_db
from models.user import User
from services.chat_service import add_user_to_system_group

router = APIRouter()


class SetupStatusResponse(BaseModel):
    needs_setup: bool


class SetupInitRequest(BaseModel):
    username: str
    password: str
    email: Optional[str] = None
    full_name: Optional[str] = None
    venue_type: Optional[str] = None
    venue_name: Optional[str] = None
    pin: Optional[str] = None


class SetupInitResponse(BaseModel):
    ok: bool


class SecurityConfigResponse(BaseModel):
    login_method: str
    autofill_username: bool


@router.get("/security-config", response_model=SecurityConfigResponse)
def security_config(db: Session = Depends(get_db)):
    """Public endpoint — returns only the security settings needed by the login page."""
    from models.settings import PosSettings
    rows = {r.key: r.value for r in db.query(PosSettings).filter(
        PosSettings.key.in_(["security.login_method", "security.autofill_username"])
    ).all()}
    return SecurityConfigResponse(
        login_method=rows.get("security.login_method", "password"),
        autofill_username=rows.get("security.autofill_username", "true") == "true",
    )


@router.get("/status", response_model=SetupStatusResponse)
def setup_status(db: Session = Depends(get_db)):
    has_manager = db.query(User).filter(
        User.perm_access_dashboard == True,
        User.is_active == True,
    ).first()
    return SetupStatusResponse(needs_setup=has_manager is None)


@router.post("/init", response_model=SetupInitResponse)
def setup_init(body: SetupInitRequest, db: Session = Depends(get_db)):
    has_manager = db.query(User).filter(
        User.perm_access_dashboard == True,
        User.is_active == True,
    ).first()
    if has_manager:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="Setup already completed — a manager account already exists.",
        )

    if not body.username.strip():
        raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Username is required.")
    if len(body.password) < 6:
        raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Password must be at least 6 characters.")

    existing = db.query(User).filter(User.username == body.username.strip()).first()
    if existing:
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Username already taken.")

    password_hash = bcrypt.hashpw(body.password.encode(), bcrypt.gensalt()).decode()

    raw_pin = body.pin if (body.pin and body.pin.isdigit() and 4 <= len(body.pin) <= 6) else "0000"
    pin_hash = bcrypt.hashpw(raw_pin.encode(), bcrypt.gensalt()).decode()

    user = User(
        username=body.username.strip(),
        pin_hash=pin_hash,
        password_hash=password_hash,
        email=body.email,
        full_name=body.full_name,
        role="store_manager",
        is_active=True,
    )
    # Apply store_manager default permissions
    from roles import get_default_permissions
    for field, value in get_default_permissions("store_manager").items():
        setattr(user, field, value)
    db.add(user)

    # Persist venue settings if provided
    if body.venue_name or body.venue_type:
        from models.settings import PosSettings
        from datetime import datetime, timezone
        now = datetime.now(timezone.utc)
        if body.venue_name:
            setting = db.query(PosSettings).filter(PosSettings.key == "venue.name").first()
            if setting:
                setting.value = body.venue_name
                setting.updated_at = now
            else:
                db.add(PosSettings(key="venue.name", value=body.venue_name, updated_at=now))
        if body.venue_type:
            setting = db.query(PosSettings).filter(PosSettings.key == "venue.type").first()
            if setting:
                setting.value = body.venue_type
                setting.updated_at = now
            else:
                db.add(PosSettings(key="venue.type", value=body.venue_type, updated_at=now))

    db.commit()
    db.refresh(user)
    add_user_to_system_group(db, user.id)
    return SetupInitResponse(ok=True)
