import uuid
from dataclasses import dataclass
from datetime import datetime, timezone
from typing import Any, Optional

from adafri.v1.base.firebase_collection import FirebaseCollectionBase

CAMPAIGN_LINK_COLLECTION = 'workflow_campaign_links'

CAMPAIGN_LINK_PICKABLE_FIELDS = [
    'id', 'workspaceId', 'campaignId', 'linkedBy', 'linkedAt',
]


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


def _new_id() -> str:
    return str(uuid.uuid4())


@dataclass(init=False)
class WorkflowCampaignLink(FirebaseCollectionBase):
    id: str
    workspaceId: str
    campaignId: str
    linkedBy: str
    linkedAt: str

    def __init__(self, data=None, **kwargs):
        super().__init__(collection_name=CAMPAIGN_LINK_COLLECTION, **kwargs)
        d = data or {}
        self.id = d.get('id') or _new_id()
        self.workspaceId = d.get('workspaceId', '')
        self.campaignId = d.get('campaignId', '')
        self.linkedBy = d.get('linkedBy', '')
        self.linkedAt = d.get('linkedAt') or _now()

    @classmethod
    def from_dict(cls, obj: Any, **kwargs) -> 'WorkflowCampaignLink':
        return cls(obj, **kwargs)

    def to_dict(self) -> dict:
        return {
            'id': self.id,
            'workspaceId': self.workspaceId,
            'campaignId': self.campaignId,
            'linkedBy': self.linkedBy,
            'linkedAt': self.linkedAt,
        }

    @staticmethod
    def toListDict(items: list, fields=None) -> list:
        return [item.to_dict() for item in items]

    @classmethod
    def find(cls, link_id: str) -> 'Optional[WorkflowCampaignLink]':
        inst = cls()
        doc = inst.collection().document(link_id).get()
        if not doc.exists:
            return None
        return cls({**doc.to_dict(), 'id': doc.id})

    @classmethod
    def listByWorkspace(cls, workspace_id: str) -> 'list[WorkflowCampaignLink]':
        inst = cls()
        docs = (
            inst.collection()
            .where('workspaceId', '==', workspace_id)
            .order_by('linkedAt')
            .stream()
        )
        return [cls({**d.to_dict(), 'id': d.id}) for d in docs]

    def save(self) -> 'WorkflowCampaignLink':
        self.collection().document(self.id).set(self.to_dict())
        return self

    def delete(self) -> None:
        self.collection().document(self.id).delete()
