from typing import Optional, Dict, Any
from sqlmodel import Field
from sqlalchemy import Column, Text, Integer, Float, JSON
from datetime import datetime
from fmatch.saas.db import Base
import uuid


class C2ASuggestion(Base, table=True):
    __tablename__ = "c2a_suggestions"

    id: str = Field(primary_key=True, default_factory=lambda: str(uuid.uuid4()))
    policy_id: str = Field(index=True)
    contact_id: str = Field(index=True)
    account_id: str = Field(index=True)

    # lifecycle
    status: str = Field(default="pending", index=True)  # pending|linked|rejected|error
    explanation: Optional[str] = Field(default=None)  # e.g., "manual"
    reason_code: Optional[str] = Field(default="assign")  # assign|upgrade

    # parity fields
    tier: Optional[str] = Field(default=None, index=True, max_length=20)
    # Store compact top-contributor reasons and full field score details as JSON
    reasons: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    field_score_details: Optional[Dict[str, Any]] = Field(
        default=None, sa_column=Column(JSON)
    )
    incumbent_field_score_details: Optional[str] = Field(
        sa_column=Column(Text), default="{}"
    )
    decided_at: Optional[datetime] = Field(default=None)
    decided_by: Optional[str] = Field(default=None)
    registry_version: Optional[str] = Field(default="")
    gain: Optional[float] = Field(sa_column=Column(Float), default=None)
    last_verified_at: Optional[datetime] = Field(default=None)

    # audit
    incumbent_account_id: Optional[str] = Field(default=None)
    applied_field: Optional[str] = Field(
        default=None
    )  # "AccountId" or "AccountContactRelation"
    previous_value: Optional[str] = Field(default=None)
    applied_value: Optional[str] = Field(default=None)
    # When using AccountContactRelation writeback, capture created relation id for reliable undo
    relation_id: Optional[str] = Field(default=None)
    score: Optional[float] = Field(default=None)
    score_gap: Optional[float] = Field(default=None)
    # Link to a job (for reporting/undo)
    job_id: Optional[str] = Field(default=None, index=True)
    error_message: Optional[str] = Field(default=None)

    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(
        default_factory=datetime.utcnow,
        description="Auto-updated timestamp",
    )

    __table_args__ = {"extend_existing": True}


class C2AJob(Base, table=True):
    __tablename__ = "c2a_jobs"

    id: str = Field(primary_key=True, default_factory=lambda: str(uuid.uuid4()))
    account_id: str = Field(index=True)
    user_id: Optional[str] = Field(default=None, index=True)

    status: str = Field(default="queued")  # queued|running|completed|failed|canceled
    params_json: Optional[str] = Field(sa_column=Column(Text), default=None)

    # parity job fields
    kind: str = Field(default="c2a_bulk_link")
    filters_json: str = Field(sa_column=Column(Text), default="[]")
    exclusions_json: str = Field(sa_column=Column(Text), default="[]")
    writeback_field: str = Field(default="AccountId")
    overwrite_mode: str = Field(default="if_empty")

    total: int = Field(sa_column=Column(Integer), default=0)
    processed: int = Field(sa_column=Column(Integer), default=0)
    applied: int = Field(sa_column=Column(Integer), default=0)
    skipped: int = Field(sa_column=Column(Integer), default=0)
    skipped_b2c: int = Field(sa_column=Column(Integer), default=0)
    conflicts: int = Field(sa_column=Column(Integer), default=0)
    error_count: int = Field(sa_column=Column(Integer), default=0)

    approval_status: str = Field(
        default="auto"
    )  # auto|waiting_approval|approved|rejected
    requested_by: Optional[str] = Field(default=None)
    approved_by: Optional[str] = Field(default=None)
    approved_via: Optional[str] = Field(default=None)

    started_at: Optional[datetime] = Field(default=None)
    ended_at: Optional[datetime] = Field(default=None)
    last_cursor: Optional[str] = Field(sa_column=Column(Text), default=None)
    last_page_size: int = Field(sa_column=Column(Integer), default=0)
    eta_sec: int = Field(sa_column=Column(Integer), default=0)
    blocked_if_empty: int = Field(sa_column=Column(Integer), default=0)
    blocked_never: int = Field(sa_column=Column(Integer), default=0)

    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    __table_args__ = {"extend_existing": True}
