from requests import api
import json


class Auth:
    def __init__(self,url_login,payload_auth,url_logout):
        """
        Auth    :
        ce module permet se connecter pour récupérer le token qui sera utilisé
        pour ApiCRUD et de se deconnecter une fois le travail fini

        CONSTRUCTOR :
            url_login:str       endpoint for login
            payload_auth:dict   dictionary contains information for auth
            url_logout:str      endpoint for logout 

        METHODS     :

            login   log and return Response you can use json() method for get information user
            logout  logout 


        Example         

        >>> url_login = "http://localhost:8000/api/auth/login/"    
        >>> url_logout = "http://localhost:8000/api/auth/logout/"
        >>> user = {"username":"gracy",password:"1234Coding"}
        >>> gracy  = Auth(url_login,user,url_logout)
        >>> gracy.login
            <Response [200]>
        >>> gracy.login.json()
            {'access': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzUyODI4MjMzLCJpYXQiOjE3NTI4Mjc5MzMsImp0aSI6ImVjMzk3Njc2OWMzMzQzMTQ5MGJmYjMzNjU0MWQzMzE1IiwidXNlcl9pZCI6NH0.-c1p4yEH-FXRIBuwkmSG9_nLmHZ52YS-g2BVspu4ouo',
            'refresh': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTc1MjkxNDMzMywiaWF0IjoxNzUyODI3OTMzLCJqdGkiOiI5ZDI2ZDQ2ODM3NmI0OTA2ODlkODIyODAxNTg2ZDI3OSIsInVzZXJfaWQiOjR9.4sLko1OFKsGPfWjA60wWepdNzvy02_AJE0A_dNqP0t8',
            'user': {'pk': 4,
            'username': 'gracy',
            'email': '',}}


        """
        self.user = payload_auth
        self.headers = {
            "content-type":"application/json",
        }
        self.login_url = url_login
        self.logout_url = url_logout
        self.login

    @property
    def login(self): # login and return user value with token 
        """
        Example 

        >>> user = {"username":"gracy",password:"1234Coding"}
        >>> gracy  = Auth(url_login,user,url_logout)
        >>> gracy.login
            <Response [200]>
        >>> gracy.login.json()
            {'access': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzUyODI4MjMzLCJpYXQiOjE3NTI4Mjc5MzMsImp0aSI6ImVjMzk3Njc2OWMzMzQzMTQ5MGJmYjMzNjU0MWQzMzE1IiwidXNlcl9pZCI6NH0.-c1p4yEH-FXRIBuwkmSG9_nLmHZ52YS-g2BVspu4ouo',
            'refresh': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTc1MjkxNDMzMywiaWF0IjoxNzUyODI3OTMzLCJqdGkiOiI5ZDI2ZDQ2ODM3NmI0OTA2ODlkODIyODAxNTg2ZDI3OSIsInVzZXJfaWQiOjR9.4sLko1OFKsGPfWjA60wWepdNzvy02_AJE0A_dNqP0t8',
            'user': {'pk': 4,
            'username': 'gracy',
            'email': '',}}
        """

        try:
            log = api.post(self.login_url,data=json.dumps(self.user),headers=self.headers)
            if log.status_code == 200 :
                return log
            return log
            
        except Exception as e:
            print(e) 

    @property
    def logout(self): # logout 
        """
        logout a user

        Example 
        >>> gracy.logout
            <Response [200]>
        >>> gracy.logout.json()
            {'detail': 'Successfully logged out.'}
        """
        logout = api.post(self.logout_url)
        if logout.status_code ==200:
            return logout
        return logout




class ApiCRUD:
    def __init__(self,url_endpoint,url_user =None,token=None):
        """
        Help on ApiCRUD :
        NAME :
            ApiCRUD         do operation CRUD

        CONSTRUCTOR     :
            url_endpoint:str    define url endpoint
            url_user:str        endpoint for user value
            token:str           token for authentification

        Modules :

            get_user    return Response with value user
            all         return Respone with all data 
            one         return Response with one data
            createOne   create data and return it 
            createMany  create many data and return list of Response
            updateOne   update data and return response
            updateMany  updata many data and return list of Response
            deleteOne   delete data and response
            deleteMany  delete many data and return list of Response

        Example


        """
        self.url  = url_endpoint
        self.url_user = url_user
        self.headers = {
            "content-type":"application/json"
        }
        if token:
            self.headers["Authorization"] = f"Bearer {token}" or f"Token {token}" or f"Key {token}"
    

    @property
    def get_user(self):
        """
        return user value
        
        Example

        >>> url = 'http://localhost:8000/api/branch/'
        >>> url_user = 'http://localhost:8000/api/auth/user/'
        >>> instance = ApiCRUD(url,url_user,token)
        >>> instance.get_user
            <Response [200]>
        

        """
        if self.url_user:
            return api.get(self.url_user,headers=self.headers)
        else:
            raise ValueError("Not given : url_user attribute",)
   

    
        
    def all(self):
        """
        return all data [list]

        Example 
            >>> url = 'http://localhost:8000/api/branches/'
            >>> url_user = 'http://localhost:8000/api/auth/user/'
            >>> instance = ApiCRUD(url,url_user,tok_mut)
            >>> instance.all() # you can use json() method for return json value
                <Response [200]>
            >>> instance.all().json()
                [{'id':1,'branch':'Musik','id':2,'branch':'Math'}]
        """

        return api.get(self.url)
    
    def range(self,start=0,end=0,step=1):

        return api.get(self.url).json()[start:end:step]
    
    
    def one(self,id):
        """
        return one data [dict]

        ARGS    :
                id  : id of one data

        Example 

            >>> url = 'http://localhost:8000/api/branches/'
            >>> url_user = 'http://localhost:8000/api/auth/user/'
            >>> instance = ApiCRUD(url,url_user,tok_mut)
            >>> instance.one(1) # you can use json() method for return json value
                <Response [200]>
            >>> instance.one(1).json()
                {'id':1,'branch':'Musik'}

        """
        return api.get(self.url+f'{id}/')

    def createOne(self,payload):
        """
        Description     :
                        create one data
        
        return value created [dict]

        ARGS    :
                playload    : data to create must be a dictionary ({})

        Example 

            >>> url = 'http://localhost:8000/api/branches/'
            >>> url_user = 'http://localhost:8000/api/auth/user/'
            >>> instance = ApiCRUD(url,url_user,tok_mut)
            >>> payload =  {'branch':'IT'}
            >>> create = instance.createOne(payload) # you can use json() method for return json value
            >>> create
                <Response [201]>
            >>> create.json()
                {'id':3,'branch':'IT'}
        """

        return api.post(self.url,data=json.dumps(payload),headers=self.headers)
        

    def createMany(self,list_payload):

        """
        Description     :
                        create many values

        return values [list]

        ARGS       :
            list_payload[list]      : list of dictionary to create [{},{}]

        Example 

            >>> url = 'http://localhost:8000/api/branches/'
            >>> url_user = 'http://localhost:8000/api/auth/user/'
            >>> instance = ApiCRUD(url,url_user,tok_mut)
            >>> payload =  [{'branch':'Religion'},{'branch':'Design'}]
            >>> create = instance.createMany(payload) # you can use json() method for return json value
            >>> create
                [<Response [201]>,<Response [201]>]
            >>> create[0].json()
                {'id':4,'branch':'Religion'}

        """

        return [api.post(self.url,data=json.dumps(payload),headers=self.headers) for payload in list_payload]

    def updateOne(self,payload):
        """
        Description     :
                        update one data

        return data update

        ARGS    :
                payload   : contains a pk and value to update
                
        Example 

            >>> url = 'http://localhost:8000/api/branches/'
            >>> url_user = 'http://localhost:8000/api/auth/user/'
            >>> instance = ApiCRUD(url,url_user,tok_mut)
            >>> payload =  {'pk':3,'branch':'Information Technologie'}
            >>> update = instance.updateOne(payload) # you can use json() method for return json value
            >>> update
                <Response [200]>
            >>> update.json()
                {'id':3,'branch':'Information Technologie'}
        """
        pk = payload.pop("pk") or payload.pop("id")
        return  api.patch(self.url+f"{pk}/",json.dumps(payload),headers=self.headers)
        

    def updateMany(self,list_payload):
        """
        Description     :
                        update one data and return response

        return data update

        ARGS    :
                list_payload   : contains list of payload contains a pk and value to update
                
        Example 

            >>> url = 'http://localhost:8000/api/branches/'
            >>> url_user = 'http://localhost:8000/api/auth/user/'
            >>> instance = ApiCRUD(url,url_user,tok_mut)
            >>> payload =  [{'pk':1,'branch':'MUKIKA'},{'pk':2,'branch':'EKLEZIA'}]
            >>> update = instance.updateMany(payload) # you can use json() method for return json value
            >>> update
                [<Response [200]>, <Response [200]>]
            >>> update[0].json()
                {'id':1,'branch':'MUSIKA'}
        """

        return [api.patch(self.url+f"{payload.pop("pk")}/",json.dumps(payload),headers=self.headers) for payload in list_payload]   

                

    def deleteOne(self,id):
        """
        delete one data

        ARGS :
            id  : id of data

        Example 

            >>> url = 'http://localhost:8000/api/branches/'
            >>> url_user = 'http://localhost:8000/api/auth/user/'
            >>> instance = ApiCRUD(url,url_user,tok_mut)
            >>> payload_id = 2
            >>> delete = instance.deleteOne(payload_id) # Not contains json method
            >>> delete
                <Response [204]>
        """
        return  api.delete(self.url+f"{id}/",headers=self.headers)
        
    
    def deleteMany(self,list_pk):
        """
        delete many data

        ARGS :
            list_pk  : list of pk or id data for delete

        Example 

            >>> url = 'http://localhost:8000/api/branches/'
            >>> url_user = 'http://localhost:8000/api/auth/user/'
            >>> instance = ApiCRUD(url,url_user,tok_mut)
            >>> list_payload_id = [1,2]
            >>> delete = instance.deleteMany(list_payload_id) # Not contains json method
            >>> delete
                [<Response [204]>,<Response [204]>]
        """
    
        return [api.delete(self.url+f"{pk}/",headers=self.headers) for pk in list_pk]
    