from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.views.decorators.http import require_http_methods

from accounts.decorators import seeker_required
from companies.models import Company

from .completion import SECTIONS, completion
from .profile_forms import ITEM_TYPES, LANGUAGES, SECTION_FORMS, SECTION_ITEMS
from .models import SeekerProfile


def sync_profile_text(profile):
    """Keep the plain-text summary fields (used by search, matching and cards) in step with the structured items."""
    changed = []
    roles = [f'{e.title} at {e.company}' + (f' ({e.period})' if e.period else '') for e in profile.experiences.all()]
    if roles:
        profile.experience_summary = '\n'.join(roles)
        changed.append('experience_summary')
    schools = [f'{e.qualification}, {e.institution}' + (f' ({e.period})' if e.period else '') for e in profile.education_items.all()]
    if schools:
        profile.education = '\n'.join(schools)
        changed.append('education')
    if profile.experiences.exists():
        current = profile.experiences.filter(is_current=True).first() or profile.experiences.first()
        if not profile.current_job_title:
            profile.current_job_title = current.title
            changed.append('current_job_title')
        if not profile.current_employer and current.is_current:
            profile.current_employer = current.company
            changed.append('current_employer')
    if changed:
        SeekerProfile.objects.filter(pk=profile.pk).update(**{f: getattr(profile, f) for f in changed})


def _section_url(section):
    return f"{reverse('seekers:edit_profile')}?section={section}"


def _after_save(request, section, profile=None):
    """Save and continue jumps to the next section that still has something missing,
    not just the next one in order, so the seeker always lands on unfinished work."""
    then = request.POST.get('then')
    if then == 'later':
        return redirect('seekers:dashboard')
    if then == 'next':
        keys = [k for k, _, _ in SECTIONS]
        index = keys.index(section)
        ordered = keys[index + 1:] + keys[:index + 1]
        section_done = completion(profile)['section_done'] if profile else {}
        next_section = next((k for k in ordered if not section_done.get(k, True)), None)
        if next_section:
            section = next_section
        elif index + 1 < len(keys):
            section = keys[index + 1]
    return redirect(_section_url(section))


def _get_profile(request):
    user = request.user
    profile = SeekerProfile.objects.filter(user=user).first()
    if profile:
        return profile
    from accounts.profile_setup import unique_slug

    name = user.get_full_name().strip() or user.username
    return SeekerProfile.objects.create(
        user=user, full_name=name, slug=unique_slug(SeekerProfile, name), headline='Job Seeker',
        category='General', location='Lusaka', is_public=False, visibility=SeekerProfile.Visibility.PRIVATE)


def _item_prefix(kind, pk):
    return f'{kind}{pk or "new"}'


def _build_item_blocks(profile, section, bound):
    blocks = []
    for kind in SECTION_ITEMS.get(section, []):
        model, form_class, heading, intro, add_label = ITEM_TYPES[kind]
        items = []
        for obj in getattr(profile, _related_name(kind)).all():
            key = f'{kind}:{obj.pk}'
            form = bound.get(key) or form_class(instance=obj, prefix=_item_prefix(kind, obj.pk))
            items.append({'obj': obj, 'form': form, 'open': key in bound})
        new_key = f'{kind}:new'
        blocks.append({
            'kind': kind, 'heading': heading, 'intro': intro, 'add_label': add_label, 'items': items,
            'new_form': bound.get(new_key) or form_class(prefix=_item_prefix(kind, None)),
            'new_open': new_key in bound,
        })
    return blocks


def _related_name(kind):
    return {
        'experience': 'experiences', 'volunteer': 'volunteering', 'education': 'education_items',
        'certification': 'certifications', 'membership': 'memberships', 'language': 'languages',
        'project': 'projects', 'achievement': 'achievements', 'reference': 'references',
    }[kind]


def _handle_item(request, profile):
    """Returns (redirect_response_or_None, bound_forms_dict)."""
    action = request.POST.get('action', '')
    kind = request.POST.get('kind', '')
    if kind not in ITEM_TYPES:
        return None, {}
    model, form_class, heading, _intro, _add = ITEM_TYPES[kind]
    related = getattr(profile, _related_name(kind))
    pk = request.POST.get('item')
    if action == 'item_delete':
        get_object_or_404(model, pk=pk, seeker=profile).delete()
        sync_profile_text(profile)
        messages.success(request, 'Removed.')
        return redirect(request.get_full_path().split('#')[0]), {}
    instance = get_object_or_404(model, pk=pk, seeker=profile) if action == 'item_update' else None
    form = form_class(request.POST, instance=instance, prefix=_item_prefix(kind, instance.pk if instance else None))
    if form.is_valid():
        obj = form.save(commit=False)
        obj.seeker = profile
        if not instance:
            obj.position = related.count()
        obj.save()
        sync_profile_text(profile)
        messages.success(request, 'Saved.')
        return None, {'ok': True}
    messages.error(request, 'Please fix the highlighted fields and save again.')
    return None, {f'{kind}:{instance.pk if instance else "new"}': form}


@login_required
@seeker_required
@require_http_methods(['GET', 'POST'])
def edit_profile(request):
    from companies.models import Company as _C

    profile = _get_profile(request)
    if not profile:
        messages.warning(request, 'No profile found for your account.')
        return redirect('seekers:dashboard')

    valid = {k for k, _, _ in SECTIONS}
    section = request.POST.get('section') or request.GET.get('section') or 'basics'
    if section not in valid:
        section = 'basics'

    form = None
    bound = {}
    if request.method == 'POST':
        if request.POST.get('action', '').startswith('item_') and section in SECTION_ITEMS:
            response, bound = _handle_item(request, profile)
            if response:
                return response
            if bound.get('ok'):
                return redirect(_section_url(section) + '#' + request.POST.get('kind', ''))
            if section in SECTION_FORMS:
                form = SECTION_FORMS[section](instance=profile)
        elif section in SECTION_FORMS:
            form = SECTION_FORMS[section](request.POST, request.FILES, instance=profile)
            if form.is_valid():
                profile = form.save()
                sync_profile_text(profile)
                messages.success(request, 'Saved.')
                return _after_save(request, section, profile)
            messages.error(request, 'Please fix the highlighted fields and save again.')
        else:
            return _after_save(request, section, profile)
    elif section in SECTION_FORMS:
        form = SECTION_FORMS[section](instance=profile)

    progress = completion(profile)
    context = {
        'profile': profile,
        'seeker_nav': 'profile',
        'section': section,
        'sections': [{'key': k, 'label': l, 'icon': i, 'done': progress['section_done'].get(k, False)} for k, l, i in SECTIONS],
        'progress': progress,
        'form': form,
        'item_blocks': _build_item_blocks(profile, section, bound),
        'company_names': list(_C.objects.filter(is_active=True).order_by('name').values_list('name', flat=True)[:400]),
        'language_names': LANGUAGES,
    }
    return render(request, 'seekers/profile_edit/edit.html', context)
