from config.env import ComprefaceConfig
from compreface import CompreFace
from compreface.service import RecognitionService
from compreface.collections import FaceCollection
from compreface.common.typed_dict import AllOptionsDict, check_fields_by_name


import httpx
import json
import os



RECOGNITION_ROOT_API: str = '/api/v1/recognition'

RECOGNIZE_API: str = RECOGNITION_ROOT_API + '/recognize'
RECOGNIZE_CRUD_API: str = RECOGNITION_ROOT_API + '/faces'
SUBJECTS_CRUD_API: str = RECOGNITION_ROOT_API + '/subjects'

DETECTION_API: str = '/api/v1/detection/detect'

VERIFICATION_API: str = '/api/v1/verification'




compre_face: CompreFace = CompreFace(ComprefaceConfig.COMPREFACE_BASE_URL, ComprefaceConfig.COMPERFACE_BASE_PORT)
# recognition: RecognitionService = compre_face.init_face_recognition(ComprefaceConfig.COMPREFACE_API_KEY)
# face_collection: FaceCollection = recognition.get_face_collection()



class ComprefaceUtil:
    
    api_key: str = ComprefaceConfig.COMPREFACE_API_KEY
    api_key_detection: str = ComprefaceConfig.COMPREFACE_API_KEY_DETECTION
    @classmethod
    async def send_request(cls, method: str, url: str, headers: dict, body: str | None=None, data=None, files=None ,json=True):
	
        async with httpx.AsyncClient(verify=False) as client:
            response = await client.request(
                method, url, headers=headers, content=body, data=data, files=files, timeout=5 # timeout 单位秒
            )
            if response.status_code in (301, 302, 303, 307, 308):
                location = response.headers.get("Location")
                # 可能需要处理成 GET 请求或保留原方法
                response = await client.get(location, headers=headers)
            response.raise_for_status()
            if json:
                return response.json()
            return response
    
    # 添加人脸到指定分组下, subject 为分组名称
    @classmethod
    async def face_addition(cls, image: str = '' or bytes, subject: str = '') -> dict:
        client_url: str = RECOGNIZE_CRUD_API
        url: str = ComprefaceConfig.COMPREFACE_BASE_URL + ':' + ComprefaceConfig.COMPERFACE_BASE_PORT + client_url + '?subject=' + subject
        # Validation loop and adding fields to the url.
        m = await multipart_constructor(image)
        result = await cls.send_request("post"
                                        , url
                                        , headers={'x-api-key': cls.api_key}
                                        , files=m)
        return result
    # 人脸识别
    @classmethod
    async def face_recognition(cls, image: str = '' or bytes, options: AllOptionsDict = {}) -> dict:

        client_url: str = RECOGNIZE_API
        url: str = ComprefaceConfig.COMPREFACE_BASE_URL + ':' + ComprefaceConfig.COMPERFACE_BASE_PORT + client_url+"?"
        # url: str = "http://10.0.0.202:8000/api/v1/recognition/recognize?face_plugins=landmarks&face_plugins=gender&face_plugins=age&face_plugins=pose"
        
        for key in options.keys():
            # Checks fields with necessary rules.
            # key - key field by options.
            check_fields_by_name(key, options[key])
            url += '&' + key + "=" + str(options[key])
            
        m = await multipart_constructor(image)
        result = await cls.send_request("post"
                                        , url
                                        , headers={'x-api-key': cls.api_key}
                                        , files=m)
        return result
    
    # 人脸检测
    @classmethod
    async def face_detection(cls, image: str = '' or bytes, options: AllOptionsDict = {}) -> dict:
        client_url: str = DETECTION_API
        url: str = ComprefaceConfig.COMPREFACE_BASE_URL + ':' + ComprefaceConfig.COMPERFACE_BASE_PORT + client_url+"?"
        for key in options.keys():
            # Checks fields with necessary rules.
            # key - key field by options.
            # check_fields_by_name(key, options[key])
            url += '&' + key + "=" + str(options[key])
        m = await multipart_constructor(image)
        result = await cls.send_request("post"
                                        , url
                                        , headers={'x-api-key': cls.api_key_detection}
                                        , files=m)
        return result
    
async def get_file(image: str = '' or bytes):
    if not os.path.isfile(image):
        if type(image) != bytes:
            async with httpx.AsyncClient() as client:
                response = await client.get(image, timeout=5)
                file = response.content
        else:
            file = image
        file = ('image.jpg', file)
    else:
        name_img: str = os.path.basename(image)
        file = (name_img, open(image, 'rb'))
    return file


async def multipart_constructor(image: str = '' or bytes):

    return {"file": await get_file(image)}


# def multipart_constructor_with_two_images(source_image: str = '' or bytes, target_image: str = '' or bytes):
#     return MultipartEncoder(
#         fields={'source_image': get_file(
#             source_image), 'target_image': get_file(target_image)}
#     )