from pydantic import BaseModel
from datetime import datetime
import typing as t

from app.core.security import chacha20Decrypt, chacha20Encrypt

class Base(BaseModel):
    create_time: datetime
    update_time: datetime


class Permission(BaseModel):
    id: int
    menu:str
    function:str
    link:str
    privilege:str

class RoleBase(BaseModel):
    id: int
    name:str
    description:str
    level:int


class RoleWithPermission(RoleBase):
    permissions:t.List[Permission] = []

class AssignUserRoles(BaseModel):
    userid:int
    roleids:t.List[int]
    
class UserBase(BaseModel):
    email: str
    is_active: bool = True
    is_superuser: bool = False
    first_name: str = None
    last_name: str = None
    roles:t.List[RoleBase] = []
   

class UserOut(BaseModel):
    id: int
    email: str
    is_active: bool = True
    is_superuser: bool = False
    first_name: str = None
    last_name: str = None


class UserCreate(UserBase):
    email:str
    password: str
    hashed_password :str = None
    first_name: str
    last_name: str
    is_active:bool
    is_superuser:bool
    tenantid:t.Optional[str] = "1"
    createuserid:t.Optional[int] = None
    updateuserid:t.Optional[int] = None

    class ConfigDict:
        orm_mode = True


class UserEdit(UserBase):
    password: t.Optional[str] = None
    hashed_password :str = None
    updateuserid:t.Optional[int] = None

    class ConfigDict:
        orm_mode = True


class User(UserBase):
    id: int

    class ConfigDict:
        orm_mode = True


class Token(BaseModel):
    access_token: str
    token_type: str

class AppList(Base):
    domainurl: str
    appname: str
    appid:str
    version:int
    is_saved:bool
    versionname: t.Optional[str] = None
    updateuser: UserOut
    createuser: UserOut

    
class AppVersion(Base):
    domainurl: str
    appname: str
    versionname: str
    comment:str
    appid:str
    version:t.Optional[int] = None
    updateuser: UserOut
    createuser: UserOut

class VersionUpdate(BaseModel):
    appid:str
    versionname: str
    comment:str


class TokenData(BaseModel):
    id:int = 0
    email: str = None
    permissions: str = "user"


class AppEdit(BaseModel):
    setting: str = None

class AppBase(BaseModel):
    appid: str
    setting: str = None


class App(AppBase):
    id: int

    class ConfigDict:
        orm_mode = True


class Kintone(BaseModel):
    id: int
    type: int
    name: str = None
    desc: str = None
    content: str = None

    class ConfigDict:
        orm_mode = True

class Action(BaseModel):
    id: int
    name: str = None
    title: str = None
    subtitle: str = None
    outputpoints: str = None
    property: str = None
    categoryid: int = None
    nosort: int
    categoryname : str =None
    class ConfigDict:
        orm_mode = True

class FlowIn(BaseModel):
    flowid: str 
    # domainurl:str
    appid: str 
    appname:str
    eventid: str
    name: str = None
    content: str = None

class Flow(Base):
    id: int
    flowid: str 
    appid: str 
    eventid: str
    domainurl: str
    name: str = None
    content: str = None

    class ConfigDict:
        orm_mode = True

class DomainIn(BaseModel):
    id: int
    tenantid: str
    name: str 
    url: str
    kintoneuser: str 
    kintonepwd: t.Optional[str] = None 
    is_active: bool
    createuserid:t.Optional[int] = None
    updateuserid:t.Optional[int] = None
    ownerid:t.Optional[int] = None

    def encrypt_kintonepwd(self):
        encrypted_pwd = chacha20Encrypt(self.kintonepwd)
        self.kintonepwd = encrypted_pwd

class DomainOut(BaseModel):
    id: int
    tenantid: str
    name: str 
    url: str
    kintoneuser: str
    is_active: bool
    ownerid:int

    class ConfigDict:
        orm_mode = True

class UserDomainParam(BaseModel):
    userid:int
    domainid:int

class UserDomain(BaseModel):
    id: int
    is_default: bool
    domain:DomainOut
    user:UserOut

class UserDomainIn(BaseModel):
    is_default: bool
    domainid:int
    userid:int

class Domain(Base):
    id: int
    tenantid: str
    name: str 
    url: str
    kintoneuser: str 
    is_active: bool
    updateuser:UserOut
    owner:UserOut
    
    class ConfigDict:
        orm_mode = True


class Event(Base):
    id: int
    category: str
    type: str 
    eventid: str
    function: str 
    mobile: bool
    eventgroup: bool

    class ConfigDict:
        orm_mode = True

class ErrorCreate(BaseModel):
    title:str
    location:str
    content:str