from flask import request
from flask_jwt_extended import get_jwt_identity, jwt_required
import uuid
from app.api import api_bp
from app.extensions import db
from app.models.user import User
from app.models.master import SavingsPlanMember
from app.models.transactions import ReleaseRequest, Credit, Loan
from app.services.release_service import process_release
from app.services.email_service import send_templated_email
from app.services.notification_service import create_notification
from app.utils.auth import role_required
from app.utils.response import ok, fail


@api_bp.post("/release-requests")
@jwt_required()
def create_release_request():
    user = User.query.get(get_jwt_identity())
    data = request.json or {}
    member = SavingsPlanMember.query.filter_by(user_id=user.id, status="active").first()
    if not member:
        return fail("Must be enrolled in savings plan to request release", 403)

    release_request_id = data.get("release_request_id") or f"REL-{uuid.uuid4().hex[:8].upper()}"
    release_request = ReleaseRequest(
        release_request_id=release_request_id,
        member_id=member.member_id,
        current_savings=float(data["current_savings"]),
        outstanding_loan=float(data["outstanding_loan"]),
        release_amount=float(data["release_amount"]),
        notes=data.get("notes"),
        status="pending",
    )
    db.session.add(release_request)
    db.session.commit()

    send_templated_email(
        to=user.email,
        subject="Release Request Submitted",
        template="emails/release_request_submitted.html",
        cc_admin=True,
        request_id=release_request.release_request_id,
        amount=release_request.release_amount,
        member_name=user.full_name,
    )

    create_notification(
        user_id=user.id,
        title="Release request submitted",
        message=f"Release request {release_request.release_request_id} submitted.",
        notif_type="info",
        link="/app/requests",
    )

    return ok({"release_request_id": release_request.release_request_id}, "Release request submitted", 201)


@api_bp.get("/release-requests")
@jwt_required()
def list_release_requests():
    user = User.query.get(get_jwt_identity())
    query = ReleaseRequest.query
    if user.access_level == "member":
        member_ids = [m.member_id for m in SavingsPlanMember.query.filter_by(user_id=user.id).all()]
        if member_ids:
            query = query.filter(ReleaseRequest.member_id.in_(member_ids))
        else:
            query = query.filter_by(member_id="")
    requests = query.order_by(ReleaseRequest.created_at.desc()).all()
    data = [
        {
            "id": rr.id,
            "release_request_id": rr.release_request_id,
            "member_id": rr.member_id,
            "current_savings": rr.current_savings,
            "outstanding_loan": rr.outstanding_loan,
            "release_amount": rr.release_amount,
            "cashier_id": rr.cashier_id,
            "status": rr.status,
            "notes": rr.notes,
            "created_at": rr.created_at.isoformat(),
        }
        for rr in requests
    ]
    return ok(data)


@api_bp.get("/release-requests/view")
@jwt_required()
def list_release_requests_view():
    from app.services.settings_service import is_allowed

    user = User.query.get(get_jwt_identity())
    if not user:
        return fail("Unauthorized", 401)
    if user.access_level != "administrator" and not is_allowed(user.access_level, "requests.view_all"):
        return fail("Forbidden", 403)

    requests = ReleaseRequest.query.order_by(ReleaseRequest.created_at.desc()).all()
    data = [
        {
            "id": rr.id,
            "release_request_id": rr.release_request_id,
            "member_id": rr.member_id,
            "member_short_name": rr.member.member_short_name if rr.member else None,
            "user_full_name": rr.member.user.full_name if rr.member and rr.member.user else None,
            "release_amount": rr.release_amount,
            "status": rr.status,
            "created_at": rr.created_at.isoformat(),
        }
        for rr in requests
    ]
    return ok(data)


@api_bp.post("/release-requests/<int:request_id>/process")
@role_required("administrator")
def process_release_request(request_id):
    release_request = ReleaseRequest.query.get_or_404(request_id)
    data = request.json or {}
    action = data.get("action")
    cashier_id = data.get("cashier_id")
    notes = data.get("notes")
    allocations = data.get("allocations")
    force = bool(data.get("force", False))

    if action not in ["reject", "release"]:
        return fail("Invalid action", 400)

    try:
        updated = process_release(release_request, action, cashier_id, notes, allocations=allocations, force=force)
    except ValueError as e:
        return fail(str(e), 400)
    return ok({"release_request_id": updated.release_request_id}, "Release request processed")


@api_bp.get("/release-requests/financial/<string:member_id>")
@jwt_required()
def member_financial_data(member_id):
    member = SavingsPlanMember.query.filter_by(member_id=member_id, status="active").first_or_404()
    savings_credits = Credit.query.filter_by(member_id=member_id, transaction_type="savings").all()
    total_savings = sum(credit.savings_amount for credit in savings_credits if credit.savings_amount)

    active_loan = Loan.query.filter_by(member_id=member_id, status="active").first()
    outstanding_loan = 0
    if active_loan:
        loan_payments = Credit.query.filter_by(loan_id=active_loan.loan_id).all()
        total_paid = sum(payment.total_amount for payment in loan_payments)
        outstanding_loan = active_loan.amount - total_paid

    release_amount = max(0, total_savings - outstanding_loan)

    return ok(
        {
            "current_savings": total_savings,
            "outstanding_loan": outstanding_loan,
            "release_amount": release_amount,
        }
    )
