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

from adafri.v1.base.firebase_collection import FirebaseCollectionBase

WORKSPACE_COLLECTION = 'workflow_workspaces'

WORKSPACE_PICKABLE_FIELDS = [
    'id', 'accountId', 'campaignIds', 'name', 'description',
    'logo', 'color', 'industry', 'website',
    'status', 'assignees', 'dueDate', 'tags',
    'ownerUid', 'adminUids',
    'createdAt', 'updatedAt', 'createdBy',
]

WORKSPACE_MUTABLE_FIELDS = [
    'name', 'description', 'logo', 'color', 'industry', 'website',
    'status', 'assignees', 'dueDate', 'tags', 'campaignIds',
    'adminUids',
]

WORKSPACE_STATUS = ['draft', 'in_review', 'approved', 'live', 'completed']


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


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


class WorkflowWorkspaceFields:
    @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'}
        return data

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


@dataclass(init=False)
class WorkflowWorkspace(FirebaseCollectionBase):
    id: str
    accountId: str
    campaignIds: list
    name: str
    description: str
    logo: Optional[str]
    color: Optional[str]
    industry: Optional[str]
    website: Optional[str]
    status: str
    assignees: list
    dueDate: Optional[str]
    tags: list
    ownerUid: str
    adminUids: list
    createdAt: str
    updatedAt: str
    createdBy: str

    def __init__(self, data=None, **kwargs):
        super().__init__(collection_name=WORKSPACE_COLLECTION, **kwargs)
        d = data or {}
        self.id = d.get('id') or _new_id()
        self.accountId = d.get('accountId', '')
        # Migrate legacy single-campaign workspaces to the list format
        legacy = d.get('campaignId')
        self.campaignIds = list(d.get('campaignIds') or ([legacy] if legacy else []))
        self.name = d.get('name', '')
        self.description = d.get('description', '')
        self.logo = d.get('logo')
        self.color = d.get('color')
        self.industry = d.get('industry')
        self.website = d.get('website')
        self.status = d.get('status', 'draft')
        self.assignees = list(d.get('assignees') or [])
        self.dueDate = d.get('dueDate')
        self.tags = list(d.get('tags') or [])
        self.ownerUid = d.get('ownerUid', '')
        self.adminUids = list(d.get('adminUids') or [])
        self.createdAt = d.get('createdAt') or _now()
        self.updatedAt = d.get('updatedAt') or _now()
        self.createdBy = d.get('createdBy', '')

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

    def to_dict(self) -> dict:
        return {
            'id': self.id,
            'accountId': self.accountId,
            'campaignIds': self.campaignIds,
            'name': self.name,
            'description': self.description,
            'logo': self.logo,
            'color': self.color,
            'industry': self.industry,
            'website': self.website,
            'status': self.status,
            'assignees': self.assignees,
            'dueDate': self.dueDate,
            'tags': self.tags,
            'ownerUid': self.ownerUid,
            'adminUids': self.adminUids,
            'createdAt': self.createdAt,
            'updatedAt': self.updatedAt,
            'createdBy': self.createdBy,
        }

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

    @classmethod
    def find(cls, workspace_id: str, account_id: str = None) -> 'Optional[WorkflowWorkspace]':
        inst = cls()
        doc = inst.collection().document(workspace_id).get()
        if not doc.exists:
            return None
        data = {**doc.to_dict(), 'id': doc.id}
        if account_id and data.get('accountId') != account_id:
            return None
        return cls(data)

    @classmethod
    def listByAccount(cls, account_id: str) -> 'list[WorkflowWorkspace]':
        inst = cls()
        docs = inst.collection().where('accountId', '==', account_id).stream()
        return [cls({**d.to_dict(), 'id': d.id}) for d in docs]

    @classmethod
    def listByCampaign(cls, campaign_id: str, account_id: str) -> 'list[WorkflowWorkspace]':
        inst = cls()
        docs = (
            inst.collection()
            .where('accountId', '==', account_id)
            .where('campaignIds', 'array_contains', campaign_id)
            .stream()
        )
        return [cls({**d.to_dict(), 'id': d.id}) for d in docs]

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

    def update(self, data: dict) -> 'WorkflowWorkspace':
        filtered = {k: v for k, v in data.items() if k in WORKSPACE_MUTABLE_FIELDS}
        filtered['updatedAt'] = _now()
        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()
