from typing import Any, Dict, Optional, Tuple, List
from app.core.database.operations import get_items_from_database
from app.models.registry import MODEL_REGISTRY
from app.services.crud_services import add_service, delete_service, get_by_id_service, update_service
from app.services.options_services import get_options_service
from app.services.images_services import delete_images_by_item_id_service


# Adds an item to its original table and the items table
def add_item_service(
        model_name: str, item_data: Dict[str, Any]) -> Tuple[Dict[str, Any], List[int]]:
    if not model_name:
        return ({'error': 'Neophodno ime modela'}, [400])

    if not item_data:
        return ({'error': 'Nedostaju neophodni podaci'}, [400])

    response, status_codes = add_service(
        model_name=model_name, item_data=item_data, return_column='id')
    if isinstance(response, dict) and 'error' in response:
        return (response, status_codes)

    item_data = {
        'model_name': model_name,
        'ref_item_id': response,
    }

    return add_service(model_name='item', item_data=item_data)


# Returns a dict from the items table and adds the property name to it
def list_items_service(model_name: str,
                       filters: Optional[Dict[str,
                                              Any]] = None) -> Tuple[Dict[str,
                                                                          Any],
                                                                     List[int]]:
    table_name = MODEL_REGISTRY[model_name]['metadata']['table_name']

    response = get_items_from_database(
        table_name=table_name, conditions=filters)

    if isinstance(response, dict) and 'error' in response:
        return (response, [500])

    return (response, [200])


# Returns apartment/building data using the id from the items table
def get_item_details_service(id: int) -> Tuple[Dict[str, Any], List[int]]:
    if not id:
        return ({'error': 'Neophodan ID'}, [400])

    response = get_items_from_database('items', {'id': id})
    if isinstance(response, dict) and 'error' in response:
        return {'error': response}, [500]
    if not response:
        return {'error': 'Nije pronađeno'}, [404]

    item = response[0]
    model_name = item.get('model_name')

    model_name = item.get('model_name')
    ref_item_id = item.get('ref_item_id')

    if not ref_item_id:
        return ({'error': 'Nedostaje ref_item_id u items tabeli'}, [500])

    return get_by_id_service(model_name=model_name, id=ref_item_id)


def update_item_service(
        id: int, item_data: Dict[str, Any]) -> Tuple[Dict[str, Any], List[int]]:
    if not id:
        return ({'error': 'Neophodan ID'}, [400])

    if not item_data:
        return ({'error': 'Nedostaju neophodni podaci'}, [400])

    response = get_items_from_database(
        table_name='items', conditions={'id': id})

    if isinstance(response, dict) and 'error' in response:
        return {'error': response}, [500]
    if not response:
        return {'error': 'Nije pronađeno'}, [404]

    item = response[0]

    model_name = item.get('model_name')

    model_name = item.get('model_name')
    ref_item_id = item.get('ref_item_id')

    if not ref_item_id:
        return ({'error': 'Nedostaje ref_item_id u items tabeli'}, [500])

    return update_service(
        model_name=model_name,
        item_data=item_data,
        id=ref_item_id)


def delete_item_service(id: int) -> Tuple[Dict[str, Any], List[int]]:
    if not id:
        return ({'error': 'Neophodan ID'}, [400])

    response = get_items_from_database(
        table_name='items', conditions={'id': id})
    if isinstance(response, dict) and 'error' in response:
        return {'error': response}, [500]
    if not response:
        return {'error': 'Nije pronađeno'}, [404]

    item = response[0]
    model_name = item.get('model_name')

    model_name = item.get('model_name')
    ref_item_id = item.get('ref_item_id')

    if not ref_item_id:
        return ({'error': 'Nedostaje ref_item_id u items tabeli'}, [500])

    table_name = MODEL_REGISTRY[model_name]['metadata']['table_name']

    if table_name == 'buildings':
        new_apartments = get_items_from_database(
            table_name='new_apartments', conditions={
                'building_id': ref_item_id})
        if isinstance(new_apartments, dict) and 'error' in new_apartments:
            return (new_apartments, [500])

        if new_apartments:
            return (
                {'error': 'Još uvek postoje apartmani u ovoj zgradi'}, [400])

    if table_name == 'apartment_types':
        new_apartments = get_items_from_database(
            table_name='new_apartments', conditions={
                'type_id': ref_item_id})
        if isinstance(new_apartments, dict) and 'error' in new_apartments:
            return (new_apartments, [500])

        if new_apartments:
            return (
                {'error': 'Još uvek postoje apartmani u okviru ovog tipa apartmana'}, [400])

    if table_name == 'projects':
        buildings = get_items_from_database(
            table_name='buildings', conditions={
                'project_id': ref_item_id})
        if isinstance(buildings, dict) and 'error' in buildings:
            return (buildings, [500])
        else:
            types = get_items_from_database(
                table_name='apartment_types', conditions={
                    'project_id': ref_item_id})
            if isinstance(types, dict) and 'error' in types:
                return (types, [500])
        if buildings or types:
            return (
                {'error': 'Još uvek postoje zgrade ili tipovi apartmana u ovom projektu'}, [400])

    response, status_codes = delete_service(
        model_name=model_name, id=ref_item_id)
    if 'error' in response:
        return (response, status_codes)

    response, status_codes = delete_images_by_item_id_service(id=id)
    if 'error' in response:
        return (response, status_codes)

    return delete_service(model_name='item', id=id)


# Returns a dictionary mapping the id in the items table to the relevant
# data in the ref_model for each item
def get_item_options_service() -> Tuple[Dict[str, Any], List[int]]:
    # Fetch all items
    items = get_items_from_database(table_name='items')
    if isinstance(items, dict) and 'error' in items:
        return ({'error': items}, [500])
    apartments = get_items_from_database(table_name='lots_renting')
    if isinstance(apartments, dict) and 'error' in apartments:
        return ({'error': items}, [500])

    # Determine all model names needed
    model_names = set(item['model_name'] for item in items)
    # Fetch all related data for each model, and extract relevant label fields
    model_data = {}
    for model_name in model_names:
        reduced_data, _ = get_options_service(model_name=model_name)

        model_data[model_name] = reduced_data

    # Build final result using items
    result = {}
    for item in items:
        model_name = item['model_name']
        ref_id = item['ref_item_id']
        item_id = item['id']

        label_data = model_data.get(model_name, {}).get(ref_id)
        if label_data:
            result[str(item_id)] = {
                **label_data,
                'model_name': model_name
            }

    return (result, [200])
