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

from adafri.v1.base.firebase_collection import FirebaseCollectionBase

CHANNEL_COLLECTION = 'workflow_channels'

CHANNEL_PICKABLE_FIELDS = [
    'id', 'workspaceId', 'name', 'slug', 'description',
    'type', 'isDefault', 'ownerId',
    'allowedTeamIds', 'allowedMemberUids', 'pinnedMessageIds',
    'createdAt', 'createdBy',
]

CHANNEL_MUTABLE_FIELDS = [
    'name', 'slug', 'description', 'type',
    'allowedTeamIds', 'allowedMemberUids', 'pinnedMessageIds',
]

CHANNEL_TYPES = ['general', 'announcements', 'creatives', 'scenarios', 'custom']


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


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


class WorkflowChannelFields:
    @staticmethod
    def check_create_fields(data: dict) -> dict:
        if not data:
            return {'error': 'Missing data'}
        if not data.get('name', '').strip():
            return {'error': 'name is required'}
        if not data.get('workspaceId', '').strip():
            return {'error': 'workspaceId is required'}
        return data

    @staticmethod
    def mutable_keys() -> list:
        return CHANNEL_MUTABLE_FIELDS


@dataclass(init=False)
class WorkflowChannel(FirebaseCollectionBase):
    id: str
    workspaceId: str
    name: str
    slug: str
    description: str
    type: str
    isDefault: bool
    ownerId: str
    allowedTeamIds: list
    allowedMemberUids: list
    pinnedMessageIds: list
    createdAt: str
    createdBy: str

    def __init__(self, data=None, **kwargs):
        super().__init__(collection_name=CHANNEL_COLLECTION, **kwargs)
        d = data or {}
        name = d.get('name', '')
        self.id = d.get('id') or _new_id()
        self.workspaceId = d.get('workspaceId', '')
        self.name = name
        self.slug = d.get('slug') or name.lower().replace(' ', '-')
        self.description = d.get('description', '')
        self.type = d.get('type', 'custom')
        self.isDefault = bool(d.get('isDefault', False))
        self.ownerId = d.get('ownerId', '')
        self.allowedTeamIds = list(d.get('allowedTeamIds') or [])
        self.allowedMemberUids = list(d.get('allowedMemberUids') or [])
        self.pinnedMessageIds = list(d.get('pinnedMessageIds') or [])
        self.createdAt = d.get('createdAt') or _now()
        self.createdBy = d.get('createdBy', '')

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

    def to_dict(self) -> dict:
        return {
            'id': self.id,
            'workspaceId': self.workspaceId,
            'name': self.name,
            'slug': self.slug,
            'description': self.description,
            'type': self.type,
            'isDefault': self.isDefault,
            'ownerId': self.ownerId,
            'allowedTeamIds': self.allowedTeamIds,
            'allowedMemberUids': self.allowedMemberUids,
            'pinnedMessageIds': self.pinnedMessageIds,
            'createdAt': self.createdAt,
            'createdBy': self.createdBy,
        }

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

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

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

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

    def update(self, data: dict) -> 'WorkflowChannel':
        filtered = {k: v for k, v in data.items() if k in CHANNEL_MUTABLE_FIELDS}
        self.collection().document(self.id).update(filtered)
        for k, v in filtered.items():
            setattr(self, k, v)
        return self

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