from fastapi import Request, HTTPException, status
from sqlalchemy.orm import Session, joinedload
from models.label_model import Label, TicketLabel, Release, TicketRelease
from models.ticket_model import Ticket
from schema.label_schema import LabelRequestSchema,LabelUpdateRequestSchema,TicketLabelRequestSchema
from utils.logging import logger
from models.user_model import User


def get_labels_from_db(request: Request, db: Session):
    try:
        org_id = request.state.user.org_id
        labels = (
            db.query(Label)
            .filter(Label.org_id == org_id)
            .options(
                joinedload(Label.creator).load_only(
                    User.id,
                    User.name,
                    User.email,
                    User.platform_role,
                    User.is_active,
                    User.is_verified,
                ),
                joinedload(Label.organization),
            )
            .all()
        )
        return {"labels": labels}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(
            f"Error fetching labels for organization_id: {request.state.user.org_id} - {str(e)}"
        )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error fetching labels: {str(e)}",
        )


def create_label_in_db(request: Request, payload: LabelRequestSchema, db: Session):
    try:
        org_id = request.state.user.org_id
        new_label = Label(
            name=payload.name,
            color=payload.color,
            org_id=org_id,
            created_by=request.state.user.id,
        )
        db.add(new_label)
        db.commit()
        db.refresh(new_label)
        return {
            "message": "Label created successfully",
            "label": new_label,
        }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error creating label: {str(e)}",
        )


def update_label_in_db(id,request: Request, payload: LabelUpdateRequestSchema, db: Session):
    try:
        org_id = request.state.user.org_id
        label = db.query(Label).filter(Label.id == id, Label.org_id == org_id).first()
        if not label:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="Label not found"
            )
        if payload.name is not None:
            label.name = payload.name
        if payload.color is not None:
            label.color = payload.color
        db.commit()
        db.refresh(label)
        return {
            "message": "Label updated successfully",
            "label": label,
        }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error updating label: {str(e)}",
        )
    
def delete_label_in_db(id,request: Request, db: Session):
    try:
        org_id = request.state.user.org_id
        label = db.query(Label).filter(Label.id == id, Label.org_id == org_id).first()
        if not label:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="Label not found"
            )
        db.delete(label)
        db.commit()
        return {"message": "Label deleted successfully"}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error deleting label: {str(e)}",
        )

def assign_label_to_ticket_in_db(request: Request, payload: TicketLabelRequestSchema, db: Session):
    try:
        org_id = request.state.user.org_id
        label = db.query(Label).filter(Label.id == payload.label_id, Label.org_id == org_id).first()
        if not label:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="Label not found"
            )
        
        # Check if the label is already assigned to this ticket
        existing_assignments = db.query(TicketLabel).filter(
            TicketLabel.ticket_id == payload.ticket_id,
            TicketLabel.label_id == payload.label_id
        ).all()

        if existing_assignments:
            for assignment in existing_assignments:
                db.delete(assignment)
            db.commit()
            return {
                "message": "Label unassigned from ticket successfully",
            }
        else:
            ticket_label = TicketLabel(
                ticket_id=payload.ticket_id,
                label_id=payload.label_id
            )
            db.add(ticket_label)
            db.commit()
            db.refresh(ticket_label)
            return {
                "message": "Label assigned to ticket successfully",
            }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error assigning label to ticket: {str(e)}",
        )
    
def remove_label_from_ticket_in_db(request: Request, payload: TicketLabelRequestSchema, db: Session):
    try:
        org_id = request.state.user.org_id
        label = db.query(Label).filter(Label.id == payload.label_id, Label.org_id == org_id).first()
        if not label:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="Label not found"
            )
        
        existing_assignment = db.query(TicketLabel).filter(
            TicketLabel.ticket_id == payload.ticket_id,
            TicketLabel.label_id == payload.label_id
        ).first()

        if existing_assignment:
            db.delete(existing_assignment)
            db.commit()
            return {
                "message": "Label unassigned from ticket successfully",
            }
        else:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="Label is not assigned to this ticket"
            )
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error unassigning label from ticket: {str(e)}",
        )


def assign_release_to_ticket_in_db(request: Request, payload: dict, db: Session):
    try:
        org_id = request.state.user.org_id
        # Check if ticket exists
        ticket = db.query(Ticket).filter(Ticket.id == payload["ticket_id"]).first()
        if not ticket:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="Ticket not found"
            )
        
        # 1. Fetch or create the Release in organization
        release_name = payload["name"].strip()
        release = (
            db.query(Release)
            .filter(Release.org_id == org_id, Release.name == release_name)
            .first()
        )
        if not release:
            release = Release(org_id=org_id, name=release_name)
            db.add(release)
            db.flush()

        # 2. Check if the release is already linked to this ticket
        existing_link = (
            db.query(TicketRelease)
            .filter(TicketRelease.ticket_id == ticket.id, TicketRelease.release_id == release.id)
            .first()
        )

        if existing_link:
            db.delete(existing_link)
            db.commit()
            return {
                "message": "Release unassigned from ticket successfully",
            }
        else:
            ticket_release = TicketRelease(
                ticket_id=ticket.id,
                release_id=release.id
            )
            db.add(ticket_release)
            db.commit()
            return {
                "message": "Release assigned to ticket successfully",
            }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error toggling release on ticket: {str(e)}",
        )


def get_releases_from_db(request: Request, db: Session):
    try:
        org_id = request.state.user.org_id
        releases = (
            db.query(Release)
            .filter(Release.org_id == org_id)
            .all()
        )
        return {"releases": releases}
    except Exception as e:
        logger.error(
            f"Error fetching releases for organization_id: {request.state.user.org_id} - {str(e)}"
        )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error fetching releases: {str(e)}",
        )

    

