from uuid import UUID
from sqlalchemy.orm import Session, load_only,joinedload
from fastapi import HTTPException,status, Request
from models.organization_model import Organization
from models.user_model import User
from utils.pagination import get_paginated_response
from schema.organization_schema import OrganizationCreateRequest
from utils.logging import logger
from slugify import slugify
from sqlalchemy import extract
from datetime import datetime

def get_all_organization(db:Session,request:Request, page=1, limit=10, status: str = None, search: str = None):
    try:
        all_organizations=db.query(Organization).options(
            joinedload(Organization.owner).load_only(
                    User.name,
                    User.email,
                    User.platform_role,
                    User.is_active,
                    User.is_verified
                )
        )
        
        if status:
            all_organizations = all_organizations.filter(Organization.status == status)
            
        if search:
            search_query = f"%{search}%"
            all_organizations = all_organizations.filter(
                (Organization.name.ilike(search_query)) | 
                (Organization.slug.ilike(search_query))
            )
            
        paginated_data = get_paginated_response(
            query=all_organizations,
            page=page,
            limit=limit,
            request=request
        )
        return paginated_data
    except HTTPException as e:
        raise e

    except Exception as e:
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong!! {str(e)}")
    
def create_new_organization(request:OrganizationCreateRequest,db:Session):
    try:
        check_if_user_exits=db.query(User).filter(User.id==request.owner_id).first()
        if not check_if_user_exits:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User doesn't exits!")
        if check_if_user_exits.is_active==False:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="User is not active!")
        if check_if_user_exits.is_verified==False:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="User is not verified!")
            
        check_if_same_name_exits=db.query(Organization).filter(Organization.name==request.name).first()
        if check_if_same_name_exits:
            raise HTTPException(status_code=status.HTTP_208_ALREADY_REPORTED, detail="Organization with same name already exits!")
        if request.slug:
            slug_name=slugify(request.slug)
        else:
            slug_name=slugify(request.name)
        if db.query(Organization).filter(Organization.slug==slug_name).first():
            raise HTTPException(status_code=status.HTTP_208_ALREADY_REPORTED, detail="Organization with same slug already exits!")

        create_org=Organization(
            name=request.name,
            slug=slug_name,
            logo_url=request.logo_url,
            owner_id=request.owner_id
        )
        db.add(create_org)
        db.commit()
        db.refresh(create_org)
        return{
            "message":"Organization created successfully!"
        }
    except HTTPException as e:
        raise e

    except Exception as e:
        db.rollback()
        logger.error(f"Error while creating org: {str(e)}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong while creating organization!! {str(e)}")

def update_org_details(request:OrganizationCreateRequest,db:Session,org_slug:str):
    try:
        check_org=db.query(Organization).filter(Organization.slug==org_slug).first()
        if not check_org:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Organization doesn't exits!")
        if request.name:
            check_if_same_name_exits=db.query(Organization).filter(Organization.name==request.name,Organization.id!=check_org.id).first()
            if check_if_same_name_exits:
                raise HTTPException(status_code=status.HTTP_208_ALREADY_REPORTED, detail="Organization with same name already exits!")
            check_org.name=request.name
        if request.slug:
            check_if_slug_exits=db.query(Organization).filter(Organization.slug==slugify(request.slug),Organization.id!=check_org.id).first()
            if check_if_slug_exits:
                raise HTTPException(status_code=status.HTTP_208_ALREADY_REPORTED, detail="Organization with same slug already exits!")
            check_org.slug=slugify(request.slug)
        if request.logo_url:
            check_org.logo_url=request.logo_url
        if request.status:
            check_org.status=request.status
        db.commit()
        db.refresh(check_org)
        return{
            "message":"Organization updated successfully!"
        }
    except HTTPException as e:
        raise e
    except Exception as e:
        db.rollback()
        logger.error(f"Error while updating org: {str(e)}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong while updating organization!! {str(e)}")

def get_org_by_slug(db: Session, org_slug: str):
    try:
        org = db.query(Organization).options(
            joinedload(Organization.owner).load_only(
                User.name,
                User.email,
                User.platform_role,
                User.is_active,
                User.is_verified
            )
        ).filter(Organization.slug == org_slug).first()
        
        if not org:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Organization not found")
        
        return org
    except HTTPException as e:
        raise e
    except Exception as e:
        logger.error(f"Error while fetching org by slug: {str(e)}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong!! {str(e)}")

def check_slug_availability(db: Session, slug: str):
    try:
        slug_name = slugify(slug)
        org = db.query(Organization).filter(Organization.slug == slug_name).first()
        if org:
            return {"available": False, "message": "Slug is already taken"}
        return {"available": True, "message": "Slug is available"}
    except Exception as e:
        logger.error(f"Error while checking slug availability: {str(e)}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong!! {str(e)}")

def get_organizations_by_owner(db: Session, request: Request, owner_id: UUID, page: int = 1, limit: int = 10):
    try:
        query = db.query(Organization).options(
            joinedload(Organization.owner).load_only(
                User.name,
                User.email,
                User.platform_role,
                User.is_active,
                User.is_verified
            )
        ).filter(Organization.owner_id == owner_id)
        
        paginated_data = get_paginated_response(
            query=query,
            page=page,
            limit=limit,
            request=request
        )
        return paginated_data
    except Exception as e:
        logger.error(f"Error while fetching owner organizations: {str(e)}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong!! {str(e)}")

def search_organization(db: Session, request: Request, query: str, page: int = 1, limit: int = 10):
    try:
        search_query = f"%{query}%"
        query_obj = db.query(Organization).options(
            joinedload(Organization.owner).load_only(
                User.name,
                User.email,
                User.platform_role,
                User.is_active,
                User.is_verified
            )
        ).filter(
            (Organization.name.ilike(search_query)) | 
            (Organization.slug.ilike(search_query))
        )
        
        paginated_data = get_paginated_response(
            query=query_obj,
            page=page,
            limit=limit,
            request=request
        )
        return paginated_data
    except Exception as e:
        logger.error(f"Error while searching organizations: {str(e)}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong!! {str(e)}")


def delete_organization(db:Session,org_slug:str, org_id:UUID):
    try:
        logger.info(f"Deleting organization with slug: {org_slug} and id: {org_id}")
        check_org=db.query(Organization).filter(Organization.slug==org_slug,Organization.id==org_id).first()
        if not check_org:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Organization doesn't exits!")
        db.delete(check_org)
        db.commit()
        return{
            "message":"Organization deleted successfully!"
        }
    except HTTPException as e:
        raise e
    except Exception as e:
        db.rollback()
        logger.error(f"Error while deleting org: {str(e)}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong while deleting organization!! {str(e)}")

def get_organization_monthly_growth(db: Session):
    try:
        current_year = datetime.now().year
        orgs = db.query(Organization).filter(extract('year', Organization.created_at) == current_year).all()
        
        monthly_counts = [0] * 12
        for org in orgs:
            if org.created_at:
                month_index = org.created_at.month - 1
                monthly_counts[month_index] += 1
                
        return {"data": monthly_counts}
    except Exception as e:
        logger.error(f"Error fetching monthly growth: {str(e)}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Something went wrong!! {str(e)}")