__all__ = [
    'get_ai_subro_possiblity', 'extract_reason_possibility', 'show_record_detail_by_index'
    
    ]

from ._imports import *
from botocore.exceptions import ClientError
from functools import cache



class Aws_Bedrock():
    # aws_cred = {

    #     ##currently we don't have permanent credential, need to replace everytime
    #     "region_name" : 'us-east-2',
    #     "aws_access_key_id"    : "ASIAVWZBVNN4UJN46TBL",
    #     "aws_secret_access_key"   : "sLBCnUU31wQi6YqsDPa+Z8qYGbrk5IhdCshsP2dD",
    #     "aws_session_token"       : "IQoJb3JpZ2luX2VjEKX//////////wEaCXVzLWVhc3QtMSJHMEUCIHJCvPXb8PHxjQhJt91MW4Xd6i1TlOFC5pMFiXWP6BwIAiEAxGZ5aQFBSdCjc6JoFHd1PiK3b22qr+tb3VIt5VtwTdIqgwMIrv//////////ARABGgwzOTI1MjMyNDY0NTciDJ22TrsB8tzfDxM8jSrXArr/deZxcIDUWVnGRZ3UOzaNHf9vZA6Sr/0y9KPP9jOd2dAzBVPcW4MS4PgZOE/3jKFVVke09fgx0EOzGH0qtoo1iAQOQ3uKsvFNQtLH3/N2PmL53GTHPrp+W5uM86fuYbKg6Q7aqc3+fktmMBiNGcOaIGbdCoKAaemK17FYtgV9bFkhoqcdhGAs2ax98hXnYsHK7fc0f9Wb6wKIZFZfYEof4Etf9JqWM3sNMzXPg72sKd8X3un7EwoIaAolaX6Bwn9WExj3Vapn8rS553zGHG7Te4VuDCS7krQyDtXIjnziQU6xeiyk21cTvbPPt0b2DgoPIuriuoiYUZTTQvVttQduDFOGIAX3YHPFBlHiUXO1KL+inxCoQTpRBpm9ZBS4A+dlv/Zs00gqbccPnwFZSi1OlKiP/V86NaPUq0fz5c1ZoWQYpik3Vk+nHSXRNYHLibFI9lp1vLcwia67wwY6pwEFGKq6kQkk1JpAhBtQ6hVDwluczF+8LWFrmXPSdNIRlWlZ8P0zdK7J+T/lvv2HUB95NuyHCh9yfsi2qzhuSloIRdsSXyyEWCuGfxZy31sfpK64/+sjLZnJ8YchDQt62aU67aixcWkvpqMAvdx67qiKYgmP/JKl+r2gvCb/CQqEn94YGqmgcJyM5NaDYo7/l1VR+eiqeks9WqWq33nb3PSdifVjxmpa8g=="

    # }

    # bedrock_client =  boto3.client(service_name="bedrock", **aws_cred )
    # bedrock_runtime_client = boto3.client(service_name= "bedrock-runtime", **aws_cred )     
     
    # use SSO
    session = boto3.Session(profile_name='EDS-Scientists-Dev-392523246457')
    bedrock_client =  session.client(service_name="bedrock")
    bedrock_runtime_client = session.client(service_name= "bedrock-runtime")    


    @staticmethod    
    def list_foundation_models():
        """
        Gets a list of available Amazon Bedrock foundation models.

        :return: The list of available bedrock foundation models.
        """

        try:
            response = Aws_Bedrock.bedrock_client.list_foundation_models()
            models = response["modelSummaries"]
            print("Got %s foundation models.", len(models))
            return models

        except ClientError:
            print("Couldn't list foundation models.")
            raise


    #https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime/client/invoke_model.html
    @staticmethod
    def invoke_bedrock_model(system_prompt, user_prompt, region_name="us-east-2"):
        """
        Invokes a Bedrock model and returns the generated text.

        Args:
            model_id (str): The ID of the Bedrock model to invoke.
            prompt (str): The input prompt for the model.
            region_name (str, optional): The AWS region. Defaults to "us-east-1".

        Returns:
            str: The generated text from the model, or None if an error occurred.
        """
        # try:        

        # Prepare the input payload            

        native_request = {
        "anthropic_version": "bedrock-2023-05-31",
        "system": system_prompt,
        "max_tokens": 4096,
        "temperature": 0.2,
        "messages": [
            {
                "role": "user",
                "content": [{"type": "text", "text": user_prompt}],
            }
        ],
        }

        response = Aws_Bedrock.bedrock_runtime_client.invoke_model(
            modelId=r"arn:aws:bedrock:us-east-2:392523246457:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0",#model_id,
            contentType="application/json",
            accept="application/json",
            body=json.dumps(native_request),
            guardrailIdentifier= r'arn:aws:bedrock:us-east-2:392523246457:guardrail/wof2sh6wm93z',
            #X-Amzn-Bedrock-GuardrailIdentifier = r'arn:aws:bedrock:us-east-2:392523246457:guardrail/wof2sh6wm93z',
            guardrailVersion='6'
            
        )
        
        model_response = json.loads(response["body"].read())
        model_text = model_response["content"][0]["text"]
        return model_text

@cache
def get_ai_subro_possiblity (cleaned_fnol, fault_rating ):
    if not cleaned_fnol:
        return None
    system_prompt = '''
                    You are a claim subrogation expert. Insurance company needs to recoup the money when they found the third party is liable.        
        you are presented with loss notes and try to come up with subrogation probability. In the notes, the first party can be called as insured, insd, A, etc,  whereas the third party can be called as claimant, clmt, C, etc.
         I would like you tell me if the third party is responsible for the loss, if the third party does, output a list like [reason, the percentage from 1 to 100%]. if the first party is responsible for the loss, output[ reason, 0%],
        please limit reason in 10 words, only output the list please
    '''
    user_prompt = f'''I have a column,  contain the notes, I would like you tell me if the third party is responsible for the loss, if the party does, output a list like [reason, the percentage from 1 to 100%]. if not, output[ reason, 0%], 
         please apply the following rule:
            1. if {fault_rating} is "Insured at fault", that means third party is not liable.
            2. if third party is hit and run  the case usually not consider third party is liable.
            3. if the incident cannot find the third party, the case is not liable, senario like Rock from Road, Falling/Flying Objects, Malicious Mischief and Vandalism, Weather Related (ice storm, hurricane, etc.)
            4. if the case is animal claim, usually that is not liable, but farm animal escape from enclosure, the owner is liable.
         here is the note: {cleaned_fnol}. only output the list please'''
    generated_text = Aws_Bedrock.invoke_bedrock_model(system_prompt, user_prompt)
    return generated_text


def try_ai_prediction_multiple_time(df, dest_column = 'ai_result', src_column ='loss_note_cleaned',  counterlimit = 5, func =get_ai_subro_possiblity ):    
    '''
    OpenAI API could skip record randomly, usually less than 1%, this will ensure skip record is reevaluated
    might not use for bedrock
    '''
    df[dest_column] = None
    counter = 0
    while df[dest_column].isna().sum() >0 and counter <counterlimit:
        df_ai_result_missing = df[df[dest_column].isna()]
        for i in df_ai_result_missing.index:
            df.at[i, dest_column] = func(df.at[i, src_column], df.at[i, 'fault_rating'])
        counter +=1
        print(counter, df[dest_column].isna().sum())
        func.cache_clear()  #clear cache to evaluate freshly
    return


def extract_reason_possibility (text):
    '''extract result from AI output'''    
    pattern = r'\[(.*), (\d{1,3}%)]' 
    match = re.search(pattern, text, re.IGNORECASE)
    if not match:
            return None, None   
    else:
        reason, possiblity = match.group(1), match.group(2)
        return reason, possiblity
    


def show_record_detail_by_index(df, ind):
    '''show detail info for given index for troubleshooting '''
    if 'loss_note' in df.columns:
        print(df.at[ind, 'loss_note' ])
    if 'fnol' in df.columns:
        print(df.at[ind, 'fnol' ])
    if 'claimnumber' in df.columns:
        print(df.at[ind, 'claimnumber' ])
    if 'fault_rating' in df.columns:
        print(df.at[ind, 'fault_rating' ])
    return 

@cache
def get_ai_police_report_subro_possiblity (police_report ):
    '''
    df_police['police_report_AI_result'] = df_police['content_from_pdf'].apply(get_ai_police_report_subro_possiblity)
    '''
    if not police_report:
        return None
    system_prompt = '''
                    You are a claim subrogation expert at Amica. Insurance company needs to recoup the money when they found the third party is liable.        
        you are presented with a police report and try to find if policeman state the third party is at fault. 
    '''
    user_prompt = f'''The police report will ususally contain a section where insurce companies are identified. for example, "Insurance Company  [2] 'AMICA'" means second vehicle/driver's insurance is with Amica in the report. if you don't find such info, please identify amica related vehicle number from context. 
    please note, from subrogation perspective, Amica insured is first party, the other vehicles are the third party.  please read the police report content and  
    tell me if the police stated the third party is responsible for the loss.  If the party does, output a list like [the number related with Amica vehicle, reason, the percentage from 1 to 100%]. if not, output[ the number related with Amica vehicle, reason, 0%], If police did not state the fault clearly, please output [the number related with Amica vehicle, "insufficient information to determine responsibility", 50%].
    please limit reason in 10 words, only output the list please. Please use policeman's judgement, not your own judgement.
    the police report is as follows {police_report}
              '''
    generated_text = Aws_Bedrock.invoke_bedrock_model(system_prompt, user_prompt)
    return generated_text

def extract_police_report_reason_possibility (text):
    '''extract result from AI output
    df_police[['vehicle_no', 'police report reason', 'police report subro possiblity']] = df_police.apply(lambda x: extract_police_report_reason_possibility(x['police_report_AI_result']), axis =1, result_type='expand' )
    '''    
    pattern = r'\[(\d), (.*), (\d{1,3}%)]' 
    match = re.search(pattern, text, re.IGNORECASE)
    if not match:
            return None, None, None   
    else:
        vehicle_no, reason, possiblity = match.group(1), match.group(2), match.group(3) 
        return vehicle_no, reason, possiblity