# System Packages
import json
import os
from datetime import timedelta

from fastapi import APIRouter, Request
from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from starlette.authentication import has_required_scope, requires

from khoj.database import adapters
from khoj.database.adapters import (
    ConversationAdapters,
    EntryAdapters,
    get_user_github_config,
    get_user_name,
    get_user_notion_config,
    get_user_subscription_state,
)
from khoj.database.models import KhojUser
from khoj.routers.twilio import is_twilio_enabled
from khoj.utils import constants, state
from khoj.utils.rawconfig import (
    GithubContentConfig,
    GithubRepoConfig,
    NotionContentConfig,
)

# Initialize Router
web_client = APIRouter()
templates = Jinja2Templates(directory=constants.web_directory)


# Create Routes
@web_client.get("/", response_class=FileResponse)
@requires(["authenticated"], redirect="login_page")
def index(request: Request):
    user = request.user.object
    user_picture = request.session.get("user", {}).get("picture")
    has_documents = EntryAdapters.user_has_entries(user=user)

    return templates.TemplateResponse(
        "chat.html",
        context={
            "request": request,
            "username": user.username,
            "user_photo": user_picture,
            "is_active": has_required_scope(request, ["premium"]),
            "has_documents": has_documents,
            "khoj_version": state.khoj_version,
        },
    )


@web_client.post("/", response_class=FileResponse)
@requires(["authenticated"], redirect="login_page")
def index_post(request: Request):
    user = request.user.object
    user_picture = request.session.get("user", {}).get("picture")
    has_documents = EntryAdapters.user_has_entries(user=user)

    return templates.TemplateResponse(
        "chat.html",
        context={
            "request": request,
            "username": user.username,
            "user_photo": user_picture,
            "is_active": has_required_scope(request, ["premium"]),
            "has_documents": has_documents,
            "khoj_version": state.khoj_version,
        },
    )


@web_client.get("/search", response_class=FileResponse)
@requires(["authenticated"], redirect="login_page")
def search_page(request: Request):
    user = request.user.object
    user_picture = request.session.get("user", {}).get("picture")
    has_documents = EntryAdapters.user_has_entries(user=user)

    return templates.TemplateResponse(
        "search.html",
        context={
            "request": request,
            "username": user.username,
            "user_photo": user_picture,
            "is_active": has_required_scope(request, ["premium"]),
            "has_documents": has_documents,
            "khoj_version": state.khoj_version,
        },
    )


@web_client.get("/chat", response_class=FileResponse)
@requires(["authenticated"], redirect="login_page")
def chat_page(request: Request):
    user = request.user.object
    user_picture = request.session.get("user", {}).get("picture")
    has_documents = EntryAdapters.user_has_entries(user=user)

    return templates.TemplateResponse(
        "chat.html",
        context={
            "request": request,
            "username": user.username,
            "user_photo": user_picture,
            "is_active": has_required_scope(request, ["premium"]),
            "has_documents": has_documents,
            "khoj_version": state.khoj_version,
        },
    )


@web_client.get("/login", response_class=FileResponse)
def login_page(request: Request):
    if request.user.is_authenticated:
        next_url = request.query_params.get("next", "/")
        return RedirectResponse(url=next_url)
    google_client_id = os.environ.get("GOOGLE_CLIENT_ID")
    redirect_uri = str(request.app.url_path_for("auth"))
    return templates.TemplateResponse(
        "login.html",
        context={
            "request": request,
            "google_client_id": google_client_id,
            "redirect_uri": redirect_uri,
        },
    )


@web_client.get("/config", response_class=HTMLResponse)
@requires(["authenticated"], redirect="login_page")
def config_page(request: Request):
    user: KhojUser = request.user.object
    user_picture = request.session.get("user", {}).get("picture")
    has_documents = EntryAdapters.user_has_entries(user=user)

    user_subscription_state = get_user_subscription_state(user.email)
    user_subscription = adapters.get_user_subscription(user.email)
    subscription_renewal_date = (
        user_subscription.renewal_date.strftime("%d %b %Y")
        if user_subscription and user_subscription.renewal_date
        else (user_subscription.created_at + timedelta(days=7)).strftime("%d %b %Y")
    )
    given_name = get_user_name(user)

    enabled_content_source = set(EntryAdapters.get_unique_file_sources(user))
    successfully_configured = {
        "computer": ("computer" in enabled_content_source),
        "github": ("github" in enabled_content_source),
        "notion": ("notion" in enabled_content_source),
    }

    selected_conversation_config = ConversationAdapters.get_conversation_config(user)
    conversation_options = ConversationAdapters.get_conversation_processor_options().all()
    all_conversation_options = list()
    for conversation_option in conversation_options:
        all_conversation_options.append({"chat_model": conversation_option.chat_model, "id": conversation_option.id})

    search_model_options = adapters.get_or_create_search_models().all()
    all_search_model_options = list()
    for search_model_option in search_model_options:
        all_search_model_options.append({"name": search_model_option.name, "id": search_model_option.id})

    current_search_model_option = adapters.get_user_search_model_or_default(user)

    return templates.TemplateResponse(
        "config.html",
        context={
            "request": request,
            "current_model_state": successfully_configured,
            "anonymous_mode": state.anonymous_mode,
            "username": user.username,
            "given_name": given_name,
            "conversation_options": all_conversation_options,
            "search_model_options": all_search_model_options,
            "selected_search_model_config": current_search_model_option.id,
            "selected_conversation_config": selected_conversation_config.id if selected_conversation_config else None,
            "user_photo": user_picture,
            "billing_enabled": state.billing_enabled,
            "subscription_state": user_subscription_state,
            "subscription_renewal_date": subscription_renewal_date,
            "khoj_cloud_subscription_url": os.getenv("KHOJ_CLOUD_SUBSCRIPTION_URL"),
            "is_active": has_required_scope(request, ["premium"]),
            "has_documents": has_documents,
            "is_twilio_enabled": is_twilio_enabled(),
            "phone_number": user.phone_number,
            "is_phone_number_verified": user.verified_phone_number,
            "khoj_version": state.khoj_version,
        },
    )


@web_client.get("/config/content-source/github", response_class=HTMLResponse)
@requires(["authenticated"], redirect="login_page")
def github_config_page(request: Request):
    user = request.user.object
    user_picture = request.session.get("user", {}).get("picture")
    has_documents = EntryAdapters.user_has_entries(user=user)
    current_github_config = get_user_github_config(user)

    if current_github_config:
        raw_repos = current_github_config.githubrepoconfig.all()
        repos = []
        for repo in raw_repos:
            repos.append(
                GithubRepoConfig(
                    name=repo.name,
                    owner=repo.owner,
                    branch=repo.branch,
                )
            )
        current_config = GithubContentConfig(
            pat_token=current_github_config.pat_token,
            repos=repos,
        )
        current_config = json.loads(current_config.json())
    else:
        current_config = {}  # type: ignore

    return templates.TemplateResponse(
        "content_source_github_input.html",
        context={
            "request": request,
            "current_config": current_config,
            "username": user.username,
            "user_photo": user_picture,
            "is_active": has_required_scope(request, ["premium"]),
            "has_documents": has_documents,
            "khoj_version": state.khoj_version,
        },
    )


@web_client.get("/config/content-source/notion", response_class=HTMLResponse)
@requires(["authenticated"], redirect="login_page")
def notion_config_page(request: Request):
    user = request.user.object
    user_picture = request.session.get("user", {}).get("picture")
    has_documents = EntryAdapters.user_has_entries(user=user)
    current_notion_config = get_user_notion_config(user)

    current_config = NotionContentConfig(
        token=current_notion_config.token if current_notion_config else "",
    )

    current_config = json.loads(current_config.json())

    return templates.TemplateResponse(
        "content_source_notion_input.html",
        context={
            "request": request,
            "current_config": current_config,
            "username": user.username,
            "user_photo": user_picture,
            "is_active": has_required_scope(request, ["premium"]),
            "has_documents": has_documents,
            "khoj_version": state.khoj_version,
        },
    )


@web_client.get("/config/content-source/computer", response_class=HTMLResponse)
@requires(["authenticated"], redirect="login_page")
def computer_config_page(request: Request):
    user = request.user.object
    user_picture = request.session.get("user", {}).get("picture")
    has_documents = EntryAdapters.user_has_entries(user=user)

    return templates.TemplateResponse(
        "content_source_computer_input.html",
        context={
            "request": request,
            "username": user.username,
            "user_photo": user_picture,
            "is_active": has_required_scope(request, ["premium"]),
            "has_documents": has_documents,
            "khoj_version": state.khoj_version,
        },
    )
