# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 I-Form.
#
# invenio-theme-iform is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
# details.

"""I-Form administration views."""

import json
import os
from datetime import datetime

from flask import current_app, flash, redirect, request, url_for
from invenio_accounts.models import Role, User
from invenio_accounts.proxies import current_accounts
from invenio_administration.views.base import AdminView
from invenio_db import db
from invenio_i18n import lazy_gettext as _


def get_site_settings_path():
    """Get the path to site_settings.json."""
    app_data_dir = os.path.join(current_app.instance_path, "app_data")
    os.makedirs(app_data_dir, exist_ok=True)
    return os.path.join(app_data_dir, "site_settings.json")


def get_site_settings():
    """Load site settings from JSON file."""
    path = get_site_settings_path()
    if not os.path.exists(path):
        return {"registration_enabled": True}
    try:
        with open(path, "r") as f:
            return json.load(f)
    except Exception:
        return {"registration_enabled": True}


def set_site_settings(settings):
    """Save site settings to JSON file."""
    path = get_site_settings_path()
    with open(path, "w") as f:
        json.dump(settings, f, indent=2)


class RoleManagementView(AdminView):
    """Admin view for managing user roles."""

    name = "roles"
    category = "User management"
    template = "invenio_theme_iform/administration/roles.html"
    url = "/roles"
    menu_label = _("Role Assignment")
    icon = "users"

    def get(self):
        """Render the role management template."""
        roles = Role.query.order_by(Role.name).all()
        selected_role_id = request.args.get("role_id")

        users = []
        selected_role = None
        if selected_role_id:
            selected_role = Role.query.get(selected_role_id)
            if selected_role:
                users = User.query.order_by(User.email).all()

        return self.render(
            roles=roles,
            selected_role=selected_role,
            users=users,
        )

    def post(self):
        """Handle role assignment/revocation."""
        user_id = request.form.get("user_id")
        role_id = request.form.get("role_id")
        action = request.form.get("action")

        if not (user_id and role_id and action):
            flash(_("Missing required fields."), "error")
            return redirect(url_for("administration.roles", role_id=role_id))

        try:
            user = User.query.get(int(user_id))
        except ValueError:
            user = None

        role = Role.query.get(role_id)

        if not user or not role:
            flash(_("User or role not found."), "error")
            return redirect(url_for("administration.roles", role_id=role_id))

        if action == "enable":
            if role not in user.roles:
                current_accounts.datastore.add_role_to_user(user, role)
                flash(
                    _("Role {role} enabled for {email}.").format(
                        role=role.name, email=user.email
                    ),
                    "success",
                )
        elif action == "disable":
            if role in user.roles:
                current_accounts.datastore.remove_role_from_user(user, role)
                flash(
                    _("Role {role} disabled for {email}.").format(
                        role=role.name, email=user.email
                    ),
                    "success",
                )

        db.session.commit()
        return redirect(url_for("administration.roles", role_id=role_id))


class RegistrationSettingsView(AdminView):
    """Admin view for controlling site registration settings."""

    name = "registration-settings"
    category = "Site Settings"
    template = "invenio_theme_iform/administration/registration_settings.html"
    url = "/registration-settings"
    menu_label = _("Registration Settings")
    icon = "setting"

    def get(self):
        """Render registration settings page."""
        settings = get_site_settings()
        return self.render(
            registration_enabled=settings.get("registration_enabled", True)
        )

    def post(self):
        """Handle registration settings update."""
        enabled = request.form.get("registration_enabled") == "true"
        settings = get_site_settings()
        settings["registration_enabled"] = enabled
        set_site_settings(settings)

        status_str = _("enabled") if enabled else _("disabled")
        flash(
            _("Public user registration has been {status}.").format(
                status=status_str
            ),
            "success",
        )
        return redirect(url_for("administration.registration-settings"))


class UserCreateView(AdminView):
    """Admin view for creating users."""

    name = "create-user"
    category = "User management"
    template = "invenio_theme_iform/administration/user_create.html"
    url = "/create-user"
    menu_label = _("Create User")
    icon = "user plus"

    def get(self):
        """Render user creation page."""
        return self.render()

    def post(self):
        """Handle manual user creation."""
        from flask_security.utils import hash_password
        from invenio_access.permissions import system_identity
        from invenio_users_resources.proxies import current_users_service

        email = request.form.get("email", "").strip()
        password = request.form.get("password", "").strip()
        confirm_email = request.form.get("confirm_email") == "true"

        if not email or not password:
            flash(_("Email and Password are required."), "error")
            return redirect(url_for("administration.create-user"))

        if User.query.filter_by(email=email).first():
            flash(_("A user with this email already exists."), "error")
            return redirect(url_for("administration.create-user"))

        try:
            user_kwargs = {
                "email": email,
                "password": hash_password(password),
                "active": True,
            }
            if confirm_email:
                user_kwargs["confirmed_at"] = datetime.utcnow()

            user = current_accounts.datastore.create_user(**user_kwargs)
            db.session.commit()

            # Index the newly created user in search engine
            try:
                from invenio_search import current_search_client
                current_users_service.reindex(system_identity, uids=[user.id])
                current_users_service.indexer.process_bulk_queue()
                current_search_client.indices.refresh(index="*")
            except Exception as ie:
                current_app.logger.warning("Failed to index user %s: %s", user.id, str(ie))

            flash(
                _("User {email} created successfully.").format(email=email),
                "success",
            )
        except Exception as e:
            db.session.rollback()
            flash(
                _("Failed to create user: {error}").format(error=str(e)),
                "error",
            )

        return redirect(url_for("administration.create-user"))
