"""CRM foundation DTOs — Phase 6.0 pipelines + Phase 6.1 core entities."""
from __future__ import annotations

from datetime import date, datetime
from decimal import Decimal
from uuid import UUID

from pydantic import BaseModel, Field

from app.models.types import (
    AddressType,
    AttachmentKind,
    AuditAction,
    ContactKind,
    ContactMethod,
    ContactStatus,
    CrmEntityType,
    CustomFieldType,
    LeadPriority,
    LeadStatus,
    OpportunityStatus,
    OrganizationKind,
    OrganizationStatus,
    QuoteStatus,
    TagScope,
)
from app.schemas.common import ORMBase


# ── Lead ─────────────────────────────────────────────────────────────────────


class LeadCreate(BaseModel):
    first_name: str = Field(default="", max_length=100)
    last_name: str = Field(default="", max_length=100)
    full_name: str | None = Field(default=None, max_length=255)
    title: str | None = Field(default=None, max_length=255)
    company: str | None = Field(default=None, max_length=255)
    company_name: str | None = Field(default=None, max_length=255)
    job_title: str | None = Field(default=None, max_length=150)
    email: str | None = Field(default=None, max_length=255)
    mobile: str | None = Field(default=None, max_length=50)
    phone: str | None = Field(default=None, max_length=50)
    website: str | None = Field(default=None, max_length=255)
    lead_source_id: UUID | None = None
    lead_status_id: UUID | None = None
    status: LeadStatus = LeadStatus.NEW
    source: str | None = Field(default=None, max_length=100)
    assigned_user_id: str | None = Field(default=None, max_length=100)
    priority: LeadPriority = LeadPriority.MEDIUM
    estimated_value: Decimal = Decimal("0")
    expected_close_date: date | None = None
    description: str | None = None
    owner_user_id: str | None = Field(default=None, max_length=100)
    lead_number: str | None = Field(default=None, max_length=50)
    contact_id: UUID | None = None
    organization_id: UUID | None = None


class LeadUpdate(BaseModel):
    first_name: str | None = Field(default=None, max_length=100)
    last_name: str | None = Field(default=None, max_length=100)
    full_name: str | None = Field(default=None, max_length=255)
    title: str | None = Field(default=None, max_length=255)
    company: str | None = Field(default=None, max_length=255)
    job_title: str | None = Field(default=None, max_length=150)
    email: str | None = Field(default=None, max_length=255)
    mobile: str | None = Field(default=None, max_length=50)
    phone: str | None = Field(default=None, max_length=50)
    website: str | None = Field(default=None, max_length=255)
    lead_source_id: UUID | None = None
    lead_status_id: UUID | None = None
    status: LeadStatus | None = None
    source: str | None = Field(default=None, max_length=100)
    assigned_user_id: str | None = Field(default=None, max_length=100)
    priority: LeadPriority | None = None
    estimated_value: Decimal | None = None
    expected_close_date: date | None = None
    description: str | None = None
    owner_user_id: str | None = Field(default=None, max_length=100)
    contact_id: UUID | None = None
    organization_id: UUID | None = None


class LeadRead(ORMBase):
    id: UUID
    tenant_id: UUID
    lead_number: str
    first_name: str
    last_name: str
    full_name: str
    title: str | None
    company: str | None
    job_title: str | None
    email: str | None
    mobile: str | None
    phone: str | None
    website: str | None
    lead_source_id: UUID | None
    lead_status_id: UUID | None
    status: LeadStatus
    source: str | None
    assigned_user_id: str | None
    priority: LeadPriority
    estimated_value: Decimal
    expected_close_date: date | None
    description: str | None
    owner_user_id: str
    contact_id: UUID | None
    organization_id: UUID | None
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class LeadAssignRequest(BaseModel):
    assigned_user_id: str = Field(max_length=100)
    note: str | None = None


# ── Contact ──────────────────────────────────────────────────────────────────


class ContactCreate(BaseModel):
    first_name: str = Field(max_length=100)
    last_name: str = Field(max_length=100)
    kind: ContactKind = ContactKind.BUSINESS
    contact_type_id: UUID | None = None
    email: str | None = Field(default=None, max_length=255)
    phone: str | None = Field(default=None, max_length=50)
    emails: list[str] | None = None
    phones: list[str] | None = None
    default_contact_method: ContactMethod | None = None
    social_links: dict[str, str] | None = None
    birthday: date | None = None
    job_title: str | None = Field(default=None, max_length=150)
    job_position: str | None = Field(default=None, max_length=150)
    organization_id: UUID | None = None
    owner_user_id: str | None = Field(default=None, max_length=100)
    notes_summary: str | None = None
    status: ContactStatus = ContactStatus.ACTIVE


class ContactUpdate(BaseModel):
    first_name: str | None = Field(default=None, max_length=100)
    last_name: str | None = Field(default=None, max_length=100)
    kind: ContactKind | None = None
    contact_type_id: UUID | None = None
    email: str | None = Field(default=None, max_length=255)
    phone: str | None = Field(default=None, max_length=50)
    emails: list[str] | None = None
    phones: list[str] | None = None
    default_contact_method: ContactMethod | None = None
    social_links: dict[str, str] | None = None
    birthday: date | None = None
    job_title: str | None = Field(default=None, max_length=150)
    job_position: str | None = Field(default=None, max_length=150)
    organization_id: UUID | None = None
    owner_user_id: str | None = Field(default=None, max_length=100)
    notes_summary: str | None = None
    status: ContactStatus | None = None


class ContactRead(ORMBase):
    id: UUID
    tenant_id: UUID
    first_name: str
    last_name: str
    full_name: str
    kind: ContactKind
    contact_type_id: UUID | None
    email: str | None
    phone: str | None
    emails: list | None
    phones: list | None
    default_contact_method: ContactMethod | None
    social_links: dict | None
    birthday: date | None
    job_title: str | None
    job_position: str | None
    status: ContactStatus
    organization_id: UUID | None
    owner_user_id: str | None
    notes_summary: str | None
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


# ── Organization ─────────────────────────────────────────────────────────────


class OrganizationCreate(BaseModel):
    name: str = Field(max_length=255)
    kind: OrganizationKind = OrganizationKind.COMPANY
    legal_name: str | None = Field(default=None, max_length=255)
    trade_name: str | None = Field(default=None, max_length=255)
    national_identifier: str | None = Field(default=None, max_length=50)
    tax_number: str | None = Field(default=None, max_length=50)
    organization_type_id: UUID | None = None
    organization_industry_id: UUID | None = None
    industry: str | None = Field(default=None, max_length=150)
    website: str | None = Field(default=None, max_length=255)
    email: str | None = Field(default=None, max_length=255)
    phone: str | None = Field(default=None, max_length=50)
    parent_organization_id: UUID | None = None
    owner_user_id: str | None = Field(default=None, max_length=100)
    description: str | None = None
    status: OrganizationStatus = OrganizationStatus.ACTIVE


class OrganizationUpdate(BaseModel):
    name: str | None = Field(default=None, max_length=255)
    kind: OrganizationKind | None = None
    legal_name: str | None = Field(default=None, max_length=255)
    trade_name: str | None = Field(default=None, max_length=255)
    national_identifier: str | None = Field(default=None, max_length=50)
    tax_number: str | None = Field(default=None, max_length=50)
    organization_type_id: UUID | None = None
    organization_industry_id: UUID | None = None
    industry: str | None = Field(default=None, max_length=150)
    website: str | None = Field(default=None, max_length=255)
    email: str | None = Field(default=None, max_length=255)
    phone: str | None = Field(default=None, max_length=50)
    parent_organization_id: UUID | None = None
    owner_user_id: str | None = Field(default=None, max_length=100)
    description: str | None = None
    status: OrganizationStatus | None = None


class OrganizationRead(ORMBase):
    id: UUID
    tenant_id: UUID
    name: str
    kind: OrganizationKind
    legal_name: str | None
    trade_name: str | None
    national_identifier: str | None
    tax_number: str | None
    organization_type_id: UUID | None
    organization_industry_id: UUID | None
    industry: str | None
    website: str | None
    email: str | None
    phone: str | None
    parent_organization_id: UUID | None
    status: OrganizationStatus
    owner_user_id: str | None
    description: str | None
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


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


class LookupCreate(BaseModel):
    code: str = Field(max_length=50)
    name: str = Field(max_length=150)
    description: str | None = None
    is_active: bool = True


class LeadStatusCreate(BaseModel):
    code: str = Field(max_length=50)
    name: str = Field(max_length=150)
    position: int = 0
    is_terminal: bool = False
    is_converted: bool = False
    is_active: bool = True
    color: str | None = Field(default=None, max_length=20)


class LookupRead(ORMBase):
    id: UUID
    tenant_id: UUID
    code: str
    name: str
    is_active: bool
    created_at: datetime


class LeadSourceRead(LookupRead):
    description: str | None


class LeadStatusRead(ORMBase):
    id: UUID
    tenant_id: UUID
    code: str
    name: str
    position: int
    is_terminal: bool
    is_converted: bool
    is_active: bool
    color: str | None
    created_at: datetime


# ── Tags / Addresses / Notes / Attachments / Custom Fields / Audit ───────────


class TagCreate(BaseModel):
    name: str = Field(max_length=100)
    color: str | None = Field(default=None, max_length=20)
    group_name: str | None = Field(default=None, max_length=100)
    scope: TagScope = TagScope.ANY
    is_active: bool = True


class TagRead(ORMBase):
    id: UUID
    tenant_id: UUID
    name: str
    color: str | None
    group_name: str | None
    scope: TagScope
    is_active: bool
    created_at: datetime


class TagAssignRequest(BaseModel):
    tag_id: UUID


class AddressCreate(BaseModel):
    entity_type: CrmEntityType
    entity_id: UUID
    address_type: AddressType
    label: str | None = Field(default=None, max_length=100)
    line1: str = Field(max_length=255)
    line2: str | None = Field(default=None, max_length=255)
    city: str | None = Field(default=None, max_length=100)
    state: str | None = Field(default=None, max_length=100)
    postal_code: str | None = Field(default=None, max_length=30)
    country: str | None = Field(default=None, max_length=100)
    latitude: Decimal | None = None
    longitude: Decimal | None = None
    is_default: bool = False


class AddressUpdate(BaseModel):
    address_type: AddressType | None = None
    label: str | None = Field(default=None, max_length=100)
    line1: str | None = Field(default=None, max_length=255)
    line2: str | None = Field(default=None, max_length=255)
    city: str | None = Field(default=None, max_length=100)
    state: str | None = Field(default=None, max_length=100)
    postal_code: str | None = Field(default=None, max_length=30)
    country: str | None = Field(default=None, max_length=100)
    latitude: Decimal | None = None
    longitude: Decimal | None = None
    is_default: bool | None = None


class AddressRead(ORMBase):
    id: UUID
    tenant_id: UUID
    entity_type: CrmEntityType
    entity_id: UUID
    address_type: AddressType
    label: str | None
    line1: str
    line2: str | None
    city: str | None
    state: str | None
    postal_code: str | None
    country: str | None
    latitude: Decimal | None
    longitude: Decimal | None
    is_default: bool
    is_deleted: bool
    created_at: datetime
    updated_at: datetime


class NoteCreate(BaseModel):
    entity_type: CrmEntityType
    entity_id: UUID
    body: str
    body_format: str = "richtext"
    is_pinned: bool = False


class NoteUpdate(BaseModel):
    body: str | None = None
    is_pinned: bool | None = None


class NoteRead(ORMBase):
    id: UUID
    tenant_id: UUID
    entity_type: CrmEntityType
    entity_id: UUID
    body: str
    body_format: str
    version: int
    is_pinned: bool
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class AttachmentCreate(BaseModel):
    entity_type: CrmEntityType
    entity_id: UUID
    file_storage_id: str = Field(max_length=100)
    file_name: str = Field(max_length=255)
    content_type: str | None = Field(default=None, max_length=150)
    size_bytes: int | None = None
    kind: AttachmentKind = AttachmentKind.DOCUMENT
    description: str | None = None


class AttachmentRead(ORMBase):
    id: UUID
    tenant_id: UUID
    entity_type: CrmEntityType
    entity_id: UUID
    file_storage_id: str
    file_name: str
    content_type: str | None
    size_bytes: int | None
    kind: AttachmentKind
    description: str | None
    is_deleted: bool
    created_by: str | None
    created_at: datetime


class CustomFieldCreate(BaseModel):
    entity_type: CrmEntityType
    field_key: str = Field(max_length=100)
    label: str = Field(max_length=150)
    field_type: CustomFieldType
    is_required: bool = False
    options: list[str] | None = None
    validation_rules: dict | None = None
    position: int = 0
    is_active: bool = True


class CustomFieldRead(ORMBase):
    id: UUID
    tenant_id: UUID
    entity_type: CrmEntityType
    field_key: str
    label: str
    field_type: CustomFieldType
    is_required: bool
    options: list | None
    validation_rules: dict | None
    position: int
    is_active: bool
    created_at: datetime


class CustomFieldValueUpsert(BaseModel):
    custom_field_id: UUID
    entity_type: CrmEntityType
    entity_id: UUID
    value_text: str | None = None
    value_number: Decimal | None = None
    value_boolean: bool | None = None
    value_date: date | None = None
    value_json: list | dict | None = None


class CustomFieldValueRead(ORMBase):
    id: UUID
    tenant_id: UUID
    custom_field_id: UUID
    entity_type: CrmEntityType
    entity_id: UUID
    value_text: str | None
    value_number: Decimal | None
    value_boolean: bool | None
    value_date: date | None
    value_json: list | dict | None
    created_at: datetime


class AuditRead(ORMBase):
    id: UUID
    tenant_id: UUID
    entity_type: str
    entity_id: UUID
    action: AuditAction
    actor_user_id: str | None
    changes: dict | None
    message: str | None
    created_at: datetime


class LeadAssignmentRead(ORMBase):
    id: UUID
    tenant_id: UUID
    lead_id: UUID
    assigned_user_id: str
    assigned_by: str | None
    assigned_at: datetime
    note: str | None
    is_current: bool
    created_at: datetime


# ── Pipeline / Opportunity (Phase 6.2) / Activity (Phase 6.3) / Quote ────────

from app.schemas.collaboration import (  # noqa: E402
    SalesActivityCreate,
    SalesActivityRead,
    SalesActivityUpdate,
)
from app.schemas.sales_engine import (  # noqa: E402
    OpportunityCreate,
    OpportunityLoseRequest,
    OpportunityRead,
    OpportunityStageChangeRequest,
    OpportunityUpdate,
    OpportunityWinRequest,
    PipelineCreate,
    PipelineRead,
    PipelineStageCreate,
    PipelineStageRead,
    PipelineStageUpdate,
    PipelineUpdate,
    StageHistoryRead,
)


class QuoteCreate(BaseModel):
    title: str = Field(max_length=255)
    quote_number: str = Field(max_length=50)
    amount: Decimal = Decimal("0")
    currency_code: str = Field(default="IRR", max_length=3)
    valid_until: date | None = None
    opportunity_id: UUID | None = None
    organization_id: UUID | None = None
    contact_id: UUID | None = None
    owner_user_id: str | None = Field(default=None, max_length=100)
    notes: str | None = None


class QuoteUpdate(BaseModel):
    title: str | None = Field(default=None, max_length=255)
    amount: Decimal | None = None
    currency_code: str | None = Field(default=None, max_length=3)
    valid_until: date | None = None
    opportunity_id: UUID | None = None
    organization_id: UUID | None = None
    contact_id: UUID | None = None
    owner_user_id: str | None = Field(default=None, max_length=100)
    notes: str | None = None
    status: QuoteStatus | None = None


class QuoteRead(ORMBase):
    id: UUID
    tenant_id: UUID
    title: str
    quote_number: str
    status: QuoteStatus
    amount: Decimal
    currency_code: str
    valid_until: date | None
    opportunity_id: UUID | None
    organization_id: UUID | None
    contact_id: UUID | None
    owner_user_id: str | None
    notes: str | None
    created_at: datetime
    updated_at: datetime
