from sqlalchemy.orm import Session
from fastapi import HTTPException, status
from typing import Optional, List
from datetime import datetime
from . import repository
from .schema import SystemconfigurationCreate, SystemconfigurationUpdate, SystemconfigurationResponse
from user_management import repository as user_repo


def _get_or_raise(db: Session, entity_id: str) -> repository.Systemconfiguration:
    config = repository.get_by_id(db, entity_id)
    if not config:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"System configuration with id {entity_id} not found"
        )
    return config


def create_systemconfiguration(db: Session, data: SystemconfigurationCreate) -> SystemconfigurationResponse:
    existing = repository.get_by_key(db, data.key)
    if existing:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"System configuration with key '{data.key}' already exists"
        )

    if data.modified_by_user_id:
        user = user_repo.get_by_id(db, data.modified_by_user_id)
        if not user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"User with id {data.modified_by_user_id} not found"
            )

    try:
        config_data = data.model_dump()
        config_data["last_modified_date"] = datetime.utcnow()
        config = repository.create(db, config_data)
        db.commit()
        db.refresh(config)
        return SystemconfigurationResponse.model_validate(config)
    except Exception:
        db.rollback()
        raise


def list_systemconfigurations(
    db: Session,
    limit: int = 20,
    offset: int = 0,
    search: Optional[str] = None,
    data_type: Optional[str] = None,
) -> List[SystemconfigurationResponse]:
    configs = repository.list_all(db, limit, offset, search, data_type)
    return [SystemconfigurationResponse.model_validate(c) for c in configs]


def get_systemconfiguration(db: Session, entity_id: str) -> SystemconfigurationResponse:
    config = _get_or_raise(db, entity_id)
    return SystemconfigurationResponse.model_validate(config)


def get_systemconfiguration_by_key(db: Session, key: str) -> SystemconfigurationResponse:
    config = repository.get_by_key(db, key)
    if not config:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"System configuration with key '{key}' not found"
        )
    return SystemconfigurationResponse.model_validate(config)


def update_systemconfiguration(
    db: Session,
    entity_id: str,
    data: SystemconfigurationUpdate
) -> SystemconfigurationResponse:
    config = _get_or_raise(db, entity_id)

    update_data = data.model_dump(exclude_unset=True)

    if "key" in update_data and update_data["key"] != config.key:
        existing = repository.get_by_key(db, update_data["key"])
        if existing:
            raise HTTPException(
                status_code=status.HTTP_409_CONFLICT,
                detail=f"System configuration with key '{update_data['key']}' already exists"
            )

    if "modified_by_user_id" in update_data and update_data["modified_by_user_id"]:
        user = user_repo.get_by_id(db, update_data["modified_by_user_id"])
        if not user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"User with id {update_data['modified_by_user_id']} not found"
            )

    try:
        update_data["last_modified_date"] = datetime.utcnow()
        updated_config = repository.update(db, entity_id, update_data)
        db.commit()
        db.refresh(updated_config)
        return SystemconfigurationResponse.model_validate(updated_config)
    except Exception:
        db.rollback()
        raise


def delete_systemconfiguration(db: Session, entity_id: str) -> dict:
    config = _get_or_raise(db, entity_id)

    try:
        repository.delete(db, entity_id)
        db.commit()
        return {"message": f"System configuration {entity_id} deleted successfully"}
    except Exception:
        db.rollback()
        raise


def get_systemconfiguration_with_details(db: Session, entity_id: str) -> SystemconfigurationResponse:
    config = repository.get_with_details(db, entity_id)
    if not config:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"System configuration with id {entity_id} not found"
        )
    return SystemconfigurationResponse.model_validate(config)