from __future__ import annotations

from fastapi import APIRouter, Form, Request
from fastapi.responses import RedirectResponse
from app.core.http_responses import not_found_response

from app.core.db.common import CommonSessionLocal
from app.core.security.csrf import get_or_create_csrf_token, validate_csrf
from app.core.security.session_auth import get_current_user
from app.core.templating import templates
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
from app.modules.core.rbac.permission_guard import require_permission
from app.modules.marketplace.services import (
    LEAD_PRIORITIES,
    LEAD_SOURCES,
    LEAD_STATUSES,
    SERVICE_CATEGORIES,
    assign_marketplace_lead,
    convert_lead_to_client,
    create_marketplace_lead,
    get_marketplace_lead,
    get_marketplace_overview_counts,
    is_marketplace_domain_request,
    list_marketplace_leads,
    list_public_marketplace_audit_firms,
    list_public_marketplace_consultants,
    list_reference_audit_firms,
    list_reference_branches,
    list_reference_partners,
    update_lead_status,
)

router = APIRouter(prefix="/marketplace", tags=["marketplace-ui"])
public_router = APIRouter(tags=["marketplace-public-ui"])


def _csrf_rejected(request: Request):
    from app.core.http_responses import forbidden_response
    return forbidden_response(request, "CSRF validation failed")





def _public_marketplace_ctx(request: Request, db, **ctx):
    base = {
        "request": request,
        "current_user": None,
        "current_user_roles": [],
        "current_user_permissions": [],
        "csrf_token": get_or_create_csrf_token(request),
        "service_categories": SERVICE_CATEGORIES,
        "lead_priorities": LEAD_PRIORITIES,
        "lead_sources": LEAD_SOURCES,
        "marketplace_counts": get_marketplace_overview_counts(db),
        "public_audit_firms": list_public_marketplace_audit_firms(db, limit=8),
        "public_consultants": list_public_marketplace_consultants(db, limit=8),
    }
    base.update(ctx)
    return base


def _render_public_marketplace(request: Request, template: str, db, **ctx):
    return templates.TemplateResponse(template, _public_marketplace_ctx(request, db, **ctx))


@public_router.get("/")
def marketplace_domain_home(request: Request):
    """Marketplace domain landing page.

    Only marketplace-mapped domains use this as the public home page. Normal localhost,
    tenant domains and consultant domains continue to the normal login flow.
    """
    if not is_marketplace_domain_request(request):
        return RedirectResponse(url="/login", status_code=303)
    db = CommonSessionLocal()
    try:
        return _render_public_marketplace(
            request,
            "modules/marketplace/templates/marketplace/public_marketplace_home.html",
            db,
            title="FilingABC Marketplace",
        )
    finally:
        db.close()


@public_router.get("/audit-firms")
def marketplace_public_audit_firms(request: Request):
    if not is_marketplace_domain_request(request):
        return RedirectResponse(url="/login", status_code=303)
    db = CommonSessionLocal()
    try:
        return _render_public_marketplace(
            request,
            "modules/marketplace/templates/marketplace/public_audit_firms.html",
            db,
            title="Audit Firms",
            public_audit_firms=list_public_marketplace_audit_firms(db, limit=50),
        )
    finally:
        db.close()


@public_router.get("/consultants")
def marketplace_public_consultants(request: Request):
    if not is_marketplace_domain_request(request):
        return RedirectResponse(url="/login", status_code=303)
    db = CommonSessionLocal()
    try:
        return _render_public_marketplace(
            request,
            "modules/marketplace/templates/marketplace/public_consultants.html",
            db,
            title="Consultants",
            public_consultants=list_public_marketplace_consultants(db, limit=50),
        )
    finally:
        db.close()


@public_router.get("/request-service")
def marketplace_public_request_service(request: Request):
    if not is_marketplace_domain_request(request):
        return RedirectResponse(url="/marketplace/public-lead", status_code=303)
    db = CommonSessionLocal()
    try:
        return _render_public_marketplace(
            request,
            "modules/marketplace/templates/marketplace/public_marketplace_lead_form.html",
            db,
            title="Request a Service",
        )
    finally:
        db.close()


@public_router.post("/request-service")
def marketplace_public_request_service_submit(request: Request, csrf_token: str = Form(...), lead_name: str = Form(...), business_name: str = Form(""), email: str = Form(""), mobile: str = Form(""), city: str = Form(""), state: str = Form(""), service_category: str = Form(""), service_requested: str = Form(...), message: str = Form("")):
    if not is_marketplace_domain_request(request):
        return RedirectResponse(url="/marketplace/public-lead", status_code=303)
    db = CommonSessionLocal()
    try:
        try:
            validate_csrf(request, csrf_token)
        except PermissionError:
            return _csrf_rejected(request)
        lead = create_marketplace_lead(
            db,
            lead_name=lead_name,
            business_name=business_name,
            email=email,
            mobile=mobile,
            city=city,
            state=state,
            service_category=service_category,
            service_requested=service_requested,
            message=message,
            source="public_website",
            priority="NORMAL",
        )
        return _render_public_marketplace(
            request,
            "modules/marketplace/templates/marketplace/public_marketplace_thank_you.html",
            db,
            title="Thank You",
            lead=lead,
        )
    finally:
        db.close()


def _redirect_denied():
    from app.core.http_responses import ui_access_denied
    return ui_access_denied()


def _has_perm(db, user, code: str) -> bool:
    try:
        require_permission(db, user, code)
        return True
    except Exception:
        return False


def _require_user(request: Request, db, permission_code: str):
    user = get_current_user(request, db=db)
    if not user:
        return None, RedirectResponse(url="/login", status_code=303)
    try:
        require_permission(db, user, permission_code)
    except Exception:
        # Assigned lead users are allowed if they have assigned-lead permission.
        if permission_code == "marketplace_leads.view" and _has_perm(db, user, "marketplace_leads.view_assigned"):
            return user, None
        return user, _redirect_denied()
    return user, None


def _base_ctx(request: Request, db, user=None, **ctx):
    base = {
        "request": request,
        "current_user": user,
        "current_user_roles": get_user_roles(db, user.id) if user else [],
        "current_user_permissions": get_user_permissions(db, user.id) if user else [],
        "csrf_token": get_or_create_csrf_token(request),
        "lead_statuses": LEAD_STATUSES,
        "lead_priorities": LEAD_PRIORITIES,
        "lead_sources": LEAD_SOURCES,
        "service_categories": SERVICE_CATEGORIES,
    }
    base.update(ctx)
    return base


def _render(request: Request, template: str, db, user=None, **ctx):
    return templates.TemplateResponse(template, _base_ctx(request, db, user, **ctx))


@router.get("")
def dashboard(request: Request):
    db = CommonSessionLocal()
    try:
        user, response = _require_user(request, db, "marketplace_leads.view")
        if response:
            return response
        roles = get_user_roles(db, user.id)
        leads = list_marketplace_leads(db, user=user, role_names=roles)
        return _render(request, "modules/marketplace/templates/marketplace/dashboard.html", db, user, title="Marketplace Leads", leads=leads[:8], total=len(leads), can_create=_has_perm(db, user, "marketplace_leads.create"), can_assign=_has_perm(db, user, "marketplace_leads.assign"))
    finally:
        db.close()


@router.get("/leads")
def leads_list(request: Request, q: str = "", status: str = ""):
    db = CommonSessionLocal()
    try:
        user, response = _require_user(request, db, "marketplace_leads.view")
        if response:
            return response
        roles = get_user_roles(db, user.id)
        return _render(request, "modules/marketplace/templates/marketplace/leads_list.html", db, user, title="Marketplace Leads", rows=list_marketplace_leads(db, q=q, status=status, user=user, role_names=roles), q=q, selected_status=status, can_create=_has_perm(db, user, "marketplace_leads.create"), can_assign=_has_perm(db, user, "marketplace_leads.assign"))
    finally:
        db.close()


@router.get("/leads/new")
def lead_new(request: Request):
    db = CommonSessionLocal()
    try:
        user, response = _require_user(request, db, "marketplace_leads.create")
        if response:
            return response
        return _render(request, "modules/marketplace/templates/marketplace/lead_form.html", db, user, title="New Marketplace Lead", public_mode=False)
    finally:
        db.close()


@router.post("/leads/new")
def lead_create(request: Request, csrf_token: str = Form(...), lead_name: str = Form(...), business_name: str = Form(""), email: str = Form(""), mobile: str = Form(""), city: str = Form(""), state: str = Form(""), service_category: str = Form(""), service_requested: str = Form(...), message: str = Form(""), source: str = Form("manual"), priority: str = Form("NORMAL"), estimated_value: str = Form("0")):
    db = CommonSessionLocal()
    try:
        user, response = _require_user(request, db, "marketplace_leads.create")
        if response:
            return response
        try:
            validate_csrf(request, csrf_token)
        except PermissionError:
            return _csrf_rejected(request)
        lead = create_marketplace_lead(db, lead_name=lead_name, business_name=business_name, email=email, mobile=mobile, city=city, state=state, service_category=service_category, service_requested=service_requested, message=message, source=source, priority=priority, estimated_value=estimated_value, created_by_user_id=user.id)
        return RedirectResponse(url=f"/marketplace/leads/{lead.id}", status_code=303)
    finally:
        db.close()


@router.get("/public-lead")
def public_lead_form(request: Request):
    db = CommonSessionLocal()
    try:
        return _render(request, "modules/marketplace/templates/marketplace/public_lead_form.html", db, None, title="Request a Service")
    finally:
        db.close()


@router.post("/public-lead")
def public_lead_submit(request: Request, csrf_token: str = Form(...), lead_name: str = Form(...), business_name: str = Form(""), email: str = Form(""), mobile: str = Form(""), city: str = Form(""), state: str = Form(""), service_category: str = Form(""), service_requested: str = Form(...), message: str = Form("")):
    db = CommonSessionLocal()
    try:
        try:
            validate_csrf(request, csrf_token)
        except PermissionError:
            return _csrf_rejected(request)
        lead = create_marketplace_lead(db, lead_name=lead_name, business_name=business_name, email=email, mobile=mobile, city=city, state=state, service_category=service_category, service_requested=service_requested, message=message, source="public_website", priority="NORMAL")
        return _render(request, "modules/marketplace/templates/marketplace/public_thank_you.html", db, None, title="Thank You", lead=lead)
    finally:
        db.close()


@router.get("/leads/{lead_id}")
def lead_detail(request: Request, lead_id: int):
    db = CommonSessionLocal()
    try:
        user, response = _require_user(request, db, "marketplace_leads.view")
        if response:
            return response
        lead = get_marketplace_lead(db, lead_id)
        if not lead:
            return not_found_response(request, "Marketplace lead not found")
        return _render(request, "modules/marketplace/templates/marketplace/lead_detail.html", db, user, title=f"Lead {lead.lead_no}", lead=lead, audit_firms=list_reference_audit_firms(db), branches=list_reference_branches(db, lead.assigned_tenant_id), partners=list_reference_partners(db, lead.assigned_tenant_id), can_assign=_has_perm(db, user, "marketplace_leads.assign"), can_update=_has_perm(db, user, "marketplace_leads.update"), can_convert=_has_perm(db, user, "marketplace_leads.convert"))
    finally:
        db.close()


@router.post("/leads/{lead_id}/assign")
def lead_assign(request: Request, lead_id: int, csrf_token: str = Form(...), tenant_id: int = Form(...), branch_id: int = Form(0), partner_user_id: int = Form(0), notes: str = Form("")):
    db = CommonSessionLocal()
    try:
        user, response = _require_user(request, db, "marketplace_leads.assign")
        if response:
            return response
        try:
            validate_csrf(request, csrf_token)
        except PermissionError:
            return _csrf_rejected(request)
        lead = get_marketplace_lead(db, lead_id)
        if lead:
            assign_marketplace_lead(db, lead=lead, tenant_id=tenant_id, branch_id=branch_id or None, partner_user_id=partner_user_id or None, notes=notes, assigned_by_user_id=user.id)
        return RedirectResponse(url=f"/marketplace/leads/{lead_id}", status_code=303)
    finally:
        db.close()


@router.post("/leads/{lead_id}/status")
def lead_status_update(request: Request, lead_id: int, csrf_token: str = Form(...), status: str = Form(...)):
    db = CommonSessionLocal()
    try:
        user, response = _require_user(request, db, "marketplace_leads.update")
        if response:
            return response
        try:
            validate_csrf(request, csrf_token)
        except PermissionError:
            return _csrf_rejected(request)
        lead = get_marketplace_lead(db, lead_id)
        if lead:
            update_lead_status(db, lead=lead, status=status, user_id=user.id)
        return RedirectResponse(url=f"/marketplace/leads/{lead_id}", status_code=303)
    finally:
        db.close()


@router.post("/leads/{lead_id}/convert-client")
def lead_convert_client(request: Request, lead_id: int, csrf_token: str = Form(...), tenant_id: int = Form(...), branch_id: int = Form(...), partner_user_id: int = Form(0), client_code: str = Form("")):
    db = CommonSessionLocal()
    try:
        user, response = _require_user(request, db, "marketplace_leads.convert")
        if response:
            return response
        try:
            validate_csrf(request, csrf_token)
        except PermissionError:
            return _csrf_rejected(request)
        lead = get_marketplace_lead(db, lead_id)
        if lead:
            client = convert_lead_to_client(db, lead=lead, tenant_id=tenant_id, branch_id=branch_id, partner_user_id=partner_user_id or None, client_code=client_code, user_id=user.id)
            return RedirectResponse(url=f"/clients/{client.id}", status_code=303)
        return RedirectResponse(url="/marketplace/leads", status_code=303)
    finally:
        db.close()
