from fastapi import FastAPI, HTTPException, APIRouter, Request, Header, Depends
from fastapi import BackgroundTasks
from fastapi.responses import JSONResponse
import json
from fastapi.templating import Jinja2Templates
from sqlalchemy.ext.asyncio import async_sessionmaker
from typing import Dict
from pydantic import BaseModel
from sqlalchemy.orm import Session
import json
from model.database import get_async_session, Client
from utils.clients import upsert_client, del_jobs, add_jobs, get_applied_jobs, get_filtered_jobs, client_list, get_avtopilot, get_delite, get_update
from typing import Union
import requests

import asyncio

from types import SimpleNamespace





router = APIRouter()
templates = Jinja2Templates(directory="templates")
API_KEY = "4545454"




def get_filtered_values(category, data):
    values = data.get(category, {})
    
    if isinstance(values, dict):
        # Фильтруем словарь, оставляем только значения, отличные от None
        return [key for key, value in values.items() if value is not None]
    elif isinstance(values, str) and values:
        # Если это строка, добавляем её как есть (если она не пустая)
        return [values]
    return []

# Пример данных

@router.get("/get_client/{client_id}", include_in_schema=False)
async def get_client_modal(client_id: int, db: Session = Depends(get_async_session)):
    data = SimpleNamespace(user_id=client_id)
    print(data)
    await get_update(db, data)
    
    client = await client_list(client_id, db)
    
    print(client)
    
     # Получаем токен
    token = client.get("token") if isinstance(client, dict) else getattr(client, "token", None)
    if not token:
        raise HTTPException(status_code=400, detail="Token not found for client")

    # Запрос к внешнему API
    try:
        response = requests.get(
            "https://devnet.turboapply.ai/api/getKnows",
            headers={"token": token}
        )
        response.raise_for_status()
        external_data = response.json()
    except Exception as e:
        raise HTTPException(status_code=502, detail=f"Error from external API: {str(e)}")

    # Добавляем knows к клиенту
    if isinstance(client, dict):
        client["knows"] = external_data
    else:
        # Если client — объект, делаем dict
        client = dict(client)
        client["knows"] = external_data

    return JSONResponse(content=client)

class JsonData(BaseModel):
    json_data: Union[dict, str]
    
    
class jobs_delete(BaseModel):
    user_id: int
    job_id:int
    
    
class avtopilots(BaseModel):
    user_id: int
    avtopilot:bool
    
class update(BaseModel):
    user_id: int
    
    
async def process_client_data(
    db: Session,
    data: JsonData,
    user_id: str,
    first_name: str,
    last_name: str,
    email_addr: str,
    phone_num: str
):
    """Функция для обработки данных в фоне"""
    print(f"Получены данные для {first_name} {last_name} с email {email_addr}")
    
    async_session_maker = async_sessionmaker(bind=db.bind, expire_on_commit=False)
    async with async_session_maker() as db1, async_session_maker() as db2:
        print("Запускаем задачи для обновления и удаления")
        client_task = upsert_client(db1, user_id, first_name, last_name, email_addr, phone_num, str(data.json_data))
        del_task = del_jobs(db2, user_id)
        
        client, _ = await asyncio.gather(client_task, del_task)

    job_level_values = get_filtered_values('job_level', data.json_data)
    job_type_values = get_filtered_values('job_type', data.json_data)
    location_type_values = get_filtered_values('location_type', data.json_data)
    
    print("Job Level:", ", ".join(job_level_values))
    print("Job Type:", ", ".join(job_type_values))
    print("Location Type:", ", ".join(location_type_values))
    
    jobs = await get_filtered_jobs(
        db,
        user_job_titles=["3D Modeler,3D Printing Technician,3D Visualizer"],
        minimum_annual_salary=None,
        salary_currency=None,
        user_location_type=None,
        user_locations=["Burnaby, Canada", "Vancouver, Canada", "Toronto, Canada"],
        user_levels=["Mid", "Senior", "Manager"],
        user_job_types=["Part-Time", "Permanent"]
    )

    for job in jobs:
        print(job.job_title, job.location, job.job_level, job.job_type)

    ads = await add_jobs(db, user_id)
    get_jobs = await get_applied_jobs(db, user_id)   

# [ ]: NOTE Рабоиа в фоне BackgroundTasks process_client_data()
@router.post("/client/", summary="Обновления json_data и переобновление вакансий",
    description="Этот эндпоинт обновляет json_data, удаляет все вакансии со статусом Scheduled и создаёт по полученным данным новые вакансии")
async def client(
    data: JsonData, 
    x_api_key: str = Header(...), 
    db: Session = Depends(get_async_session),
    background_tasks: BackgroundTasks = BackgroundTasks()
):
    if x_api_key != "4545454":
        raise HTTPException(status_code=403, detail="Invalid API Key")
     
    # Если json_data строка, декодируем её в словарь
    if isinstance(data.json_data, str):
        try:
            data.json_data = json.loads(data.json_data)
        except json.JSONDecodeError:
            raise HTTPException(status_code=400, detail="Invalid JSON format")

    # Проверяем что данные в нужном формате
    if not isinstance(data.json_data, dict):
        raise HTTPException(status_code=400, detail="Invalid data format")

    try:
        # Извлекаем основные данные
        first_name = data.json_data['first_name']
        last_name = data.json_data['last_name']
        email_addr = data.json_data['email_addr']
        user_id = data.json_data['user_id']
        phone_num = data.json_data['phone_num']
        
        # Добавляем фоновые задачи
        # background_tasks.add_task(
        #     process_client_data, 
        #     db=db, 
        #     data=data,
        #     user_id=user_id,
        #     first_name=first_name,
        #     last_name=last_name,
        #     email_addr=email_addr,
        #     phone_num=phone_num
        # )
        
    except KeyError as e:
        raise HTTPException(status_code=400, detail=f"Missing required field: {e}")

    return {"status": "ok", "message": "Request received and is being processed"}
    
    
# @router.post("/client/")
# async def client(data: JsonData, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
#     if x_api_key != "4545454":
#         raise HTTPException(status_code=403, detail="Invalid API Key")
    
    
#     # Если json_data строка, декодируем её в словарь
#     if isinstance(data.json_data, str):
#         try:
#             data.json_data = json.loads(data.json_data)  # Декодируем строку в словарь
#         except json.JSONDecodeError:
#             raise HTTPException(status_code=400, detail="Invalid JSON format")

#     # Если json_data строка — декодируем
#      # Теперь data.json_data гарантированно является словарем
#     if isinstance(data.json_data, dict):
#         try:
#             first_name = data.json_data['first_name']
#             last_name = data.json_data['last_name']
#             email_addr = data.json_data['email_addr']
#             user_id = data.json_data['user_id']
#             phone_num = data.json_data['phone_num']
            
#             print(f"Получены данные для {first_name} {last_name} с email {email_addr}")
            
#             async_session_maker = async_sessionmaker(bind=db.bind, expire_on_commit=False)
#             async with async_session_maker() as db1, async_session_maker() as db2:
#                 print("Запускаем задачи для обновления и удаления")
#                 client_task = upsert_client(db1, user_id, first_name, last_name, email_addr, phone_num, str(data.json_data))
#                 del_task = del_jobs(db2, user_id)
                
#                 client, _ = await asyncio.gather(client_task, del_task)

#             job_level_values = get_filtered_values('job_level', data.json_data)
#             job_type_values = get_filtered_values('job_type', data.json_data)
#             location_type_values = get_filtered_values('location_type', data.json_data)
            
#             #Результат
#             print("Job Level:", ", ".join(job_level_values))
#             print("Job Type:", ", ".join(job_type_values))
#             print("Location Type:", ", ".join(location_type_values))
            
#             # Пример использования функции
#             jobs = await get_filtered_jobs(
#                 db,
#                 user_job_titles=["Electronics Engineer", "Hardware Engineer"],
#                 minimum_annual_salary=None,
#                 salary_currency=None,
#                 user_location_type=None,
#                 user_locations=["Burnaby, Canada", "Vancouver, Canada", "Toronto, Canada"],
#                 user_levels=["Mid", "Senior", "Manager"],
#                 user_job_types=["Full-time", "Permanent"]
#             )


#             # Выводим вакансии
#             for job in jobs:
#                 print(job.job_title, job.location, job.job_level, job.job_type)

            
#             ads = await add_jobs(db, user_id)
#             get_jobs = await get_applied_jobs(db, user_id)
#             # print(f"Полученные заявки: {get_jobs}")

#         except KeyError as e:
#             print(f"Ошибка при извлечении данных: {e}")
#             raise HTTPException(status_code=400, detail="Missing required field in json_data")

#     else:
#         # print(f"Неверный формат данных: {type(data.json_data)}")
#         raise HTTPException(status_code=400, detail="Invalid data format")

#     return {"status": "ok", "message": "JSON получен"}


@router.post("/client_update", summary="Обновления клиента",
    description="Этот эндпоинт получает ID пользователя, переходит по ссылки что бы получить json_data")
async def client_update(data: update, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
    
    if x_api_key != "4545454":
        raise HTTPException(status_code=403, detail="Invalid API Key")
    
    try:
        user_id = data.user_id  # Обратите внимание на точку вместо квадратных скобок
       
        await get_update(db, data)
        

    except Exception as e:
        print(f"Ошибка при обработке данных: {e}")
        raise HTTPException(status_code=400, detail="Error processing data")

    return {"status": "ok", "message": "Data received", "user_id": user_id, }
    
    
    
@router.post("/client_jobs/", summary="Получить список работ по клиенту",
    description="Этот эндпоинт получает ID пользователя, в ответ отдаёт список вакансий")
async def client_jobs(data: update, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
    if x_api_key != "4545454":
        raise HTTPException(status_code=403, detail="Invalid API Key")
    
    try:
        user_id = data.user_id  # Обратите внимание на точку вместо квадратных скобок
        get_jobs = await get_applied_jobs(db, user_id)
        print(f"Полученные данные: user_id={user_id}")

    except Exception as e:
        print(f"Ошибка при обработке данных: {e}")
        raise HTTPException(status_code=400, detail="Error processing data")

    return {"status": "ok", "message": "Data received", "get_jobs": get_jobs}
    # return {"message": "JSON получен", "data": get_jobs}    


@router.post("/avtopilot", summary="Автопилот вкл, выкл",
    description="Этот эндпоинт получает ID пользователя, включает или отключает автопилот. При false все вакансии со статусом Scheduled становятся Paused при true наоборот!")
async def avtopilot(data: avtopilots, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
    
    if x_api_key != "4545454":
        raise HTTPException(status_code=403, detail="Invalid API Key")
    
    try:
        user_id = data.user_id  # Обратите внимание на точку вместо квадратных скобок
        avtopilotss = data.avtopilot    # Так как data - это объект Pydantic модели
        
        await get_avtopilot(db, data)

    except Exception as e:
        print(f"Ошибка при обработке данных: {e}")
        raise HTTPException(status_code=400, detail="Error processing data")

    return {"status": "ok", "message": "Data received", "user_id": user_id, "avtopilotss": avtopilotss}
   



@router.post("/jobs_delete", summary="Удаление вакансии",
    description="Этот эндпоинт получает ID пользователя и ID вакансии, Удаляет у пользователя вакансию")
async def jobs_delete(data: jobs_delete, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
    if x_api_key != "4545454":
        raise HTTPException(status_code=403, detail="Invalid API Key")
    
    try:
        user_id = data.user_id  # Обратите внимание на точку вместо квадратных скобок
        job_id = data.job_id    # Так как data - это объект Pydantic модели
        
        await get_delite(db, data)
    except Exception as e:
        print(f"Ошибка при обработке данных: {e}")
        raise HTTPException(status_code=400, detail="Error processing data")

    return {"status": "ok", "message": "Data received", "user_id": user_id, "job_id": job_id}




class QuestionRequest(BaseModel):
    question: str
    client_name: str
    token: str

@router.post("/ask_question")
async def ask_question(data: QuestionRequest):
    try:
        response = requests.get(
            f"https://devnet.turboapply.ai/api/qaRequest/?question={data.question}",
            headers={"token": data.token}
        )
        response.raise_for_status()
        external_data = response.json()
        content = external_data['result']['choices'][0]['message']['content']
        result = content.split(":")[-1].strip()
        
    except Exception as e:
        raise HTTPException(status_code=502, detail=f"Error from external API: {str(e)}")
    return {"answer": f"{result}"}