from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.views.decorators.gzip import gzip_page

from territories_dashboard_lib.indicators_lib.models import Indicator, Theme
from territories_dashboard_lib.superset_lib.logic import make_filter
from territories_dashboard_lib.superset_lib.models import Dashboard
from territories_dashboard_lib.superset_lib.serializers import serialize_dashboard
from territories_dashboard_lib.tracking_lib.logic import track_page
from territories_dashboard_lib.website_lib.logic import (
    get_favorite_theme,
)
from territories_dashboard_lib.website_lib.models import (
    GlossaryItem,
    LandingPage,
    StaticPage,
)
from territories_dashboard_lib.website_lib.params import with_params
from territories_dashboard_lib.website_lib.serializers import (
    serialize_indicator,
    serialize_sub_themes,
)
from territories_dashboard_lib.website_lib.views.utils import (
    apply_filters,
    get_base_url,
    get_favorite_indicators_ids,
    get_theme_and_sub_themes,
    get_themes,
)


@gzip_page
def landing_page_view(request):
    landing_page = LandingPage.objects.first()
    response = render(
        request,
        "territories_dashboard_lib/website/pages/page.html",
        {"landing_page": landing_page},
    )
    response = track_page(request=request, response=response)
    return response


@gzip_page
def static_page_view(request, page_url):
    static_page = get_object_or_404(StaticPage, url=page_url)
    return render(
        request,
        "territories_dashboard_lib/website/pages/static/page.html",
        {"static_page": static_page},
    )


@gzip_page
def lexique_page_view(request):
    lexique = GlossaryItem.objects.all()
    context = {"lexique": lexique}
    response = render(
        request, "territories_dashboard_lib/website/pages/lexique/page.html", context
    )
    return response


def themes_redirect_view(request):
    first_theme = Theme.objects.order_by("ordering").first()
    if getattr(request.user, "has_favorite_indicators", None):
        first_theme = get_favorite_theme()
    target_url = reverse("website:theme", kwargs={"theme_name": first_theme.name})
    get_params = request.GET.urlencode()
    if get_params:
        target_url = f"{target_url}?{get_params}"
    return redirect(target_url)


@gzip_page
@with_params
def comparison_view(request, *, theme_name, context):
    theme, sub_themes = get_theme_and_sub_themes(request, theme_name)
    themes = get_themes(request)
    context["theme"] = theme
    context["themes"] = themes
    context["sub_themes"] = sub_themes
    context["favorite_indicators_ids"] = get_favorite_indicators_ids(request)
    response = render(
        request,
        "territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/page.html",
        context,
    )
    response = track_page(
        request=request,
        response=response,
        params=context["params"],
        theme=theme,
    )
    return response


def comparison_redirect_view(request):
    first_theme = Theme.objects.order_by("ordering").first()
    if getattr(request.user, "has_favorite_indicators", None):
        first_theme = get_favorite_theme()
    target_url = reverse("website:comparison", kwargs={"theme_name": first_theme.name})
    get_params = request.GET.urlencode()
    if get_params:
        target_url = f"{target_url}?{get_params}"
    return redirect(target_url)


@gzip_page
@with_params
def theme_page_view(request, *, theme_name, context):
    theme, sub_themes = get_theme_and_sub_themes(request, theme_name)
    themes = get_themes(request)
    context["theme"] = theme
    context["themes"] = themes
    context["sub_themes"] = sub_themes
    context["favorite_indicators_ids"] = get_favorite_indicators_ids(request)
    response = render(
        request,
        "territories_dashboard_lib/website/pages/indicators/themes/page.html",
        context,
    )
    response = track_page(
        request=request,
        response=response,
        params=context["params"],
        theme=theme,
    )
    return response


@gzip_page
@with_params
def indicator_details_view(request, *, indicator_name, context):
    indicator = get_object_or_404(Indicator, name=indicator_name)
    theme = indicator.sub_theme.theme
    sub_themes = serialize_sub_themes(theme)
    themes = get_themes(request)
    filters = apply_filters(request, indicator)
    context["indicator"] = serialize_indicator(indicator)
    context["themes"] = themes
    context["theme"] = theme
    context["subtheme"] = indicator.sub_theme
    context["sub_themes"] = sub_themes
    context["filters"] = filters
    response = render(
        request,
        "territories_dashboard_lib/website/pages/indicators/details/page.html",
        context=context,
    )
    response = track_page(
        request=request,
        response=response,
        params=context["params"],
        indicator=indicator,
        theme=theme,
    )
    return response


@gzip_page
def indicator_methodo_view(request, *, indicator_name):
    indicator = get_object_or_404(Indicator, name=indicator_name)
    theme = indicator.sub_theme.theme
    context = {
        "indicator": serialize_indicator(indicator),
        "theme": theme,
    }
    response = render(
        request,
        "territories_dashboard_lib/website/pages/indicators/methodo/page.html",
        context,
    )
    response = track_page(
        request=request,
        response=response,
        indicator=indicator,
        theme=theme,
    )
    return response


@with_params
def superset_view(request, dashboard_name, context):
    dashboard = get_object_or_404(Dashboard, short_name=dashboard_name)
    context["dashboard"] = serialize_dashboard(dashboard)
    filter_string = make_filter(
        dashboard,
        context["params"]["territory_id"],
        context["params"]["territory_mesh"],
    )
    if filter_string:
        context["dashboard_filter"] = filter_string
    response = render(
        request,
        "territories_dashboard_lib/website/pages/superset/page.html",
        context=context,
    )
    response = track_page(request=request, response=response)
    return response


def handler_404_view(request, exception):
    return render(request, "territories_dashboard_lib/website/404.html", status=404)


def handler_500_view(request):
    return render(request, "territories_dashboard_lib/website/500.html", status=500)


@gzip_page
def sitemap_view(request):
    context = {
        "themes": [
            {"title": theme.title, "name": theme.name}
            for theme in Theme.objects.all().order_by("ordering")
        ],
        "indicators": [
            {"title": indicator.title, "name": indicator.name}
            for indicator in Indicator.objects.all().order_by("index_in_theme")
        ],
        "static_pages": [
            {"title": static_page.name, "url": static_page.url}
            for static_page in StaticPage.objects.all()
        ],
        "lexique": GlossaryItem.objects.exists(),
    }
    response = render(
        request, "territories_dashboard_lib/website/pages/sitemap/page.html", context
    )
    response = track_page(request=request, response=response)
    return response


def raw_sitemap_view(request):
    """Generate XML sitemap for search engines."""
    base_url = get_base_url(request)

    urls = []

    # Landing page
    urls.append(f"{base_url}{reverse('website:landing-page')}")

    # Theme pages
    for theme in Theme.objects.all().order_by("ordering"):
        urls.append(
            f"{base_url}{reverse('website:theme', kwargs={'theme_name': theme.name})}"
        )

    # Comparison pages
    for theme in Theme.objects.all().order_by("ordering"):
        urls.append(
            f"{base_url}{reverse('website:comparison', kwargs={'theme_name': theme.name})}"
        )

    # Indicator detail pages
    for indicator in Indicator.objects.all().order_by("index_in_theme"):
        urls.append(
            f"{base_url}{reverse('website:indicator-details', kwargs={'indicator_name': indicator.name})}"
        )
        # Indicator methodology pages
        urls.append(
            f"{base_url}{reverse('website:indicator-methodo', kwargs={'indicator_name': indicator.name})}"
        )

    # Static pages
    for static_page in StaticPage.objects.all():
        urls.append(
            f"{base_url}{reverse('website:static-page', kwargs={'page_url': static_page.url})}"
        )

    # Lexique page (if glossary items exist)
    if GlossaryItem.objects.exists():
        urls.append(f"{base_url}{reverse('website:lexique')}")

    # Sitemap page itself
    urls.append(f"{base_url}{reverse('website:sitemap')}")

    # Generate XML
    xml_lines = [
        '<?xml version="1.0" encoding="UTF-8"?>',
        '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
    ]

    for url in urls:
        xml_lines.append("  <url>")
        xml_lines.append(f"    <loc>{url}</loc>")
        xml_lines.append("  </url>")

    xml_lines.append("</urlset>")

    xml_content = "\n".join(xml_lines)

    return HttpResponse(xml_content, content_type="application/xml")


def robots_txt_view(request):
    base_url = get_base_url(request)
    text_content = f"User-agent: *\nSitemap: {base_url}/sitemap.xml"
    return HttpResponse(text_content, content_type="text/plain")
