import base64
import json
import aiohttp
import requests
from management.auth import get_access_token, get_client, get_sp_client
from msgraph.generated.sites.item.lists.item.items.items_request_builder import ItemsRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
import asyncio
from PIL import Image
from io import BytesIO

from datetime import timedelta
from msgraph.generated.models.event import Event
from msgraph.generated.models.item_body import ItemBody
from msgraph.generated.models.date_time_time_zone import DateTimeTimeZone
from msgraph.generated.models.body_type import BodyType
from msgraph.generated.models.free_busy_status import FreeBusyStatus
 
async def create_outlook_event_msgraph(user_email, subject, start_time, end_time, body_content, event_type):
    client = get_client()
 
    if event_type == 1:  # Ferie → all-day
        start_date = start_time.date().isoformat()
        end_date = (end_time.date() + timedelta(days=1)).isoformat()
 
        event = Event(
            subject=subject,
            body=ItemBody(content="", content_type=BodyType.Html),
            is_all_day=True,
            start=DateTimeTimeZone(date_time=start_date, time_zone="UTC"),
            end=DateTimeTimeZone(date_time=end_date, time_zone="UTC"),
            show_as=FreeBusyStatus.Tentative
        )
 
    else:
        start_time_naive = (start_time.replace(tzinfo=None) + timedelta(hours=2))
        end_time_naive   = (end_time.replace(tzinfo=None) + timedelta(hours=2))
        
        event = Event(
            subject=subject,
            body=ItemBody(content="", content_type=BodyType.Html),
            is_all_day=False,
            start=DateTimeTimeZone(date_time=start_time_naive.isoformat(), time_zone="Europe/Rome"),
            end=DateTimeTimeZone(date_time=end_time_naive.isoformat(), time_zone="Europe/Rome"),
            show_as=FreeBusyStatus.Tentative
        )
 
    created_event = await client.users.by_user_id(user_email).events.post(event)
    return created_event.id
 
async def confirm_outlook_event_msgraph(user_email, event_id, subject, start_time, end_time, body_content, event_type):
    client = get_client()
 
    if event_type == 1:  # Ferie → all-day
        start_date = start_time.date().isoformat()
        end_date = (end_time.date() + timedelta(days=1)).isoformat()
 
        event = Event(
            subject=f"{subject} - Approvato",
            body=ItemBody(content="", content_type=BodyType.Html),
            is_all_day=True,
            start=DateTimeTimeZone(date_time=start_date, time_zone="UTC"),
            end=DateTimeTimeZone(date_time=end_date, time_zone="UTC"),
            show_as=FreeBusyStatus.Oof       # Stato confermato
        )
    else:  # Permesso → orario specifico
        start_time_naive = (start_time.replace(tzinfo=None) + timedelta(hours=2))
        end_time_naive   = (end_time.replace(tzinfo=None) + timedelta(hours=2))
        
        event = Event(
            subject=f"{subject} - Approvato",
            body=ItemBody(content="", content_type=BodyType.Html),
            is_all_day=False,
            start=DateTimeTimeZone(date_time=start_time_naive.isoformat(), time_zone="Europe/Rome"),
            end=DateTimeTimeZone(date_time=end_time_naive.isoformat(), time_zone="Europe/Rome"),
            show_as=FreeBusyStatus.Oof
        )
 
    updated_event = await client.users.by_user_id(user_email).events.by_event_id(event_id).patch(event)
    return updated_event.id
 
async def delete_outlook_event_msgraph(user_email, event_id):
    client = get_client()
 
    try:
        await client.users.by_user_id(user_email).events.by_event_id(event_id).delete()
        print(f"Evento Outlook {event_id} cancellato per {user_email}")
    except Exception as e:
        print(f"Errore cancellazione evento Outlook {event_id}: {e}")

async def get_user_info(user_id):
    client = get_client()
    user = await client.users.by_user_id(user_id).get()
    return user

async def get_group_members(group_id):
    client = get_client()

    #import pdb
    #pdb.set_trace()
    query_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
        select=["id", "givenName", "surname", "mail", "accountEnabled"],
    )
    request_configuration = RequestConfiguration(
        query_parameters=query_params,
    )

    group_members = await client.groups.by_group_id(group_id).members.get(request_configuration=request_configuration)

    if hasattr(group_members, 'value'):
        
        for member in group_members.value:
            return [
                {"id": member.id, "givenName": member.given_name, "surname": member.surname, "mail": member.mail, "enabled":member.account_enabled}
                for member in group_members.value
            ]
    
async def get_project_managers(user):
    client = get_client()

    #import pdb
    #pdb.set_trace()

    site_id = "webearitsrl.sharepoint.com,94bd8a27-42d2-4f9c-a939-78ff92110b0c,041a114f-3ead-4cd4-853b-69f6d7a64f83"
    list_id = "16c6b6a8-eb64-41de-b003-10ce552c9913"
    
    query_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
        expand=["fields($select=Risorsa, CommessaLookupId)"], 
        select=["id", "fields"],
    )

    # Configurazione della richiesta
    request_configuration = RequestConfiguration(
        query_parameters=query_params,
    )
    
    # Richiesta per ottenere gli items dalla lista
    response = await client.sites.by_site_id(site_id).lists.by_list_id(list_id).items.get(
        request_configuration=request_configuration
    )

    project_managers = []

    for item in response.value:

        dict = item.fields.__dict__
        resources = dict["additional_data"]["Risorsa"]

        for resource in resources: 
            if resource["Email"] == user.mail:

                subquery_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
                    expand=["Fields"],
                    select=["id", "Fields"]
                )
                subrequest_configuration = RequestConfiguration(
                    query_parameters=subquery_params
                )

                job_id = dict["additional_data"]["CommessaLookupId"]
                subresponse = await client.sites.by_site_id(site_id).lists.by_list_id("960e2ccd-6955-4379-8af5-9e59f1233e30").items.by_list_item_id(job_id).get(
                    request_configuration=subrequest_configuration
                )

                sub_dict = subresponse.fields.__dict__
                project_managers.append(
                        {
                        "id": dict["additional_data"]["CommessaLookupId"],
                        "commessa_data": sub_dict["additional_data"]
                        }
                    )
                if sub_dict["additional_data"]["ResponsabileCommessaLookupId"] not in [pm["id"] for pm in project_managers]:
                    subsubquery_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
                        expand=["Fields($select=id,Title,Email)"],
                        select=["id, Fields"]
                    )
                    subsubrequest_configuration = RequestConfiguration(
                        query_parameters=subsubquery_params
                    )
                    
                    subsubresponse = await client.sites.by_site_id("root").lists.by_list_id("008f8bc3-9c69-44de-9962-3107f37419fe").items.by_list_item_id(sub_dict["additional_data"]["ResponsabileCommessaLookupId"]).get(
                        request_configuration=subsubrequest_configuration
                    )
                    subsub_dict = subsubresponse.fields.__dict__

                    # Aggiorna l'ultimo elemento della lista invece di creare un nuovo oggetto
                    project_managers[-1]["responsabile_id"] = sub_dict["additional_data"]["ResponsabileCommessaLookupId"]
                    project_managers[-1]["responsabile"] = subsub_dict["additional_data"]

    return project_managers
    
async def get_projects_cron(user_dict):
    client = get_client()
    sp_client = get_sp_client()

    # Recupera tutte le commesse con Stato '5'
    items = (
        sp_client.web.lists.get_by_id("960e2ccd-6955-4379-8af5-9e59f1233e30")
        .items.select(["Id", "Title", "ResponsabileCommessa/EMail", "ResponsabileProgetto/EMail", "Cliente/Id","GeneraApprovazione"])
        .expand(["ResponsabileCommessa", "ResponsabileProgetto", "Cliente"])
        .filter("Stato eq '5'")
        .top(5000)
        .get()
    )

    items.execute_query()

    # Recupera tutte le risorse in un'unica query per evitare chiamate multiple
    partecipanti_raw = (
        sp_client.web.lists.get_by_id("16c6b6a8-eb64-41de-b003-10ce552c9913")
        .items.select(["Id", "Commessa/Id", "Risorsa/EMail"])
        .expand(["Risorsa", "Commessa"])
        .top(5000)
        .get()
    )
    partecipanti_raw.execute_query()

    # Creiamo una mappa Commessa -> Email
    partecipanti_map = {}
    for p in partecipanti_raw:
        if p.properties.get("Commessa"):
            commessa_id = p.properties.get("Commessa")["Id"]  # Ottieni l'ID della Commessa
            risorse = p.properties.get("Risorsa", {})  # Dizionario di risorse (potrebbe essere vuoto)

            for key, risorsa in risorse.items():
                email = risorsa.get("EMail")  # Ottieni l'email
                if commessa_id and email:
                    if commessa_id not in partecipanti_map:
                        partecipanti_map[commessa_id] = []
                    partecipanti_map[commessa_id].append(email)

    sp_commessa = []
    sp_risorse = []

    # Iteriamo sulle commesse
    for item in items:
        commessa_id = item.properties.get("Id")
        if not commessa_id:
            continue  # Salta se manca l'ID

        resp_comm_id = user_dict.get(item.properties.get('ResponsabileCommessa', {}).get('EMail'))
        resp_proj_id = user_dict.get(item.properties.get('ResponsabileProgetto', {}).get('EMail'))

        client = item.properties.get("Cliente", {})
        cliente_id = client.get("Id")

        sp_commessa.append(
            Commessa(
                id=commessa_id,
                name=item.properties.get("Title"),
                resp_comm_id=resp_comm_id,
                resp_prog_id=resp_proj_id,
                client_id=cliente_id,
                approval=item.properties.get("GeneraApprovazione")
            )
        )
        partecipanti_email = partecipanti_map.get(commessa_id, [])
        partecipanti_id = [user_dict.get(email) for email in partecipanti_email if email in user_dict]

        for partecipante_id in partecipanti_id: 
            if partecipante_id:
                sp_risorse.append(
                    RisorseCommessa(
                        sp_co_id=commessa_id,
                        azure_id=partecipante_id
                    )
                )

    # # Query per ottenere i dati della lista con Lookup Expand
    # items = (
    #     sp_client.web.lists.get_by_id("960e2ccd-6955-4379-8af5-9e59f1233e30")
    #     .items.select(["ID", "Title", "ResponsabileCommessa/EMail","ResponsabileProgetto/EMail"])
    #     .expand(["ResponsabileCommessa", "ResponsabileProgetto"])
    #     .filter("Stato eq '5'")
    #     .get()
    # )
    # items.execute_query()
    # sp_commessa = []
    # sp_risorse = []
    # for item in items:
    #     partecipanti = (
    #         sp_client.web.lists.get_by_id("16c6b6a8-eb64-41de-b003-10ce552c9913")
    #         .items.select(["Risorsa/EMail"])
    #         .expand(["Risorsa"])
    #         .filter(f"Commessa eq '{item.properties['ID']}'")
    #         .get()
    #     )
    #     partecipanti.execute_query()

    #     emails = [info["EMail"] for info in partecipanti.properties.get("Risorsa", {}).values()]
        
    #     partecipanti_id = [user_dict.get(email) for email in emails if email in user_dict]
    #     # print(partecipanti_id.count)
    #     partecipanti_id = [pid for pid in partecipanti_id if pid is not None]

    #     resp_comm_id = user_dict.get(item.properties['ResponsabileCommessa']['EMail'])
    #     resp_proj_id = user_dict.get(item.properties['ResponsabileProgetto']['EMail'])
    #     sp_commessa.append(
    #         Commessa(
    #             id=item.properties['ID'],
    #             name=item.properties['Title'],
    #             resp_comm_id=resp_comm_id,
    #             resp_prog_id=resp_proj_id
    #         )
    #     )
    #     for partecipante_id in partecipanti_id:
    #         sp_risorse.append(
    #             RisorseCommessa(
    #                 sp_co_id=item.properties['ID'],
    #                 azure_id=partecipante_id
    #             )
    #         )

        # print(f"ID: {item.properties['ID']}, Titolo: {item.properties['Title']}, "
        #       f"Responsabile Commessa: {resp_comm_id}, Responsabile Progetto: {resp_proj_id}, Partecipanti: {partecipanti_id} ")

    return {"sp_commessa": sp_commessa, "sp_risorse": sp_risorse}







async def get_clients_cron():
    client = get_client()
    sp_client = get_sp_client()

    clients = (
        sp_client.web.lists.get_by_id("960e2ccd-6955-4379-8af5-9e59f1233e30")
        .items.select(["Cliente/Id", "Cliente/Title"]).expand(["Cliente"]).
        filter("Stato eq '5'")
        .top(5000)
        .get()

    )

    clients.execute_query()

    sp_clienti = []
    seen_ids = set()

    for client in clients:
        cliente = client.properties.get("Cliente", {})
        cliente_id = cliente.get("Id")
        if cliente_id not in seen_ids:
            seen_ids.add(cliente_id)
            sp_clienti.append(
                Cliente(
                    id=cliente_id,
                    title=cliente.get("Title")
                )
            )
    return {"sp_clienti": sp_clienti}




async def get_users_photo_cron(users):

    token = await get_access_token()
    headers = {
        "Authorization": f"Bearer {token}",
    }
    users_to_update = []

    async with aiohttp.ClientSession(headers=headers) as session:
        GRAPH_API_URL = "https://graph.microsoft.com/v1.0"


        for user in users:            
            user_id = user.id  
            photo_url = f"{GRAPH_API_URL}/users/{user_id}/photo/$value"

            async with session.get(photo_url) as response:
                if response.status == 200:
                    photo_bytes = await response.read()
                    image = Image.open(BytesIO(photo_bytes))
                    image = image.resize((48, 48))
                    buffered = BytesIO()
                    image.save(buffered, format="PNG")
                    photo_base64 = base64.b64encode(buffered.getvalue()).decode("utf-8")
                    
                    photo_base64_with_prefix = f"data:image/png;base64,{photo_base64}"

                    user.photo = photo_base64_with_prefix
                    users_to_update.append(user)
                else:
                    print(f"Photo {user_id} doesn't got {response.status}")
    return users_to_update




    # #import pdb
    # #pdb.set_trace()

    # site_id = "webearitsrl.sharepoint.com,94bd8a27-42d2-4f9c-a939-78ff92110b0c,041a114f-3ead-4cd4-853b-69f6d7a64f83"
    # list_id = "960e2ccd-6955-4379-8af5-9e59f1233e30"
    
    # subquery_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
    #     expand=["Fields($select=ID, ClienteLookupId, StatoLookupId, ResponsabileCommessaLookupId, ResponsabileProgettoLookupId, Title)"],
    #     select=["id", "Fields"],
    #     top=5000,
    #     filter=f"fields/StatoLookupId eq '5'"
    # )
    # subrequest_configuration = RequestConfiguration(
    #     query_parameters=subquery_params
    # )
    # subrequest_configuration.headers.add("Prefer","HonorNonIndexedQueriesWarningMayFailRandomly")
    # response = await client.sites.by_site_id(site_id).lists.by_list_id(list_id).items.get(
    #     request_configuration=subrequest_configuration
    # )

    # #return response.value[0].fields.__dict__

    # projects = []
    # for item in response.value:

    #     sub_dict = item.fields.__dict__

    #     subsubquery_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
    #         expand=["Fields($select=Title)"],
    #         select=["id", "Fields"]
    #     )
    #     subsubrequest_configuration = RequestConfiguration(
    #         query_parameters=subsubquery_params
    #     )
    #     client_id = sub_dict["additional_data"]["ClienteLookupId"]
    #     subsubresponse = await client.sites.by_site_id(site_id).lists.by_list_id("7f7616fc-47ad-402d-bc5f-3489fe3d779f").items.by_list_item_id(client_id).get(
    #         request_configuration=subsubrequest_configuration
    #     )
    #     subsub_dict = subsubresponse.fields.__dict__

    #     query_params_res = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
    #         expand=["fields($select=Risorsa, CommessaLookupId)"], 
    #         select=["fields"],
    #         top=5000,
    #         filter=f"fields/CommessaLookupId eq '{sub_dict['id']}'"
    #     )

    #     # Configurazione della richiesta
    #     request_configuration_res = RequestConfiguration(
    #         query_parameters=query_params_res
    #     )
    #     request_configuration_res.headers.add("Prefer","HonorNonIndexedQueriesWarningMayFailRandomly")
        
    #     # Richiesta per ottenere gli items dalla lista
    #     response_res = await client.sites.by_site_id(site_id).lists.by_list_id("16c6b6a8-eb64-41de-b003-10ce552c9913").items.get(
    #         request_configuration=request_configuration_res
    #     )

    #     projects.append(
    #         {
    #         "id": f'{sub_dict["id"]}',
    #         "name": f"{subsub_dict['additional_data']['Title']} - {sub_dict['additional_data']['Title']}" ,

    #         "resources" : response_res.__dict__
    #         }
    #     )
    # projects_list = sorted(projects, key=lambda x: x["name"], reverse=False)
    # return projects_list

async def get_projects(user):
    client = get_client()

    #import pdb
    #pdb.set_trace()

    site_id = "webearitsrl.sharepoint.com,94bd8a27-42d2-4f9c-a939-78ff92110b0c,041a114f-3ead-4cd4-853b-69f6d7a64f83"
    list_id = "16c6b6a8-eb64-41de-b003-10ce552c9913"
    
    query_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
        expand=["fields($select=Risorsa, CommessaLookupId)"], 
        select=["id", "fields"],
        top=5000
    )

    # Configurazione della richiesta
    request_configuration = RequestConfiguration(
        query_parameters=query_params,
    )
    
    # Richiesta per ottenere gli items dalla lista
    response = await client.sites.by_site_id(site_id).lists.by_list_id(list_id).items.get(
        request_configuration=request_configuration
    )
    projects = []
    for item in response.value:

        dict = item.fields.__dict__
        resources = dict["additional_data"]["Risorsa"]

        for resource in resources: 
            if resource["Email"] == user.mail:
                subquery_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
                    expand=["Fields($select=ClienteLookupId, StatoLookupId, Title)"],
                    select=["id", "Fields"],
                    top=5000,
                    filter=f"fields/StatoLookupId eq '5'"
                )
                subrequest_configuration = RequestConfiguration(
                    query_parameters=subquery_params
                )
                subrequest_configuration.headers.add("Prefer","HonorNonIndexedQueriesWarningMayFailRandomly")
                job_id = dict["additional_data"]["CommessaLookupId"]
                subresponse = await client.sites.by_site_id(site_id).lists.by_list_id("960e2ccd-6955-4379-8af5-9e59f1233e30").items.by_list_item_id(job_id).get(
                    request_configuration=subrequest_configuration
                )

                sub_dict = subresponse.fields.__dict__

                subsubquery_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(
                    expand=["Fields($select=Title)"],
                    select=["id", "Fields"]
                )
                subsubrequest_configuration = RequestConfiguration(
                    query_parameters=subsubquery_params
                )
                client_id = sub_dict["additional_data"]["ClienteLookupId"]
                subsubresponse = await client.sites.by_site_id(site_id).lists.by_list_id("7f7616fc-47ad-402d-bc5f-3489fe3d779f").items.by_list_item_id(client_id).get(
                    request_configuration=subsubrequest_configuration
                )
                subsub_dict = subsubresponse.fields.__dict__
                projects.append(
                    {
                    "id": f'{dict["additional_data"]["CommessaLookupId"]}',
                    "name": f"{subsub_dict['additional_data']['Title']} - {sub_dict['additional_data']['Title']}" ,
                    }
                )
    projects_list = sorted(projects, key=lambda x: x["name"], reverse=False)
    return projects_list
'''

import requests
from management.auth import get_access_token

def get_group_members(group_id):

    group_id = "3fd16536-7c95-4b48-ad14-696255ce7d74"
    url = f"https://graph.microsoft.com/v1.0/groups/{group_id}/members"

    access_token = get_access_token()

    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }

    members_response = requests.get(url, headers=headers)

    if members_response.status_code != 200:
        raise Exception(f"Errore nel recuperare i membri del gruppo: {members_response.json()}")

    # Restituisci i membri
    return members_response.json()

'''


'''
import requests
import os

from management.utils.auth_token_decorator import get_token_auth_header

def get_group_members(token, group_id):

    # Usa il token di accesso per chiamare Microsoft Graph
    graph_url = f"https://graph.microsoft.com/v1.0/groups/{group_id}/members"
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json',
    }

    members_response = requests.get(graph_url, headers=headers)

    if members_response.status_code != 200:
        raise Exception(f"Errore nel recuperare i membri del gruppo: {members_response.json()}")

    # Restituisci i membri
    return members_response.json()
'''
