from sqlalchemy.orm import Session,joinedload
from sqlalchemy import or_
from fastapi import HTTPException, status, Request
from models.user_model import User, PlatformRole, OrgRole
from models.organization_model import Organization
from utils.logging import logger
from models.organization_registration_request import OrganizationRegistrationRequest
from schema.orgnaization_registration_request_schema import OrganizationRegistrationRequestSchema,UpdateOrganizationRegistrationRequest
from utils.pagination import get_paginated_response
from slugify import slugify
from utils.hashing_password import hash_password

def get_all_organization_registration_requests_from_db(
    db: Session,
    request:Request,
    limit: int = 10,
    page: int = 0,
    request_status: str = None,
    search: str = None,
    order_by: str = "created_at"
):
    try:

        query = (
            db.query(OrganizationRegistrationRequest)
            .options(
                joinedload(
                    OrganizationRegistrationRequest.request_reviewer
                ).load_only(
                    User.name,
                    User.email,
                    User.platform_role
                )
            )
        )

        # Status filter
        if request_status:
            query = query.filter(
                OrganizationRegistrationRequest.status == request_status
            )

        # Search filter
        if search:
            logger.info(f"Inside search: {search}")

            search_term = f"%{search.strip()}%"

            query = query.filter(
                or_(
                    OrganizationRegistrationRequest.company_name.ilike(search_term),
                    OrganizationRegistrationRequest.contact_name.ilike(search_term),
                    OrganizationRegistrationRequest.contact_email.ilike(search_term),
                )
            )

        # Ordering
        if order_by and hasattr(OrganizationRegistrationRequest, order_by):
            logger.info(f"Order: {order_by}")
            query = query.order_by(
                getattr(OrganizationRegistrationRequest, order_by)
            )

        # Pagination
        paginated_data = get_paginated_response(
            query=query,
            page=page,
            limit=limit,
            request=request
        )

        return paginated_data

    except Exception as e:
        logger.exception(
            f"Error while getting organization registration requests: {str(e)}"
        )

        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Error while getting organization registration requests"
        )


def create_organization_registration_request(
    request: OrganizationRegistrationRequestSchema,
    db: Session,
):
    try:
        logger.info(f"Organization registration request received: {request.dict()}")

        existing_request = (
        db.query(OrganizationRegistrationRequest)
            .filter(
                OrganizationRegistrationRequest.contact_email
                == request.contact_email
            )
            .first()
        )

        if existing_request:
            raise HTTPException(
                status_code=status.HTTP_409_CONFLICT,
                detail="You have already submitted your request!",
            )

        new_request = OrganizationRegistrationRequest(
            company_name=request.company_name,
            contact_name=request.contact_name,
            contact_email=request.contact_email,
            contact_phone=request.contact_phone,
            message=request.message,
        )

        db.add(new_request)
        db.commit()
        db.refresh(new_request)

        return {
            "message": "Request submitted successfully!",
        }

    except HTTPException as e:
        raise e

    except Exception as e:
        db.rollback()

        logger.error(
            f"Error while creating organization registration request: {str(e)}"
        )

        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Something went wrong while submitting request.",
        )
    

def update_organization_registration_request_status(
    request_id: UpdateOrganizationRegistrationRequest,
    current_user: str,
    db: Session
):
    try:

        request = (
            db.query(OrganizationRegistrationRequest)
            .filter(
                OrganizationRegistrationRequest.id == request_id.id
            )
            .first()
        )

        if not request:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Request not found"
            )

        if current_user.platform_role != PlatformRole.SUPER_ADMIN:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You don't have permission to perform this action"
            )

        # Update request status
        request.status = request_id.status
        request.reviewed_by = current_user.id

        logger.info(
            f"Request status updated to "
            f"{request_id.status} "
            f"for request id: {request_id.id}"
        )

        # APPROVED FLOW
        if request_id.status == "COMPLETED":

            logger.info(
                f"Creating organization and admin user "
                f"for request id: {request_id.id}"
            )

            # Check existing user
            existing_user = (
                db.query(User)
                .filter(User.email == request.contact_email)
                .first()
            )

            if existing_user:
                raise HTTPException(
                    status_code=400,
                    detail="User already exists"
                )

            # Create org admin user
            create_org_admin = User(
                name=request.contact_name,
                email=request.contact_email,
                password=hash_password("DefaultPassword123!"),
                platform_role=PlatformRole.USER,
                org_role=OrgRole.ORG_ADMIN,
                is_active=True,
                is_verified=True
            )

            db.add(create_org_admin)

            # flush => generates user.id
            db.flush()

            # Create organization
            new_org = Organization(
                name=request.company_name,
                slug=slugify(request.company_name),
                owner_id=create_org_admin.id,
                status="ACTIVE"
            )

            db.add(new_org)

            db.flush()

            # Link org to user
            create_org_admin.org_id = new_org.id

            logger.info(
                f"Organization and admin created successfully "
                f"for request id: {request_id.id}"
            )

        # FINAL COMMIT ONLY ON SUCCESS
        db.commit()

        return {
            "message": (
                f"Request status updated to "
                f"{request_id.status} successfully!"
            )
        }

    except HTTPException as e:
        db.rollback()
        raise e

    except Exception as e:
        db.rollback()

        logger.error(
            f"Error while updating request status: {str(e)}"
        )

        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=str(e)
        )