from fastapi import APIRouter, HTTPException, status, Depends, Query
from sqlalchemy.orm import Session
from sqlalchemy import or_
from typing import List

from app.schemas import Contact, ContactCreate, ContactUpdate, loginData
from app.models import Contact as ContactModel
from app.dependencies import get_db
from app.routers.auth import get_current_user

contact_router = APIRouter()


# GET /contacts: Retrieve active contacts from the active_pgroup
@contact_router.get("/", response_model=List[Contact])
async def get_contacts(
    active_pgroup: str = Query(...),
    db: Session = Depends(get_db),
    current_user: loginData = Depends(get_current_user),
):
    # Validate that the active_pgroup belongs to the user
    if active_pgroup not in current_user.pgroups:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Invalid pgroup provided.",
        )

    # Query for active contacts in the active_pgroup
    contacts = (
        db.query(ContactModel)
        .filter(
            ContactModel.pgroups.like(f"%{active_pgroup}%"),
            ContactModel.status == "active",
        )
        .all()
    )
    return contacts


# GET /contacts/all: Retrieve all contacts from the user's pgroups
@contact_router.get("/all", response_model=List[Contact])
async def get_all_contacts(
    db: Session = Depends(get_db),
    current_user: loginData = Depends(get_current_user),
):
    # Query for all contacts belonging to any of the user's pgroups
    user_pgroups = current_user.pgroups
    filters = [ContactModel.pgroups.like(f"%{pgroup}%") for pgroup in user_pgroups]
    contacts = db.query(ContactModel).filter(or_(*filters)).all()
    return contacts


@contact_router.post("/", response_model=Contact, status_code=status.HTTP_201_CREATED)
async def create_contact(
    contact: ContactCreate,  # Body parameter ONLY
    db: Session = Depends(get_db),  # Secondary dependency for database access
):
    # Check if a contact with the same email already exists in this pgroup
    if (
        db.query(ContactModel)
        .filter(
            ContactModel.email == contact.email,
            ContactModel.pgroups.like(f"%{contact.pgroups}%"),
            ContactModel.status == "active",
        )
        .first()
    ):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="This contact already exists in the provided pgroup.",
        )

    # Create a new contact
    db_contact = ContactModel(
        firstname=contact.firstname,
        lastname=contact.lastname,
        phone_number=contact.phone_number,
        email=contact.email,
        pgroups=contact.pgroups,  # Use the pgroups from the body
        status="active",  # Newly created contacts will be active
    )
    db.add(db_contact)
    db.commit()
    db.refresh(db_contact)
    return db_contact


# PUT /contacts/{contact_id}: Update a contact
@contact_router.put("/{contact_id}", response_model=Contact)
async def update_contact(
    contact_id: int,
    contact: ContactUpdate,
    db: Session = Depends(get_db),
):
    # Retrieve the existing contact
    db_contact = db.query(ContactModel).filter(ContactModel.id == contact_id).first()
    if not db_contact:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Contact not found.",
        )
    # Normalize existing and new pgroups (remove whitespace, handle case
    # sensitivity if needed)
    existing_pgroups = (
        set(p.strip() for p in db_contact.pgroups.split(",") if p.strip())
        if db_contact.pgroups
        else set()
    )
    new_pgroups = (
        set(p.strip() for p in contact.pgroups.split(",") if p.strip())
        if contact.pgroups
        else set()
    )

    # Check if any old pgroups are being removed (strict validation against removal)
    if not new_pgroups.issuperset(existing_pgroups):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Modifying pgroups to remove existing ones is not allowed.",
        )

    combined_pgroups = existing_pgroups.union(new_pgroups)

    # Mark the old contact as inactive
    db_contact.status = "inactive"
    db.commit()
    db.refresh(db_contact)

    # Create a new contact with the updated data
    new_contact = ContactModel(
        firstname=contact.firstname or db_contact.firstname,
        lastname=contact.lastname or db_contact.lastname,
        phone_number=contact.phone_number or db_contact.phone_number,
        email=contact.email or db_contact.email,
        pgroups=",".join(combined_pgroups),  # Use the active_pgroup
        status="active",  # Newly created contacts will be active
    )
    db.add(new_contact)
    db.commit()
    db.refresh(new_contact)

    return new_contact


# DELETE /contacts/{contact_id}: Mark a contact as inactive
@contact_router.delete("/{contact_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_contact(
    contact_id: int,
    db: Session = Depends(get_db),
):
    # Retrieve the existing contact
    db_contact = db.query(ContactModel).filter(ContactModel.id == contact_id).first()
    if not db_contact:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Contact not found.",
        )

    # Mark the contact as inactive
    db_contact.status = "inactive"
    db.commit()
    return
