from fastapi import APIRouter, HTTPException, Request, Depends
from fastapi.responses import RedirectResponse
import openai
from openai import OpenAI
import re
import boto3
import os
import time
from schemas import ChatMessage, SpeechText, QuizMessage, LineUser, MedicineText, UserQuestion
from config import logger, openai_api_key
import json
from sklearn.feature_extraction.text import TfidfVectorizer
import logging
import requests
from bs4 import BeautifulSoup
import numpy as np
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from urllib.parse import urljoin, urlparse
import time
import ast
from datetime import datetime
import chromadb
from chromadb.config import Settings

# Chroma 서버 연결 (1.x 서버 실행중이어야 함)
chroma_client = chromadb.HttpClient(
    host="localhost",
    port=8001,
    settings=Settings(chroma_api_impl="rest")
)

# 컬렉션명은 기존에 저장한 이름 사용
collection = chroma_client.get_collection("excel_honbun")

router = APIRouter()

openai.api_key = openai_api_key
client = OpenAI(api_key=openai_api_key)

s3_client = boto3.client('s3')
bucket_name = 'shanri-ai-chatbot-for-text-to-speech'


async def ask_openai(messages):
    valid_messages = [msg for msg in messages if msg.get('content')]
    response = openai.chat.completions.create(
        model="gpt-4o",
        messages=valid_messages
    )
    answer = response.choices[0].message.content.strip()
    return answer


async def synthesize_speech(text, user_id):
    response = client.audio.speech.create(
        model="tts-1",
        voice="nova",
        input=text,
    )
    audio_file = f"tmp/audio-{user_id}-{time.time()}.mp3"
    with open(audio_file, 'wb') as f:
        for chunk in response.iter_bytes():
            f.write(chunk)
    s3_key = f"{user_id}-{time.time()}.mp3"
    s3_client.upload_file(audio_file, bucket_name, s3_key)
    os.remove(audio_file)
    return f"https://{bucket_name}.s3.amazonaws.com/{s3_key}"

# ✅ 특정 웹사이트(segue-g) 크롤링 함수
def init_driver():
    options = Options()
    options.add_argument("--headless")
    options.add_argument("--disable-gpu")
    options.add_argument("--no-sandbox")
    return webdriver.Chrome(options=options)

def is_same_domain(base_url, test_url):
    return urlparse(base_url).netloc == urlparse(test_url).netloc

async def fetch_all_pages_with_selenium(url_list):
    """url_list에 있는 각 페이지의 <section> 태그 HTML만 크롤링 (내부 링크 X)"""
    driver = init_driver()
    all_html = ""

    try:
        for url in url_list:
            try:
                print(f"\n🟢 크롤링 중: {url}")
                driver.get(url)
                soup = BeautifulSoup(driver.page_source, "html.parser")

                # ✅ sections_group 클래스를 가진 요소만 가져오기
                sections = soup.find_all("section")

                page_html = ""
                for section in sections:
                    page_html += section.prettify()  # ✅ HTML 코드로 가져오기

                all_html += f"<!-- {url} -->\n{page_html}\n\n"

            except Exception as e:
                print(f"[에러] {url}: {e}")

        return all_html
    finally:
        driver.quit()

# ✅ chromadb 검색함수
async def search_excel_context(question):
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=question
    )
    query_embedding = response.data[0].embedding

    results = collection.query(
        query_embeddings=[query_embedding],
        n_results=1  # 원하는 검색결과 수
    )

    retrieved_docs = results['documents'][0]
    excel_context = "\n\n".join(retrieved_docs)
    return excel_context

# # ✅ GPT-4o를 사용해 생성된 답변을 더 자연스럽고 정돈되게 수정 + 마크다운형식
# def refine_answer_with_gpt(raw_answer):
#     messages = [
#         {"role": "system", "content": "答えを整えてSNSのやりとりのように、親しみやすく、簡潔で、前向きなトーンで行ってください。"},
#         {"role": "system", "content": "会社名は『弊社』と表現してください。"},
#         {"role": "system", "content": "常に丁寧さと共感を大切にしてください。ただし、堅苦しくなりすぎないように心がけてください。"},
#         {"role": "system", "content": "ユーザーが名前を入力した場合でも、挨拶や名前の呼びかけ、自己紹介への返答は不要です。常に質問の内容にのみ答えてください。"},
#         {"role": "system", "content": "不要な前置きや余計な説明は控え、知りたい内容に端的に答えてください。"},
#         # {"role": "system", "content": "数値に関する内容が出たら、マークダウン形式の表で作成して答えてくれ。数値情報がなければあえて表にする必要はない。"}, 수치데이터는 추가하는가?
#         {"role": "user", "content": "答え \n" + raw_answer}
#     ]

#     response = client.chat.completions.create(
#         model="gpt-4o",
#         messages=messages
#     )

#     return response.choices[0].message.content

async def choose_hompage_url(question):
    """homepage_url을 선택하는 함수"""

    messages = [
        {"role": "system", "content": "質問を分析し、回答を作成する際に必要な情報を持つURLを返す必要があります。質問を見てURLを選択してください。"},
        {"role": "system", "content": "最も情報がある可能性が高いURLを配列で返す必要があります。"},
        {"role": "system", "content": "関数の戻り値のように、配列のみを返す必要があります。3つ以内のURLをリターンしてください。 例) ['https://sanwanet.co.jp/unique/history','https://sanwanet.co.jp/construction/government']"},
        {"role": "system", "content": "三和電業株式会社 会社概要 : https://sanwanet.co.jp/company/sanwa"},
        {"role": "system", "content": "三和プラントエンジニアリング株式会社 会社概要 : https://sanwanet.co.jp/company/plant"},
        {"role": "system", "content": "三和エコ&エナジー株式会社 会社概要 : https://sanwanet.co.jp/company/ecoenergy"},
        {"role": "system", "content": "三和空調株式会社 会社概要 : https://sanwanet.co.jp/company/kucho"},
        {"role": "system", "content": "三和科技（蘇州）有限公司 & 三和工程設備（蘇州）有限公司 & 三和技研（蘇州）有限公司 会社概要 : https://sanwanet.co.jp/company/yugenkoushi"},
        {"role": "system", "content": "三和電業グループ 沿革: https://sanwanet.co.jp/unique/history"},
        {"role": "system", "content": "三和電業グループ 技術紹介 : https://sanwanet.co.jp/unique/technology"},
        {"role": "system", "content": "企業の社会的責任 : https://sanwanet.co.jp/unique/csr"},
        {"role": "system", "content": "三和会(会社の同好会) : https://sanwanet.co.jp/unique/sanwakai"},
        {"role": "system", "content": "施工事例(官公庁) : https://sanwanet.co.jp/construction/government"},
        {"role": "system", "content": "施工事例(工場) : https://sanwanet.co.jp/construction/factory"},
        {"role": "system", "content": "施工事例(研究施設) : https://sanwanet.co.jp/construction/laboratory"},
        {"role": "system", "content": "施工事例(病院・特養施設・福祉施設) : https://sanwanet.co.jp/construction/hospital"},
        {"role": "system", "content": "施工事例(一般ビル) : https://sanwanet.co.jp/construction/building"},
        {"role": "system", "content": "施工事例(中国物件) : https://sanwanet.co.jp/construction/china"},
        {"role": "system", "content": "施工事例(特別高圧) : https://sanwanet.co.jp/construction/high-voltage"},
        {"role": "system", "content": "施工事例(太陽光) : https://sanwanet.co.jp/construction/solar"},
        {"role": "system", "content": "ピックアッププロジェクト : https://sanwanet.co.jp/category/project"},
        {"role": "system", "content": "採用情報 : https://sanwanet.co.jp/recruit"},
        {"role": "user", "content": "質問 : " + question}
    ]

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages
    )

    return response.choices[0].message.content


# ✅ GPT에게 질문하고 답변을 생성하는 함수 (웹 크롤링 + OpenAI 웹 검색 기능 활용)
async def generate_gpt_answer(question):
    """GPT-4o를 사용해 https://sanwanet.co.jp/ 크롤링 데이터 + 웹 검색 정보를 포함한 답변 생성"""

    # 질문에 "御社の"가 없으면 추가
    if not question.startswith("御社の"):
        question = "御社の" + question

    print(datetime.now(),"url 선택 시작")
    url_list_str = await choose_hompage_url(question)
    url_list = ast.literal_eval(url_list_str)
    print(datetime.now(),"url 선택 끝")


    print(datetime.now(),"크롤링시작")
    website_data = await fetch_all_pages_with_selenium(url_list)
    print(website_data)
    print(datetime.now(),"크롤링끝")

    print(datetime.now(),"Excel 검색 시작")
    excel_data = await search_excel_context(question)

    print("excel_data : " + excel_data)
    print(datetime.now(),"Excel 검색 끝")

    messages = [
        {"role": "system", "content": "あなたは「三和電業グループ」の会社紹介および就職希望者向けのチャットボットです。"},
        {"role": "system", "content": "以下のルールに従って、ユーザーと会話してください。"},
        {"role": "system", "content": "1.会話スタイル：SNS上のやり取りのように、親しみやすく、1回の返信は300文字以内に収めてください。"},
        # {"role": "system", "content": "2.トーン：丁寧で共感的な言葉遣いを心がけ、ユーザーとの会話を楽しむように、適度に質問を返してください。"},
        {"role": "system", "content": "3.情報の制限：返答に使用できるのは、提供されたURLとExcelファイルに含まれる情報のみとします。その他の情報は使用しないでください。"},
        {"role": "system", "content": "この制約のもと、ユーザーに寄り添いながら会話を進めてください。"},
    ]

    # 웹사이트 데이터와 엑셀 데이터 양쪽을 모두 사용하여 답변을 생성
    if website_data:
        messages.append({"role": "system", "content": f"企業サイト情報\n{website_data}"})

    if excel_data:
        messages.append({"role": "system", "content": f"Excelファイルに記載されている情報\n{excel_data}"})


    messages.append({"role": "user", "content": question})

    print(datetime.now(),"대답생성 시작")
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages
    )
    print(datetime.now(),"대답생성 종료")

    initial_answer  =  response.choices[0].message.content

    print("초기대답 : " + initial_answer)

    return initial_answer

    # if(initial_answer == "申し訳ありませんが、その件についてはお答えできません。"):
    #     print(initial_answer)
    #     return initial_answer
    # else:
    #     print(datetime.now(),"답변 정리 시작")
    #     refined_answer = refine_answer_with_gpt(initial_answer)
    #     print(datetime.now(),"답변 정리 종료")
    #     return refined_answer


@router.get("/health")
async def health_check():
    return {"status": "healthy"}


@router.post("/sanwa/gpt-backup/speech")
async def speech(speech_text: SpeechText):
    text = speech_text.text
    chat_token = speech_text.chat_token
    if not text:
        raise HTTPException(status_code=400, detail="Text is required。")
    audio_file = await synthesize_speech(text, chat_token)
    return {"audio_file": audio_file}


# 질문을 받아서 처리하는 API
@router.post('/sanwa/gpt-backup/ask_question')
async def ask_question(user_question: UserQuestion):
    question_text = user_question.question.strip()
    if not question_text:
        raise HTTPException(status_code=400, detail="Question is required")

    generated_answer = await generate_gpt_answer(question_text)
    return {"answer": generated_answer}

