from app.helpers.crud import get_or_404
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import cast, String
from typing import List, Optional
from app.database import get_db
from app.models.asim import Asim
from app.schemas.asim import AsimCreate, AsimUpdate, AsimResponse, AsimImportPeriode
from app.models.user import User, UserRole
from app.core.security import get_password_hash

router = APIRouter(prefix="/api/asim", tags=["ASIM"])

def asim_to_response(asim: Asim, include_role: bool = False) -> dict:
    data = {c.name: getattr(asim, c.name) for c in asim.__table__.columns}
    if include_role and asim.user:
        data['user_role'] = asim.user.role
    elif include_role:
        data['user_role'] = None
    return data

@router.get("/", response_model=List[AsimResponse])
def get_all_asim(
    search: Optional[str] = None,
    is_active: Optional[bool] = None,
    db: Session = Depends(get_db)
):
    query = db.query(Asim)
    if search:
        query = query.filter(
            Asim.full_name.ilike(f"%{search}%") |
            Asim.nickname.ilike(f"%{search}%") |
            cast(Asim.no_asim, String).ilike(f"%{search}%")
        )
    if is_active is not None:
        query = query.filter(Asim.is_active == is_active)
    asims = query.order_by(Asim.no_asim).all()
    return [asim_to_response(a) for a in asims]

@router.get("/{asim_id}", response_model=AsimResponse)
def get_asim(asim_id: int, db: Session = Depends(get_db)):
    asim = get_or_404(db, Asim, asim_id, "ASIM")
    return asim_to_response(asim, include_role=True)

@router.put("/{asim_id}/set-role")
def set_asim_role(asim_id: int, role: str, db: Session = Depends(get_db)):
    """Ubah role user ASIM (asim → pengurus → super_admin, dst)."""
    asim = get_or_404(db, Asim, asim_id, "ASIM")
    if not asim.user_id:
        raise HTTPException(status_code=400, detail="ASIM belum memiliki akun user")
    try:
        new_role = UserRole(role)
    except ValueError:
        raise HTTPException(status_code=400, detail=f"Role tidak valid: {role}. Pilihan: asim, pengurus, super_admin")
    user = db.query(User).filter(User.id == asim.user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="User tidak ditemukan")
    user.role = new_role
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal mengubah role pengguna")
    return {"message": f"Role berhasil diubah menjadi {new_role}", "role": str(new_role)}

@router.post("/bulk-import", response_model=List[AsimResponse])
def bulk_import_asim(data: List[AsimCreate], db: Session = Depends(get_db)):
    try:
        db.query(Asim).delete()
        results = []
        for item in data:
            item_dict = item.model_dump()
            asim = Asim(**item_dict)
            db.add(asim)
            results.append(asim)
        try:
            db.commit()
            for asim in results:
                db.refresh(asim)
        except Exception:
            db.rollback()
            raise HTTPException(status_code=500, detail="Gagal menyimpan data import ASIM")
        return [asim_to_response(a) for a in results]
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=400, detail=f"Import gagal: {str(e)}")

@router.post("/", response_model=AsimResponse)
def create_asim(data: AsimCreate, db: Session = Depends(get_db)):
    item_dict = data.model_dump()
    existing = db.query(Asim).filter(Asim.no_asim == data.no_asim).first()
    if existing:
        for key, value in item_dict.items():
            setattr(existing, key, value)
        try:
            db.commit()
            db.refresh(existing)
        except Exception:
            db.rollback()
            raise HTTPException(status_code=500, detail="Gagal memperbarui data ASIM")
        return asim_to_response(existing)
    asim = Asim(**item_dict)
    db.add(asim)
    try:
        db.commit()
        db.refresh(asim)
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menyimpan data ASIM baru")
    return asim_to_response(asim)

@router.put("/{asim_id}", response_model=AsimResponse)
def update_asim(asim_id: int, data: AsimUpdate, db: Session = Depends(get_db)):
    asim = get_or_404(db, Asim, asim_id, "ASIM")
    item_dict = data.model_dump(exclude_unset=True)
    for key, value in item_dict.items():
        setattr(asim, key, value)
    try:
        db.commit()
        db.refresh(asim)
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal memperbarui data ASIM")
    return asim_to_response(asim)

@router.delete("/all")
def delete_all_asim(db: Session = Depends(get_db)):
    db.query(Asim).delete()
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menghapus semua data ASIM")
    return {"message": "Semua data ASIM berhasil dihapus"}

@router.delete("/{asim_id}")
def delete_asim(asim_id: int, db: Session = Depends(get_db)):
    from app.models.assignment import Assignment
    from app.models.unavailability import Unavailability
    from app.models.area_unavailability import AsimAreaUnavailability
    asim = get_or_404(db, Asim, asim_id, "ASIM")
    db.query(Assignment).filter(Assignment.asim_id == asim_id).update({Assignment.asim_id: None})
    db.query(Unavailability).filter(Unavailability.asim_id == asim_id).delete()
    db.query(AsimAreaUnavailability).filter(AsimAreaUnavailability.asim_id == asim_id).delete()
    if asim.user_id:
        db.query(User).filter(User.id == asim.user_id).delete()
    db.delete(asim)
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menghapus data ASIM")
    return {"message": "ASIM berhasil dihapus"}


@router.post("/{asim_id}/create-account")
def create_asim_account(asim_id: int, db: Session = Depends(get_db)):
    asim = get_or_404(db, Asim, asim_id, "ASIM")
    if asim.user_id:
        raise HTTPException(status_code=400, detail="ASIM sudah punya akun")
    
    default_password = f"{asim.no_asim}asimSMTB!"
    user = User(
        username=str(asim.no_asim),
        password=get_password_hash(default_password),
        role=UserRole.asim,
        is_active=True,
        must_change_password=True,
    )
    db.add(user)
    db.flush()
    asim.user_id = user.id
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal membuat akun ASIM")
    return {"message": f"Akun berhasil dibuat. Username: {asim.no_asim}, Password: {default_password}"}

@router.post("/import-periode")
def import_periode(data: List[AsimImportPeriode], db: Session = Depends(get_db)):
    """
    Import data ASIM untuk pergantian periode baru.
    Matching by phone_hp (wajib ada).

    - phone_hp cocok di DB (aktif/nonaktif) → update data + reset password akun
    - phone_hp tidak ada di DB              → buat ASIM baru + akun baru
    - phone_hp tidak ada di list import     → nonaktifkan
    """
    try:
        # --- Validasi input ---
        if not data:
            raise HTTPException(status_code=400, detail="Data import kosong")

        # Cek phone_hp tidak boleh duplikat dalam file
        phones_in_file = [row.phone_hp.strip() for row in data]
        if len(phones_in_file) != len(set(phones_in_file)):
            raise HTTPException(status_code=400, detail="Ada duplikat No HP dalam file import")

        # Cek no_asim tidak boleh duplikat dalam file
        nos_in_file = [row.no_asim for row in data]
        if len(nos_in_file) != len(set(nos_in_file)):
            raise HTTPException(status_code=400, detail="Ada duplikat No ASIM dalam file import")

        incoming_phones = set(phones_in_file)

        # --- Step 1: Simpan no_asim lama, lalu bebaskan semua untuk hindari unique conflict ---
        all_asim = db.query(Asim).all()
        original_nos = {a.id: a.no_asim for a in all_asim}
        for a in all_asim:
            a.no_asim = -(1000000 + a.id)  # nilai temp negatif unik
        db.flush()

        # --- Step 2: Proses tiap baris dari file ---
        updated_nos = []
        reactivated_nos = []
        created_nos = []

        for row in data:
            phone = row.phone_hp.strip()
            row_dict = row.model_dump()

            existing = db.query(Asim).filter(Asim.phone_hp == phone).first()

            if existing:
                was_inactive = not existing.is_active

                # Update semua field profil
                for key, value in row_dict.items():
                    setattr(existing, key, value)
                existing.is_active = True
                db.flush()

                # Update akun user: username baru = no_asim baru, reset password
                if existing.user_id:
                    user = db.query(User).filter(User.id == existing.user_id).first()
                    if user:
                        new_password = f"{row.no_asim}asimSMTB!"
                        user.username = str(row.no_asim)
                        user.password = get_password_hash(new_password)
                        user.must_change_password = True
                        user.is_active = True
                        db.flush()

                if was_inactive:
                    reactivated_nos.append(row.no_asim)
                else:
                    updated_nos.append(row.no_asim)

            else:
                # ASIM baru: buat record + akun
                new_asim = Asim(**row_dict)
                new_asim.is_active = True
                db.add(new_asim)
                db.flush()

                new_password = f"{row.no_asim}asimSMTB!"
                new_user = User(
                    username=str(row.no_asim),
                    password=get_password_hash(new_password),
                    role=UserRole.asim,
                    is_active=True,
                    must_change_password=True,
                )
                db.add(new_user)
                db.flush()
                new_asim.user_id = new_user.id
                db.flush()

                created_nos.append(row.no_asim)

        # --- Step 3: Nonaktifkan ASIM yang tidak ada di file import ---
        # (ditandai dengan no_asim masih negatif = belum diproses)
        deactivated_nos = []
        for a in db.query(Asim).all():
            if a.no_asim < 0:
                original_no = original_nos.get(a.id, 0)
                a.no_asim = original_no  # kembalikan no lama
                if a.is_active:
                    a.is_active = False
                    # Nonaktifkan akun user juga
                    if a.user_id:
                        user = db.query(User).filter(User.id == a.user_id).first()
                        if user:
                            user.is_active = False
                    deactivated_nos.append(original_no)
                db.flush()

        try:
            db.commit()
        except Exception:
            db.rollback()
            raise HTTPException(status_code=500, detail="Gagal menyimpan data import periode")

        return {
            "message": "Import periode selesai",
            "summary": {
                "updated": len(updated_nos),
                "reactivated": len(reactivated_nos),
                "created": len(created_nos),
                "deactivated": len(deactivated_nos),
            },
            "detail": {
                "updated_nos": sorted(updated_nos),
                "reactivated_nos": sorted(reactivated_nos),
                "created_nos": sorted(created_nos),
                "deactivated_nos": sorted(deactivated_nos),
            }
        }

    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=400, detail=f"Import periode gagal: {str(e)}")


@router.post("/create-all-accounts")
def create_all_asim_accounts(db: Session = Depends(get_db)):
    asims = db.query(Asim).filter(Asim.is_active == True, Asim.user_id == None).all()
    created = []
    for asim in asims:
        default_password = f"{asim.no_asim}asimSMTB!"
        user = User(
            username=str(asim.no_asim),
            password=get_password_hash(default_password),
            role=UserRole.asim,
            is_active=True,
            must_change_password=True,
        )
        db.add(user)
        db.flush()
        asim.user_id = user.id
        created.append(asim.no_asim)
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal membuat akun untuk semua ASIM")
    return {"message": f"Berhasil membuat {len(created)} akun", "asim_numbers": created}