import os
import time
import random
import re
import json
import requests
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_core.prompts import ChatPromptTemplate
from crawl4ai import AsyncWebCrawler
import asyncio
from langchain_groq import ChatGroq
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser, PydanticOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_community.document_loaders import PyPDFLoader, TextLoader, Docx2txtLoader, UnstructuredPowerPointLoader
from PyPDF2 import PdfReader
from langchain_experimental.text_splitter import SemanticChunker
from pydantic import BaseModel, Field
from typing import List, Optional, Dict
from urllib.parse import urlparse
from langchain_ollama import ChatOllama

import shutil

GROQ_API_KEY = "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"
OLLAMA_MODEL = "nomic-embed-text"


def map_skills_to_designations(skills_db, JobProfile, model_name="mixtral-8x7b-32768", temperature=0):
   

    # Initialize the chat model
    #chat = ChatGroq(temperature=temperature, groq_api_key=groq_api_key, model_name=model_name)
    chat = ChatOllama(
            base_url = 'http://127.0.0.1:11434',
            model = "llama3:8b"
            #model = "deepseek-r1:8b"
            )
    #print(chat)
    # Define the system prompt
    system_prompt = PromptTemplate(
        input_variables=["skills_db", "JobProfile"],
        template='''
        You are an expert in skill-to-Job Profile mapping. Your task is to analyze a given set of skills and map them to the most appropriate JobProfile.

        ### Input Skills:
        {skills_db}

        ### Designations:
        {JobProfile}

        ### Output Format:
        {{
        "JobProfile 1": ["Skill 1", "Skill 2", "Skill 3"],
        "JobProfile 2": ["Skill 4", "Skill 5"],
        "JobProfile 3": ["Skill 6", "Skill 7", "Skill 8"]
        }}

        ### Notes:
        - Ensure that each skill is mapped only to the most relevant JobProfile(s).
        - If a skill fits multiple JobProfile, include it in both.
        - Use clear and concise mappings.
        - Respond only with the JSON object in the specified format, without any additional text.
        - If you found no skills for some JobProfile check does JobProfile at last one more time

        ### Instructions:
        - **Respond only with the JSON object in the specified format.**
        - **Do not include any additional text, explanations, or code fences (e.g., ```json).**
        - **Ensure that the JSON is properly formatted and valid.**
        '''
            )

    # Format the prompt with the input skills and designations
    formatted_prompt = system_prompt.format(skills_db=skills_db, JobProfile=JobProfile)
    #print(formatted_prompt)
    # Send the formatted prompt to ChatGroq
    try:
        output = chat.invoke(formatted_prompt)
        total_tokens = output.usage_metadata["output_tokens"]
        #token_consumed = output.response_metadata['token_usage']['total_tokens']
        skill_to_jobProfile_mapping = output.content
    except Exception as e:
        print(f"An error occurred during chat invocation: {e}")
        return None, 0

    return skill_to_jobProfile_mapping, total_tokens


import json
import re

def extract_json_from_response(response_text):
    """Extracts the JSON object from a response string"""
    json_match = re.search(r"```json\s*(\{.*?\})\s*```", response_text, re.DOTALL)
    if json_match:
        return json_match.group(1)  # Extract the JSON part only
    return None  # Return None if no JSON found

def map_skills_to_designations_non_empty(skills_db, JobProfile, mapped_skills):
    # Initialize the chat model
    #chat = ChatGroq(temperature=temperature, groq_api_key=groq_api_key, model_name=model_name)
    chat = ChatOllama(
            base_url = 'http://127.0.0.1:11434',
            model = "llama3:8b"
            #model = "deepseek-r1:8b"
            )
    # Convert mapped_skills dictionary to a JSON string
    formatted_mapped_skills = json.dumps(mapped_skills, ensure_ascii=False)

    # Define the system prompt
    system_prompt = PromptTemplate(
        input_variables=["skills_db", "JobProfile", "mapped_skills"],
        template='''
        You are an expert in skill-to-JobProfile mapping. Your task is to validate and refine a given mapping of skills to JobProfile to ensure accuracy, completeness, and clarity.
    
        ### Input:
        - **Existing Mapped Skills** (JSON format):  
        {mapped_skills}  

        ### Input Skills:
        {skills_db}

        ### JobProfile:
        {JobProfile}

        ### Output Format:
        {{  
        "JobProfile 1": ["Skill 1", "Skill 2", "Skill 3"],  
        "JobProfile 2": ["Skill 4", "Skill 5"],  
        "JobProfile 3": ["Skill 6", "Skill 7", "Skill 8"]  
        }}  

        ### Validation & Enhancement Guidelines:
        1. **Ensure Relevance:**  
        - Verify that each skill is appropriately mapped to the correct JobProfile(s).  
        - Remove any incorrectly assigned skills.  
        2. **Check for Completeness:**  
        - Identify and add missing skills relevant to each JobProfile.  
        - Ensure no important skills are overlooked.  
        3. **Refine Overlapping Skills:**  
        - If a skill belongs to multiple JobProfile, ensure it is correctly included in each.  
        - Avoid redundant mappings unless justified.  
        4. **Improve Consistency & Clarity:**  
        - Standardize skill naming to avoid duplicates with different names.  
        - Use precise and industry-recognized terminology.  
        5. **Handle Unmapped JobProfile:**  
        - If a JobProfile lacks sufficient mapped skills, reevaluate and attempt to match relevant ones.  
        6. **Respond in Valid JSON Format:**  
        - **ONLY return the JSON object without any explanations, comments, or additional text.**  
        - **DO NOT wrap the JSON in code blocks (```json ... ```).**  
        '''
    )

    # Format the prompt safely
    formatted_prompt = system_prompt.format(
        skills_db=skills_db.replace("{", "{{").replace("}", "}}"),
        JobProfile=JobProfile.replace("{", "{{").replace("}", "}}"),
        mapped_skills=formatted_mapped_skills
    )

    # Send the formatted prompt to ChatGroq
    try:
        output = chat.invoke(formatted_prompt)

        # Debugging: Print raw API response
        print(f"Raw API response: {output.content}")

        # Extract the JSON part from the response
        # json_data = extract_json_from_response(output.content)
        # if not json_data:
        #     print("Error: No valid JSON found in the response")
        #     return None, 0

        # Ensure response is valid JSON
        skill_to_JobProfile_mapping = json.loads(json_data)  # Convert response to dict
        #token_consumed = output.response_metadata['token_usage']['total_tokens']
        token_consumed = output.usage_metadata["output_tokens"]

    except json.JSONDecodeError as e:
        print(f"Error decoding JSON response: {e}")
        return None, 0
    except Exception as e:
        print(f"An error occurred during chat invocation: {e}")
        return None, 0

    return skill_to_JobProfile_mapping, token_consumed


# Example usage
if __name__ == "__main__":
    GROQ_API_KEY = "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"  # Replace with your actual Groq API key
    industry = "Infrastructure"
    #skill_tree,token_consumed  = generate_skill_tree(prompt_text=industry, groq_api_key=GROQ_API_KEY)
    skillset ='''
      Budgeting,
      Cost Estimation,
    
      Civil Engineering,
      Structural Analysis,
   
      AutoCAD,
      Revit,
    
      Communication,
      Leadership,
      Teamwork,
      Urban Design,
      Water Supply and Distribution
      , SQL, C++ , Management, Housekeeping Management,Front Desk Management,Complaint Handling,Recruitment,Training & Development
    '''

    JobProfile = '''

        HR, Developer, Manager, Planner,CEO, Infrastructure Deverloper
        
        '''
    
    mapped = {
    "Manager": [
        "Time Management",
        "Decision Making",
        "Industry Trends",
        "Sector Expertise",
        "Business Acumen",
        "Stakeholder Communication",
        "Risk Management",
        "Agile Methodologies",
        "Leadership",
        "Teamwork",
        "Adaptability"
    ],
    "Engineer": [
        "Data Encryption",
        "Incident Response",
        "Cloud Architecture",
        "Cloud Migration",
        "Cloud Monitoring",
        "Network Security",
        "Programming Languages",
        "Py"
    ],
    "CEO": [
        "Negotiation",
        "Empathy",
        "Leadership",
        "Risk Management",
        "Business Acumen",
        "Sector Expertise",
        "Industry Trends",
        "Stakeholder Communication",
        "Creativity"
    ],
    "CO-Founder": [
        "Creativity",
        "Sector Expertise",
        "Empathy",
        "Leadership",
        "Stakeholder Communication",
        "Risk Management",
        "Business Acumen",
        "Industry Trends",
        "Negotiation"
    ],
    "Developer": [
        "Py",
        "Programming Languages",
        "Software Testing",
        "Version Control"
    ],
    "Senior Developer": [
        "Network Security",
        "Py",
        "Programming Languages",
        "Data Encryption",
        "Incident Response"
    ],
    "HR Head": [
        "Communication",
        "Stakeholder Communication"
    ],
    "Product Engineer": [
        "Software Testing",
        "Version Control",
        "Programming Languages",
        "Cloud Migration",
        "Cloud Monitoring",
        "Py",
        "Cloud Architecture"
    ]
}
    
    mapped_skills = {
    "Manager": [
        "Time Management",
        "Decision Making",
        "Industry Trends",
        "Sector Expertise",
        "Business Acumen",
        "Stakeholder Communication",
        "Risk Management",
        "Agile Methodologies",
        "Leadership",
        "Teamwork",
        "Adaptability"
    ],
    "Engineer": [
        "Data Encryption",
        "Incident Response",
        "Cloud Architecture",
        "Cloud Migration",
        "Cloud Monitoring",
        "Network Security",
        "Programming Languages",
        "Py"
    ],
    "CEO": [
        "Negotiation",
        "Empathy",
        "Leadership",
        "Risk Management",
        "Business Acumen",
        "Sector Expertise",
        "Industry Trends",
        "Stakeholder Communication",
        "Creativity"
    ],
    "CO-Founder": [
        "Creativity",
        "Sector Expertise",
        "Empathy",
        "Leadership",
        "Stakeholder Communication",
        "Risk Management",
        "Business Acumen",
        "Industry Trends",
        "Negotiation"
    ],
    "Developer": [
        "Py",
        "Programming Languages",
        "Software Testing",
        "Version Control"
    ],
    "Senior Developer": [
        "Network Security",
        "Py",
        "Programming Languages",
        "Data Encryption",
        "Incident Response"
    ],
    "HR Head": [
        "Communication",
        "Stakeholder Communication"
    ],
    "Product Engineer": [
        "Software Testing",
        "Version Control",
        "Programming Languages",
        "Cloud Migration",
        "Cloud Monitoring",
        "Py",
        "Cloud Architecture"
    ]
    }

    
    # print(type(mapped_skills))
    json_data = json.dumps(mapped_skills)  # 'indent' makes it readable
    print("OPO")
    print(json_data)
    print("LKL")
    # print(type(json_data))
    # print(json_data)
    #print(mapped_skills)

    skill_tree,token_consumed  = map_skills_to_designations_non_empty(skills_db= skillset,JobProfile =JobProfile, mapped_skills= json_data)
    #skill_tree,token_consumed  = map_skills_to_designations(skills_db= skillset,JobProfile =JobProfile)


    print(token_consumed)
    print(skill_tree)
    print(type(skill_tree))