from datetime import datetime
from typing import List
from pyspark.sql.types import *

class Process:
    @classmethod
    def columns(cls, data: dict, fields_column, fields_display) -> dict:
        """
            Receives a dictionary with the data of a work item and returns the data with the selected fields.
        """
        fields = [
          {column.name: data[tag]['displayName']} if tag in fields_display and tag in data \
              else ({column.name: data[tag]} if tag in data else {column.name: None}) for tag, column in fields_column.items()]
      
        date_type_fields = [schema.name for name, schema in fields_column.items() if schema.dataType == DateType()]
        schema_convert_date = [
            {
                name: cls.datetime_to_date(schema)
            } if name in date_type_fields and schema != None else {name:schema} for item in fields for name, schema in item.items()]
        item = {}
        for value in schema_convert_date:
            for column, tag in value.items():
                item[column] = tag
        return item

    @classmethod
    def all_teams(cls, response: dict) -> List[dict]:
        """
            Receives data from all squads and returns `name and id`.
        """
        comprehension = [
            {
            'Squad': values['name'],
            'Id': values['id'],
            } for values in response['value']]
        return comprehension

    @classmethod
    def team_backlog(cls, response: dict) -> List[int]:
        """
            Receives a dictionary and returns a list of ids.
        """
        ids = []
        for list_value in response.values():
            for value in list_value:
                id = str(value['target']['id'])
                ids.append(id)                
        return ids

    @classmethod
    def team_interation(cls, response: dict, squad: str) -> List[dict]:
        """
            Receives a dictionary and returns a list of iteration information.
        """
        comprehension = [
            {
            'Iteration_Id': values['id'],
            'Iteration_Name': values['name'],
            'Iteration_Path': values['path'],
            'Iteration_Start_Date': cls.datetime_to_date(values['attributes']['startDate']) if values['attributes']['startDate'] else None,
            'Iteration_End_Date': cls.datetime_to_date(values['attributes']['finishDate']) if values['attributes']['finishDate'] else None,
            'Iteration_State': values['attributes']['timeFrame'],
            'Squad': squad
            } for values in response['value']
            ]
        return comprehension
    
    @classmethod
    def members(cls, response: dict, squad: str) -> List[dict]:
        """
            Receives a dictionary and the name of a squad and returns a list of all squad members.
        """
        members = []
        for value in response['value']:
            info = value['identity']
            member = {'Name':info['displayName'], 'Id': info['id'], 'squad': squad}
            members.append(member)
        return members
    
    @staticmethod
    def datetime_to_date(str_datetime: str):
        """
            Receives a datetime in string and turns it into a date object.
        """
        date = str_datetime[:str_datetime.find('T')]
        return datetime.fromisoformat(date).date()
    
    @classmethod
    def tags(cls, response: dict) -> List[dict]:
        """
            Receives a dictionary and returns a list comprehension of all tags and their ids.
        """
        return [{'Id':item['id'], 'Name':item['name']} for item in response['value']]
      
    @classmethod
    def all_process(cls, response: dict) -> List[dict]:
        """
            Receives a dictionary and returns a list of dict with process id and value.
            [{'id':...,'name': Basic}]
        """
        return [{'id':values['typeId'], 'name':values['name']} for values in response['value']]
    
    @classmethod
    def all_work_items(cls, response: dict) -> List[dict]:
        """
            Receives a dictionary and returns only the item id.
        """
        return [values['id'] for values in response['value']]
    
    
    @classmethod
    def clean_fields(cls, response: dict) -> List[dict]:
        """
            Receives a dictionary with the process fields and returns only the referenceName, name and type.
            [ {'referenceName':'System.Tag', 'name':'Tag', 'type': 'string'},... ]
        """
        return [{'referenceName': values['referenceName'], 'name': values['name'], 'type': values['type']} for values in response['value']]
 
    @classmethod
    def spark_equivalent(cls, fields:list) -> List[dict]:
        schema = {}
        spark_types = {
            'string': StringType(),
            'integer': IntegerType(),
            'double': DoubleType(),
            'boolean': BooleanType(),
            'html': StringType(),
            'dateTime': DateType()
        }
        for item in fields:
            ref_name = item['referenceName']
            name = item['referenceName'].split('.')[-1]
            type_field = spark_types.get(item['type'])
            field = StructField(name, type_field)
            schema[ref_name] = field
        return schema