"""Views for PI FYAD plugin."""

from django.contrib.auth.decorators import login_required, permission_required
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.views.decorators.http import require_POST

from allianceauth.eveonline.models import EveCharacter

from .clipboard import ClipboardParser, ClipboardSerializer
from .constants import VISIBILITY_CHOICES
from .forms import PlanetTemplateForm
from .models import (
    CharacterOwner,
    CharacterPlanet,
    PlanetPin,
    PlanetTemplate,
)


@login_required
@permission_required("pi_fyad.view_pi")
def dashboard(request):
    """Main PI dashboard — summary cards + character table + alerts."""
    user = request.user
    characters = EveCharacter.objects.filter(
        character_ownership__user=user
    )
    char_ids = [c.pk for c in characters]
    owners = CharacterOwner.objects.filter(character__in=char_ids)

    # Build per-character summary
    character_data = []
    critical_planets = []

    for owner in owners:
        planets = owner.planets.all().prefetch_related("pins")
        total_extractors = 0
        active_extractors = 0
        expired_extractors = 0
        total_planets = planets.count()

        for planet in planets:
            summary = planet.extractor_summary
            total_extractors += summary["active"] + summary["idle"] + summary["expired"]
            active_extractors += summary["active"]
            expired_extractors += summary["expired"]

            if planet.has_critical_alerts:
                critical_planets.append(planet)

        character_data.append({
            "character": owner.character,
            "total_planets": total_planets,
            "total_extractors": total_extractors,
            "active_extractors": active_extractors,
            "expired_extractors": expired_extractors,
            "owner": owner,
        })

    context = {
        "character_data": character_data,
        "critical_planets": critical_planets,
        "total_characters": len(character_data),
    }
    return render(request, "pi_fyad/dashboard.html", context)


@login_required
@permission_required("pi_fyad.view_pi")
def character_planets(request, character_id):
    """List all planets for a specific character."""
    character = get_object_or_404(EveCharacter, pk=character_id)

    # Permission check: own character, or corp/alliance permissions
    if not _can_view_character(request.user, character):
        return render(request, "pi_fyad/partials/no_access.html", status=403)

    owner = get_object_or_404(CharacterOwner, character=character)
    planets = owner.planets.all().prefetch_related("pins", "pins__contents")

    planet_data = []
    for planet in planets:
        planet_data.append({
            "planet": planet,
            "extractors": planet.pins.filter(is_extractor=True),
            "factories": planet.pins.filter(is_factory=True).order_by("-factory_tier"),
            "storage_pins": planet.pins.filter(is_storage=True),
            "summary": planet.extractor_summary,
        })

    context = {
        "character": character,
        "owner": owner,
        "planet_data": planet_data,
    }
    return render(request, "pi_fyad/character_planets.html", context)


@login_required
@permission_required("pi_fyad.view_pi")
def planet_detail(request, character_id, planet_id):
    """Detailed view of a single planet — pins, storage, extractors."""
    character = get_object_or_404(EveCharacter, pk=character_id)

    if not _can_view_character(request.user, character):
        return render(request, "pi_fyad/partials/no_access.html", status=403)

    owner = get_object_or_404(CharacterOwner, character=character)
    planet = get_object_or_404(
        CharacterPlanet, owner=owner, planet_id=planet_id
    )
    pins = planet.pins.all().prefetch_related("contents")

    # Group pins by category
    extractors = [p for p in pins if p.is_extractor]
    factories = [p for p in pins if p.is_factory]
    storage_pins = [p for p in pins if p.is_storage]
    other_pins = [p for p in pins if not p.is_extractor and not p.is_factory and not p.is_storage]

    # Group factories by tier (highest first)
    factory_tiers = {}
    for f in factories:
        tier = f.factory_tier
        factory_tiers.setdefault(tier, []).append(f)

    context = {
        "character": character,
        "planet": planet,
        "extractors": extractors,
        "factory_tiers": dict(sorted(factory_tiers.items(), reverse=True)),
        "storage_pins": storage_pins,
        "other_pins": other_pins,
        "summary": planet.extractor_summary,
    }
    return render(request, "pi_fyad/planet_detail.html", context)


@login_required
@permission_required("pi_fyad.manage_templates")
def template_list(request):
    """List all templates visible to the user."""
    main_char = request.user.profile.main_character
    if main_char:
        templates = PlanetTemplate.objects.visible_to_character(main_char)
    else:
        templates = PlanetTemplate.objects.none()

    context = {
        "templates": templates,
        "visibility_choices": VISIBILITY_CHOICES,
    }
    return render(request, "pi_fyad/template_list.html", context)


@login_required
@permission_required("pi_fyad.manage_templates")
def template_detail(request, template_id):
    """View a single template's details."""
    template = get_object_or_404(PlanetTemplate, pk=template_id)

    # Check visibility
    main_char = request.user.profile.main_character
    if main_char:
        visible = PlanetTemplate.objects.visible_to_character(main_char).filter(pk=template_id).exists()
    else:
        visible = False

    if not visible:
        return render(request, "pi_fyad/partials/no_access.html", status=403)

    # Generate clipboard export
    serializer = ClipboardSerializer()
    clipboard_text = serializer.serialize(template)

    context = {
        "template": template,
        "template_pins": template.template_pins.all(),
        "clipboard_text": clipboard_text,
    }
    return render(request, "pi_fyad/template_detail.html", context)


@login_required
@permission_required("pi_fyad.manage_templates")
def template_create(request):
    """Create a new template from clipboard paste."""
    if request.method == "POST":
        form = PlanetTemplateForm(request.POST)
        if form.is_valid():
            clipboard_text = form.cleaned_data["clipboard_raw"]
            parser = ClipboardParser()
            try:
                parsed = parser.parse(clipboard_text)
            except ValueError as e:
                form.add_error("clipboard_raw", str(e))
                return render(request, "pi_fyad/template_create.html", {"form": form})

            template = form.save(commit=False)
            template.template_data = parsed["data"]
            template.pin_count = parsed["pin_count"]
            template.factory_count = parsed["factory_count"]
            template.extractor_count = parsed["extractor_count"]
            template.output_products = parsed["output_products"]
            template.created_by = request.user.profile.main_character

            # Set corp/alliance from character
            main_char = request.user.profile.main_character
            if main_char:
                template.corporation_id = main_char.corporation_id
                template.alliance_id = main_char.alliance_id

            template.save()

            # Create template pins
            for pin_data in parsed.get("pins", []):
                template.template_pins.create(**pin_data)

            return redirect("pi_fyad:template_detail", template_id=template.pk)
    else:
        form = PlanetTemplateForm()

    return render(request, "pi_fyad/template_create.html", {"form": form})


@login_required
@permission_required("pi_fyad.manage_templates")
@require_POST
def template_clipboard_export(request, template_id):
    """AJAX endpoint: return clipboard text for a template."""
    template = get_object_or_404(PlanetTemplate, pk=template_id)
    serializer = ClipboardSerializer()
    clipboard_text = serializer.serialize(template)
    return JsonResponse({"clipboard": clipboard_text})


def _can_view_character(user, character) -> bool:
    """Check if user can view a character's PI data."""
    # Own characters
    own_chars = EveCharacter.objects.filter(
        character_ownership__user=user
    ).values_list("pk", flat=True)
    if character.pk in own_chars:
        return True

    # Corp permission
    if user.has_perm("pi_fyad.view_corp_pi"):
        main = user.profile.main_character
        if main and main.corporation_id == character.corporation_id:
            return True

    # Alliance permission
    if user.has_perm("pi_fyad.view_alliance_pi"):
        main = user.profile.main_character
        if main and main.alliance_id and main.alliance_id == character.alliance_id:
            return True

    return False
