"""Phase 6.1 supporting CRM APIs — lookups, tags, addresses, notes, attachments, custom fields, audit."""
from __future__ import annotations

from uuid import UUID

from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db, get_pagination, require_tenant
from app.core.security import get_current_user
from app.models.types import CrmEntityType
from app.schemas.foundation import (
    AddressCreate,
    AddressRead,
    AddressUpdate,
    AttachmentCreate,
    AttachmentRead,
    AuditRead,
    CustomFieldCreate,
    CustomFieldRead,
    CustomFieldValueRead,
    CustomFieldValueUpsert,
    LeadSourceRead,
    LeadStatusCreate,
    LeadStatusRead,
    LookupCreate,
    LookupRead,
    NoteCreate,
    NoteRead,
    NoteUpdate,
    TagAssignRequest,
    TagCreate,
    TagRead,
)
from app.services.audit_service import AuditService
from app.services.supporting_services import (
    AddressService,
    AttachmentService,
    CustomFieldService,
    LookupService,
    NoteService,
    TagService,
)
from shared.pagination import PaginationParams
from shared.security import CurrentUser

router = APIRouter()


# ── Lookups ──────────────────────────────────────────────────────────────────


@router.post(
    "/lookups/lead-sources",
    response_model=LeadSourceRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_lead_source(
    body: LookupCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).create_lead_source(tenant_id, body)


@router.get("/lookups/lead-sources", response_model=list[LeadSourceRead])
async def list_lead_sources(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).list_lead_sources(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/lookups/lead-statuses",
    response_model=LeadStatusRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_lead_status(
    body: LeadStatusCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).create_lead_status(tenant_id, body)


@router.get("/lookups/lead-statuses", response_model=list[LeadStatusRead])
async def list_lead_statuses(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).list_lead_statuses(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/lookups/contact-types",
    response_model=LookupRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_contact_type(
    body: LookupCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).create_contact_type(tenant_id, body)


@router.get("/lookups/contact-types", response_model=list[LookupRead])
async def list_contact_types(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).list_contact_types(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/lookups/organization-types",
    response_model=LookupRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_organization_type(
    body: LookupCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).create_organization_type(tenant_id, body)


@router.get("/lookups/organization-types", response_model=list[LookupRead])
async def list_organization_types(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).list_organization_types(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post(
    "/lookups/organization-industries",
    response_model=LookupRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_organization_industry(
    body: LookupCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).create_organization_industry(tenant_id, body)


@router.get("/lookups/organization-industries", response_model=list[LookupRead])
async def list_organization_industries(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await LookupService(db).list_organization_industries(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


# ── Tags ─────────────────────────────────────────────────────────────────────


@router.post("/tags", response_model=TagRead, status_code=status.HTTP_201_CREATED)
async def create_tag(
    body: TagCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await TagService(db).create(tenant_id, body)


@router.get("/tags", response_model=list[TagRead])
async def list_tags(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await TagService(db).list(
        tenant_id, offset=pagination.offset, limit=pagination.page_size
    )


@router.post("/tags/leads/{lead_id}")
async def assign_lead_tag(
    lead_id: UUID,
    body: TagAssignRequest,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    row = await TagService(db).assign_to_lead(tenant_id, lead_id, body.tag_id)
    return {"id": str(row.id), "lead_id": str(row.lead_id), "tag_id": str(row.tag_id)}


@router.post("/tags/contacts/{contact_id}")
async def assign_contact_tag(
    contact_id: UUID,
    body: TagAssignRequest,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    row = await TagService(db).assign_to_contact(tenant_id, contact_id, body.tag_id)
    return {
        "id": str(row.id),
        "contact_id": str(row.contact_id),
        "tag_id": str(row.tag_id),
    }


@router.post("/tags/organizations/{organization_id}")
async def assign_organization_tag(
    organization_id: UUID,
    body: TagAssignRequest,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    row = await TagService(db).assign_to_organization(
        tenant_id, organization_id, body.tag_id
    )
    return {
        "id": str(row.id),
        "organization_id": str(row.organization_id),
        "tag_id": str(row.tag_id),
    }


# ── Addresses ────────────────────────────────────────────────────────────────


@router.post(
    "/addresses", response_model=AddressRead, status_code=status.HTTP_201_CREATED
)
async def create_address(
    body: AddressCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await AddressService(db).create(tenant_id, body, actor=user)


@router.get("/addresses", response_model=list[AddressRead])
async def list_addresses(
    entity_type: CrmEntityType = Query(...),
    entity_id: UUID = Query(...),
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await AddressService(db).list_for_entity(tenant_id, entity_type, entity_id)


@router.patch("/addresses/{address_id}", response_model=AddressRead)
async def update_address(
    address_id: UUID,
    body: AddressUpdate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await AddressService(db).update(tenant_id, address_id, body, actor=user)


# ── Notes ────────────────────────────────────────────────────────────────────


@router.post("/notes", response_model=NoteRead, status_code=status.HTTP_201_CREATED)
async def create_note(
    body: NoteCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await NoteService(db).create(tenant_id, body, actor=user)


@router.get("/notes", response_model=list[NoteRead])
async def list_notes(
    entity_type: CrmEntityType = Query(...),
    entity_id: UUID = Query(...),
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await NoteService(db).list_for_entity(tenant_id, entity_type, entity_id)


@router.patch("/notes/{note_id}", response_model=NoteRead)
async def update_note(
    note_id: UUID,
    body: NoteUpdate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await NoteService(db).update(tenant_id, note_id, body, actor=user)


# ── Attachments ──────────────────────────────────────────────────────────────


@router.post(
    "/attachments",
    response_model=AttachmentRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_attachment(
    body: AttachmentCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await AttachmentService(db).create(tenant_id, body, actor=user)


@router.get("/attachments", response_model=list[AttachmentRead])
async def list_attachments(
    entity_type: CrmEntityType = Query(...),
    entity_id: UUID = Query(...),
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await AttachmentService(db).list_for_entity(
        tenant_id, entity_type, entity_id
    )


# ── Custom fields ────────────────────────────────────────────────────────────


@router.post(
    "/custom-fields",
    response_model=CustomFieldRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_custom_field(
    body: CustomFieldCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await CustomFieldService(db).create(tenant_id, body)


@router.get("/custom-fields", response_model=list[CustomFieldRead])
async def list_custom_fields(
    entity_type: CrmEntityType = Query(...),
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await CustomFieldService(db).list_definitions(tenant_id, entity_type)


@router.put(
    "/custom-fields/values",
    response_model=CustomFieldValueRead,
)
async def upsert_custom_field_value(
    body: CustomFieldValueUpsert,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await CustomFieldService(db).upsert_value(tenant_id, body)


# ── Audit ────────────────────────────────────────────────────────────────────


@router.get("/audit", response_model=list[AuditRead])
async def list_audit(
    entity_type: str = Query(...),
    entity_id: UUID = Query(...),
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await AuditService(db).list_for_entity(tenant_id, entity_type, entity_id)
