import builtins
import contextlib
import uuid
from collections.abc import Generator
from datetime import UTC, datetime
from typing import Annotated, Any, Literal, override

import structlog
from babel.numbers import format_currency
from fastapi import APIRouter, Depends, HTTPException, Query, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from pydantic import UUID4, BeforeValidator, ValidationError
from pydantic_core import PydanticCustomError
from sqlalchemy import or_, select
from sqlalchemy.orm import contains_eager, joinedload
from sse_starlette.sse import EventSourceResponse
from tagflow import classes, document, tag, text

from polar.account.service import (
    CannotChangeAdminError,
    UserNotOrganizationMemberError,
)
from polar.account.service import account as account_service
from polar.enums import AccountType
from polar.file.repository import FileRepository
from polar.file.service import file as file_service
from polar.file.sorting import FileSortProperty
from polar.integrations.plain.service import plain as plain_service
from polar.kit.pagination import PaginationParams
from polar.kit.schemas import empty_str_to_none
from polar.kit.sorting import Sorting
from polar.models import (
    Account,
    File,
    Organization,
    User,
    UserOrganization,
)
from polar.models.file import FileServiceTypes
from polar.models.organization import OrganizationStatus
from polar.models.organization_review import OrganizationReview
from polar.models.transaction import TransactionType
from polar.models.user import IdentityVerificationStatus
from polar.organization import sorting
from polar.organization.repository import OrganizationRepository
from polar.organization.schemas import OrganizationFeatureSettings
from polar.organization.service import organization as organization_service
from polar.organization.sorting import OrganizationSortProperty
from polar.postgres import AsyncSession, get_db_read_session, get_db_session
from polar.transaction.service.transaction import transaction as transaction_service
from polar.user.repository import UserRepository
from polar.user_organization.service import (
    CannotRemoveOrganizationAdmin,
    UserNotMemberOfOrganization,
)
from polar.user_organization.service import (
    OrganizationNotFound as UserOrgOrganizationNotFound,
)
from polar.user_organization.service import (
    user_organization as user_organization_service,
)

from .. import formatters
from ..components import accordion, button, datatable, description_list, input, modal
from ..layout import layout
from ..responses import HXRedirectResponse
from ..toast import add_toast
from .account_review._ai_review import AIReviewVerdict
from .account_review._payment_verdict import PaymentVerdict
from .account_review._setup_verdict import SetupVerdict
from .analytics import (
    OrganizationSetupAnalyticsService,
    PaymentAnalyticsService,
)
from .forms import (
    OrganizationOrdersImportForm,
    OrganizationStatusFormAdapter,
    UpdateOrganizationDetailsForm,
    UpdateOrganizationForm,
    UpdateOrganizationInternalNotesForm,
)
from .orders_import import orders_import_sse
from .schemas import PaymentStatistics, SetupVerdictData

router = APIRouter()

logger = structlog.getLogger(__name__)


def empty_str_to_none_before_enum(value: Any) -> Any:
    """Convert empty strings to None before enum parsing."""
    if isinstance(value, str) and value.strip() == "":
        return None
    return value


def empty_str_to_none_before_bool(value: Any) -> Any:
    """Convert empty strings to None before boolean parsing."""
    if isinstance(value, str) and value.strip() == "":
        return None
    if isinstance(value, str):
        if value.lower() in ("true", "1", "yes", "on"):
            return True
        elif value.lower() in ("false", "0", "no", "off"):
            return False
    return value


@contextlib.contextmanager
def organization_badge(organization: Organization) -> Generator[None]:
    with tag.div(classes="badge"):
        if organization.status == OrganizationStatus.ACTIVE:
            classes("badge-success")
        elif (
            organization.is_under_review
            or organization.status == OrganizationStatus.DENIED
        ):
            classes("badge-warning")
        else:
            classes("badge-secondary")
        text(organization.status.get_display_name())
    yield


class OrganizationStatusColumn(
    datatable.DatatableAttrColumn[Organization, OrganizationSortProperty]
):
    def render(self, request: Request, item: Organization) -> Generator[None] | None:
        with organization_badge(item):
            pass
        return None


class NextReviewThresholdColumn(
    datatable.DatatableAttrColumn[Organization, OrganizationSortProperty]
):
    def render(self, request: Request, item: Organization) -> Generator[None] | None:
        from babel.numbers import format_currency

        text(format_currency(item.next_review_threshold / 100, "USD", locale="en_US"))
        return None


class DaysInStatusColumn(
    datatable.DatatableAttrColumn[Organization, OrganizationSortProperty]
):
    def render(self, request: Request, item: Organization) -> Generator[None] | None:
        if item.status_updated_at:
            delta = datetime.now(UTC) - item.status_updated_at
            days = delta.days
        else:
            delta = datetime.now(UTC) - item.created_at
            days = delta.days

        if item.is_under_review:
            text(f"{days} days in review")
        else:
            text(f"{days} days since review")
        return None


class AccountTypeDescriptionListAttrItem(
    description_list.DescriptionListAttrItem[Account]
):
    def render(self, request: Request, item: Account) -> Generator[None] | None:
        account_type = item.account_type
        if account_type == AccountType.stripe:
            with tag.a(
                href=f"https://dashboard.stripe.com/connect/accounts/{item.stripe_id}",
                classes="link flex flex-row gap-1",
                target="_blank",
                rel="noopener noreferrer",
            ):
                text(account_type.get_display_name())
                with tag.div(classes="icon-external-link"):
                    pass
        else:
            text(account_type.get_display_name())
        return None


async def get_payment_statistics(
    session: AsyncSession, organization_id: UUID4
) -> PaymentStatistics:
    """Get all-time payment statistics for an organization."""

    analytics_service = PaymentAnalyticsService(session)

    # Get account ID for the organization
    account_id = await analytics_service.get_organization_account_id(organization_id)
    if not account_id:
        return PaymentStatistics(
            payment_count=0,
            p50_risk=0,
            p90_risk=0,
            refunds_count=0,
            transfer_sum=0,
            refunds_amount=0,
            total_payment_amount=0,
        )

    # Get payment statistics
    (
        payment_count,
        total_payment_amount,
        risk_scores,
    ) = await analytics_service.get_succeeded_payments_stats(organization_id)

    # Calculate risk percentiles and level
    p50_risk, p90_risk = analytics_service.calculate_risk_percentiles(risk_scores)

    # Get refund statistics
    refunds_count, refunds_amount = await analytics_service.get_refund_stats(
        organization_id
    )

    # Get transfer sum (used for review threshold checking)
    transfer_sum = await transaction_service.get_transactions_sum(
        session, account_id, type=TransactionType.balance
    )

    return PaymentStatistics(
        payment_count=payment_count,
        p50_risk=p50_risk,
        p90_risk=p90_risk,
        refunds_count=refunds_count,
        transfer_sum=transfer_sum,
        refunds_amount=refunds_amount,
        total_payment_amount=total_payment_amount,
    )


async def get_setup_verdict_data(
    organization: Organization, session: AsyncSession
) -> SetupVerdictData:
    """Get enhanced setup verdict for an organization."""

    analytics_service = OrganizationSetupAnalyticsService(session)

    # Get all setup metrics using helper methods
    checkout_links_count = await analytics_service.get_checkout_links_count(
        organization.id
    )
    webhooks_count = await analytics_service.get_webhooks_count(organization.id)
    org_tokens_count = await analytics_service.get_organization_tokens_count(
        organization.id
    )
    products_count = await analytics_service.get_products_count(organization.id)
    benefits_count = await analytics_service.get_benefits_count(organization.id)

    # Check user verification status (get the first user as owner)
    user_verified_result = await session.execute(
        select(User.identity_verification_status)
        .join(UserOrganization, User.id == UserOrganization.user_id)
        .where(UserOrganization.organization_id == organization.id)
        .limit(1)
    )
    user_verified_row = user_verified_result.first()
    user_verified = (
        user_verified_row[0] == IdentityVerificationStatus.verified
        if user_verified_row
        else False
    )

    # Check account charges and payouts enabled
    (
        account_charges_enabled,
        account_payouts_enabled,
    ) = await analytics_service.check_account_enabled(organization)

    # Calculate setup score using helper
    setup_score = analytics_service.calculate_setup_score(
        checkout_links_count=checkout_links_count,
        webhooks_count=webhooks_count,
        org_tokens_count=org_tokens_count,
        products_count=products_count,
        benefits_count=benefits_count,
        user_verified=user_verified,
        account_charges_enabled=account_charges_enabled,
        account_payouts_enabled=account_payouts_enabled,
    )

    return SetupVerdictData(
        checkout_links_count=checkout_links_count,
        webhooks_count=webhooks_count,
        api_keys_count=org_tokens_count,  # Only organization tokens now
        products_count=products_count,
        benefits_count=benefits_count,
        user_verified=user_verified,
        account_charges_enabled=account_charges_enabled,
        account_payouts_enabled=account_payouts_enabled,
        setup_score=setup_score,
        benefits_configured=benefits_count > 0,
        webhooks_configured=webhooks_count > 0,
        products_configured=products_count > 0,
        api_keys_created=org_tokens_count > 0,
    )


@router.get("/", name="organizations:list")
async def list(
    request: Request,
    sorting: sorting.ListSorting,
    session: AsyncSession = Depends(get_db_read_session),
    page: int = Query(1, description="Page number, defaults to 1.", gt=0),
    limit: int = Query(100, description="Size of a page, defaults to 100.", gt=0),
    query: str | None = Query(None),
    organization_status: Annotated[
        OrganizationStatus | None,
        BeforeValidator(empty_str_to_none_before_enum),
        Query(),
    ] = None,
    has_appealed: Annotated[
        bool | None, BeforeValidator(empty_str_to_none_before_bool), Query()
    ] = None,
    review_cycle: Annotated[
        Literal["first", "subsequent"] | None,
        BeforeValidator(empty_str_to_none),
        Query(),
    ] = None,
) -> None:
    # Create custom pagination with default limit of 100
    pagination = PaginationParams(page, min(100, limit))
    repository = OrganizationRepository.from_session(session)
    statement = (
        repository.get_base_statement()
        .join(Account, Organization.account_id == Account.id, isouter=True)
        .options(
            contains_eager(Organization.account),
        )
    )
    if query:
        try:
            statement = statement.where(Organization.id == uuid.UUID(query))
        except ValueError:
            statement = statement.where(
                or_(
                    Organization.name.ilike(f"%{query}%"),
                    Organization.slug.ilike(f"%{query}%"),
                    Organization.website.ilike(f"%{query}%"),
                )
            )
    if organization_status:
        statement = statement.where(Organization.status == organization_status)

    # Add appeal filter
    if has_appealed is not None:
        if has_appealed:
            statement = statement.join(
                OrganizationReview,
                Organization.id == OrganizationReview.organization_id,
            ).where(OrganizationReview.appeal_submitted_at.is_not(None))
        else:
            statement = statement.outerjoin(
                OrganizationReview,
                Organization.id == OrganizationReview.organization_id,
            ).where(
                or_(
                    OrganizationReview.id.is_(None),
                    OrganizationReview.appeal_submitted_at.is_(None),
                )
            )

    # Add review cycle filter
    if review_cycle:
        match review_cycle:
            case "first":
                status = OrganizationStatus.INITIAL_REVIEW
            case "subsequent":
                status = OrganizationStatus.ONGOING_REVIEW
        statement = statement.where(Organization.status == status)

    statement = repository.apply_sorting(statement, sorting)
    items, count = await repository.paginate(
        statement, limit=pagination.limit, page=pagination.page
    )

    with layout(
        request,
        [
            ("Organizations", str(request.url_for("organizations:list"))),
        ],
        "organizations:list",
    ):
        with tag.div(classes="flex flex-col gap-4"):
            with tag.h1(classes="text-4xl"):
                text("Organizations")
            with tag.form(method="GET", classes="w-full flex flex-col gap-4"):
                with tag.div(classes="flex flex-row gap-2"):
                    with input.search("query", query):
                        pass
                    with input.select(
                        [
                            ("All Organization Statuses", ""),
                            *[
                                (status.get_display_name(), status.value)
                                for status in OrganizationStatus
                            ],
                        ],
                        organization_status.value if organization_status else "",
                        name="organization_status",
                    ):
                        pass
                    with input.select(
                        [
                            ("All Appeal Statuses", ""),
                            ("Has Appealed", "true"),
                            ("Has Not Appealed", "false"),
                        ],
                        "true"
                        if has_appealed is True
                        else ("false" if has_appealed is False else ""),
                        name="has_appealed",
                    ):
                        pass
                    with input.select(
                        [
                            ("All Review Cycles", ""),
                            ("First Review", "first"),
                            ("Subsequent Review", "subsequent"),
                        ],
                        review_cycle or "",
                        name="review_cycle",
                    ):
                        pass
                with tag.div(classes="flex flex-row gap-2"):
                    with input.select(
                        [
                            ("25 per page", "25"),
                            ("50 per page", "50"),
                            ("100 per page", "100"),
                        ],
                        str(limit),
                        name="limit",
                    ):
                        pass
                    with button(type="submit"):
                        text("Filter")
            with datatable.Datatable[Organization, OrganizationSortProperty](
                datatable.DatatableAttrColumn(
                    "id", "ID", href_route_name="organizations:get", clipboard=True
                ),
                datatable.DatatableDateTimeColumn(
                    "created_at",
                    "Created At",
                    sorting=OrganizationSortProperty.created_at,
                ),
                OrganizationStatusColumn("status", "Status"),
                datatable.DatatableAttrColumn(
                    "name",
                    "Name",
                    sorting=OrganizationSortProperty.organization_name,
                ),
                datatable.DatatableAttrColumn(
                    "slug",
                    "Slug",
                    sorting=OrganizationSortProperty.slug,
                    clipboard=True,
                ),
                NextReviewThresholdColumn(
                    "next_review_threshold",
                    "Next Review Threshold",
                    sorting=OrganizationSortProperty.next_review_threshold,
                ),
                DaysInStatusColumn(
                    "status_updated_at",
                    "Days in Status",
                    sorting=OrganizationSortProperty.days_in_status,
                ),
            ).render(request, items, sorting=sorting):
                pass
            with datatable.pagination(request, pagination, count):
                pass


@router.api_route("/{id}/update", name="organizations:update", methods=["GET", "POST"])
async def update(
    request: Request,
    id: UUID4,
    session: AsyncSession = Depends(get_db_session),
) -> Any:
    org_repo = OrganizationRepository.from_session(session)
    organization = await org_repo.get_by_id(id)
    if not organization:
        raise HTTPException(status_code=404)

    validation_error: ValidationError | None = None

    if request.method == "POST":
        data = await request.form()
        try:
            form = UpdateOrganizationForm.model_validate_form(data)
            if form.slug != organization.slug:
                existing_slug = await org_repo.get_by_slug(form.slug)
                if existing_slug is not None:
                    raise ValidationError.from_exception_data(
                        title="SlugAlreadyExists",
                        line_errors=[
                            {
                                "loc": ("slug",),
                                "type": PydanticCustomError(
                                    "SlugAlreadyExists",
                                    "An organization with this slug already exists.",
                                ),
                                "input": form.slug,
                            }
                        ],
                    )

            form_dict = form.model_dump(exclude_none=True)
            feature_flags_from_form = form_dict.pop("feature_flags", None)

            # Dynamically handle all feature flags from OrganizationFeatureSettings
            # If None, all checkboxes were unchecked - set all to False
            if feature_flags_from_form is None:
                # Get all field names from OrganizationFeatureSettings and set to False
                feature_flags = {
                    field_name: False
                    for field_name in OrganizationFeatureSettings.model_fields.keys()
                }
            else:
                # Use the values from the form, ensuring all fields have values
                feature_flags = {
                    field_name: feature_flags_from_form.get(field_name, False)
                    for field_name in OrganizationFeatureSettings.model_fields.keys()
                }

            # Merge with existing feature_settings
            updated_feature_settings = {
                **organization.feature_settings,
                **feature_flags,
            }

            # Update organization with both basic fields and feature_settings
            organization = await org_repo.update(
                organization,
                update_dict={
                    **form_dict,
                    "feature_settings": updated_feature_settings,
                },
            )
            return HXRedirectResponse(
                request, str(request.url_for("organizations:get", id=id)), 303
            )

        except ValidationError as e:
            validation_error = e

    # Prepare data for form rendering with current feature settings
    # Dynamically populate all feature flags from OrganizationFeatureSettings
    form_data = {
        "name": organization.name,
        "slug": organization.slug,
        "customer_invoice_prefix": organization.customer_invoice_prefix,
        "feature_flags": {
            field_name: organization.feature_settings.get(field_name, False)
            for field_name in OrganizationFeatureSettings.model_fields.keys()
        },
    }

    with modal("Update Organization", open=True):
        with UpdateOrganizationForm.render(
            form_data,
            hx_post=str(request.url_for("organizations:update", id=id)),
            hx_target="#modal",
            classes="flex flex-col gap-4",
            validation_error=validation_error,
        ):
            with tag.div(classes="modal-action"):
                with tag.form(method="dialog"):
                    with button(ghost=True):
                        text("Cancel")
                with button(
                    type="submit",
                    variant="primary",
                ):
                    text("Update")


@router.api_route(
    "/{id}/update_details", name="organizations:update_details", methods=["GET", "POST"]
)
async def update_details(
    request: Request,
    id: UUID4,
    session: AsyncSession = Depends(get_db_session),
) -> Any:
    org_repo = OrganizationRepository.from_session(session)
    organization = await org_repo.get_by_id(id)
    if not organization:
        raise HTTPException(status_code=404)

    validation_error: ValidationError | None = None

    if request.method == "POST":
        data = await request.form()
        try:
            form = UpdateOrganizationDetailsForm.model_validate_form(data)
            organization = await org_repo.update(
                organization, update_dict=form.model_dump(exclude_none=True)
            )
            return HXRedirectResponse(
                request, str(request.url_for("organizations:get", id=id)), 303
            )

        except ValidationError as e:
            validation_error = e

    with modal("Edit Business Information", open=True):
        with tag.p(classes="text-sm text-base-content-secondary"):
            text("Update the key information about your business and products")

        with UpdateOrganizationDetailsForm.render(
            data=organization,
            validation_error=validation_error,
            hx_post=str(request.url_for("organizations:update_details", id=id)),
            hx_target="#modal",
            classes="space-y-6",
        ):
            # Action buttons
            with tag.div(classes="modal-action pt-6 border-t border-base-200"):
                with tag.form(method="dialog"):
                    with button(ghost=True):
                        text("Cancel")
                with button(
                    type="submit",
                    variant="primary",
                ):
                    text("Update Details")


@router.api_route(
    "/{id}/update_internal_notes",
    name="organizations:update_internal_notes",
    methods=["GET", "POST"],
)
async def update_internal_notes(
    request: Request,
    id: UUID4,
    session: AsyncSession = Depends(get_db_session),
) -> Any:
    org_repo = OrganizationRepository.from_session(session)
    organization = await org_repo.get_by_id(id)
    if not organization:
        raise HTTPException(status_code=404)

    validation_error: ValidationError | None = None

    if request.method == "POST":
        data = await request.form()
        try:
            form = UpdateOrganizationInternalNotesForm.model_validate_form(data)
            organization = await org_repo.update(
                organization, update_dict=form.model_dump(exclude_none=True)
            )
            return HXRedirectResponse(
                request, str(request.url_for("organizations:get", id=id)), 303
            )

        except ValidationError as e:
            validation_error = e

    with modal("Edit Internal Notes", open=True):
        with tag.p(classes="text-sm text-base-content-secondary"):
            text("Add or update internal notes about this organization (admin only)")

        with UpdateOrganizationInternalNotesForm.render(
            data=organization,
            validation_error=validation_error,
            hx_post=str(request.url_for("organizations:update_internal_notes", id=id)),
            hx_target="#modal",
            classes="space-y-4",
        ):
            # Action buttons
            with tag.div(classes="modal-action pt-6 border-t border-base-200"):
                with tag.form(method="dialog"):
                    with button(ghost=True):
                        text("Cancel")
                with button(
                    type="submit",
                    variant="primary",
                ):
                    text("Save Notes")


@router.api_route("/{id}/delete", name="organizations:delete", methods=["GET", "POST"])
async def delete(
    request: Request,
    id: UUID4,
    session: AsyncSession = Depends(get_db_session),
) -> Any:
    org_repo = OrganizationRepository.from_session(session)
    organization = await org_repo.get_by_id(id)
    if not organization:
        raise HTTPException(status_code=404)

    if request.method == "POST":
        await organization_service.delete(session, organization)
        await add_toast(
            request,
            f"Organization with ID {organization.id} has been deleted",
            "success",
        )

        return

    with modal(f"Delete Organization {organization.id}", open=True):
        with tag.div(classes="flex flex-col gap-4"):
            with tag.p():
                text("Are you sure you want to delete this Organization? ")

            with tag.p():
                text("Deleting this Organization DOES NOT:")
            with tag.ul(classes="list-disc list-inside"):
                with tag.li():
                    text("Delete or anonymize Users related Organization")
                with tag.li():
                    text("Delete or anonymize Account of the Organization")
                with tag.li():
                    text(
                        "Delete or anonymize Customers, Products, Discounts, Benefits, Checkouts of the Organization"
                    )
                with tag.li():
                    text("Revoke Benefits granted")
                with tag.li():
                    text("Remove API tokens (organization or personal)")

            with tag.p():
                text("The User can be deleted separately")

            with tag.div(classes="modal-action"):
                with tag.form(method="dialog"):
                    with button(ghost=True):
                        text("Cancel")
                with tag.form(method="dialog"):
                    with button(
                        type="button",
                        variant="primary",
                        hx_post=str(request.url),
                        hx_target="#modal",
                    ):
                        text("Delete")


@router.get(
    "/{id}/confirm_remove_member/{user_id}", name="organizations:confirm_remove_member"
)
async def confirm_remove_member(
    request: Request,
    id: UUID4,
    user_id: UUID4,
    session: AsyncSession = Depends(get_db_session),
) -> Any:
    """Show confirmation modal for removing a member."""

    # Get user info for the modal
    user_repo = UserRepository.from_session(session)
    user = await user_repo.get_by_id(user_id)

    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    with modal(f"Remove {user.email}", open=True):
        with tag.div(classes="flex items-start gap-4 mb-6"):
            # Message content
            with tag.div(classes="flex-1"):
                with tag.p(classes="text-sm text-gray-600 mb-4"):
                    text("Are you sure you want to remove ")
                    with tag.strong():
                        text(user.email)
                    text(" from this organization?")

                with tag.p(classes="text-xs text-gray-500"):
                    text(
                        "This action cannot be undone. The user will lose access to all organization resources."
                    )

        # Action buttons
        with tag.div(classes="modal-action"):
            with tag.form(method="dialog"):
                with button(ghost=True):
                    text("Cancel")

            with tag.form(method="dialog"):
                with button(
                    variant="error",
                    hx_delete=str(
                        request.url_for(
                            "organizations:remove_member",
                            id=id,
                            user_id=user_id,
                        )
                    ),
                    hx_target="#modal",
                ):
                    text("Remove User")


@router.api_route(
    "/{id}/remove_member/{user_id}",
    name="organizations:remove_member",
    methods=["DELETE"],
)
async def remove_member(
    request: Request,
    id: UUID4,
    user_id: UUID4,
    session: AsyncSession = Depends(get_db_session),
) -> Any:
    """Remove member endpoint with DELETE method."""

    try:
        # Get user info for better error messages
        user_repo = UserRepository.from_session(session)
        user = await user_repo.get_by_id(user_id)
        user_email = user.email if user else str(user_id)

        # Attempt to remove the member safely
        await user_organization_service.remove_member_safe(session, user_id, id)

        # Add success toast and redirect
        await add_toast(
            request,
            f"{user_email} has been removed from the organization",
            "success",
        )

        return HXRedirectResponse(
            request, request.url_for("organizations:get", id=id), 303
        )

    except UserOrgOrganizationNotFound:
        raise HTTPException(status_code=404, detail="Organization not found")

    except UserNotMemberOfOrganization:
        raise HTTPException(
            status_code=400, detail="User is not a member of this organization"
        )

    except CannotRemoveOrganizationAdmin:
        raise HTTPException(
            status_code=403,
            detail=f"Cannot remove {user_email} - they are the organization admin",
        )

    except Exception:
        raise HTTPException(
            status_code=500, detail="An error occurred while removing the user"
        )


@router.get(
    "/{id}/confirm_change_admin/{user_id}", name="organizations:confirm_change_admin"
)
async def confirm_change_admin(
    request: Request,
    id: UUID4,
    user_id: UUID4,
    session: AsyncSession = Depends(get_db_session),
) -> Any:
    """Show confirmation modal for changing account admin."""

    # Get organization and account
    org_repo = OrganizationRepository.from_session(session)
    organization = await org_repo.get_by_id(
        id, options=(joinedload(Organization.account),)
    )

    if not organization or not organization.account:
        raise HTTPException(status_code=404, detail="Organization or account not found")

    # Get current admin
    current_admin = await org_repo.get_admin_user(session, organization)

    # Get new admin user info
    user_repo = UserRepository.from_session(session)
    new_admin = await user_repo.get_by_id(user_id)

    if not new_admin:
        raise HTTPException(status_code=404, detail="User not found")

    # Check all the conditions that might prevent changing admin
    has_stripe_account = bool(organization.account.stripe_id)
    user_not_verified = (
        new_admin.identity_verification_status != IdentityVerificationStatus.verified
    )
    not_enough_users = (
        len(await user_repo.get_all_by_organization(organization.id)) <= 1
    )

    # Determine if admin change is blocked and why
    is_blocked = has_stripe_account or user_not_verified or not_enough_users

    with modal("Change Account Admin", open=True):
        with tag.div(classes="flex flex-col gap-4"):
            # Show appropriate alert based on blocking conditions
            if is_blocked:
                with tag.div(classes="alert alert-error"):
