import {CurdColumn, CurdPage} from "../../../../components/curd";
import {useCallback, useMemo, useState} from "react";
import {LDAP, LDAPApis} from "../../../../api/ldap.ts";
import {ICurdConfig} from "../../../../components/curd/types.ts";
import {Alert, Button} from "antd";
import './index.less'
import {Link} from "react-router-dom";
import {useRouteLoaderData} from "react-router";
import {SyncOutlined} from "@ant-design/icons";
import {isNullOrTrue, Message} from "auto-antd";
import {UserAttributesText} from "../components/UserAttributes.tsx";
import {safeParse} from "../../../../utils/json.ts";

const columns: CurdColumn[] = [
    {
        key: 'id',
        title: 'ID',
        type: 'string',
        disabled: true,
        required: false,
        width: 50,
        addable: false,
    },
    {
        key: 'account',
        title: '账号(uid)',
        type: 'string',
        editable: false,
        placeholder: '账号，全局唯一，不可重复',
        required: true,
        width: 120,
        addable: true,
    },
    {
        key: 'givenName',
        title: '姓',
        type: 'string',
        editable: true,
        required: true,
        width: 120,
        hidden: true,
        addable: true,
    },
    {
        key: 'sn',
        title: '名',
        type: 'string',
        editable: true,
        required: true,
        width: 120,
        hidden: true,
        addable: true,
    },
    {
        key: 'objectClass',
        title: 'objectClass',
        type: 'select',
        editable: true,
        required: true,
        width: 120,
        hidden: true,
        addable: true,
        option:['top','inetOrgPerson','organizationalPerson','person'],
        multiple: true,
    },
    {
        key: 'dn',
        title: 'DN',
        type: 'string',
        placeholder: 'eg. cn=Abc,dc=tonyandmoney,dc=cn',
        width: 150,
        addable: false,
        editable: false,
        editHide: true,
    },
    {
        key: 'organize',
        title: '上级(DN)',
        type: 'string',
        placeholder: 'eg. ou=users,dc=tonyandmoney,dc=cn',
        width: 150,
    },
    {
        key: 'mail',
        title: '邮箱',
        type: 'string',
        width: 150
    },
    {
        key: 'password',
        title: '密码',
        type: 'password',
        width: 150,
        addable: true,
    },
    {
        key: 'attributes',
        title: '更多属性',
        type: 'attributes',
        render: (v: string)=>(<UserAttributesText  value={v}/>),
        hidden: true,
        required: false,
    },
    {
        key: 'remark',
        title: '备注',
        type: 'textarea',
        required: false,
    }
]

const toObjKeys = ['givenName','sn', 'objectClass']
const delKeys = ['cn','mail','userPassword','uid']

const parseUser = (user: LDAP.User) => {
    const attrs = safeParse(user.attributes, [])
    console.log('attrs', attrs)
    const attrList = []
    for (const attr of attrs) {
        attr.Value = Array.isArray(attr.Values) ? attr.Values[0] : undefined
        if (attr.Name == 'objectClass'){
            attr.Value = attr.Values || []
        }
        if (toObjKeys.includes(attr.Name)){
            (user as any)[attr.Name] = attr.Value
        }else if (!delKeys.includes(attr.Name)){
            attrList.push(attr)
        }
    }
    return {
        ...user,
        attributes: attrList,
    } as LDAP.User
}

const stringifyUser = (user: Partial<LDAP.User>) => {
    const attributes = []
    for (const attr of (user.attributes as any[])) {
        attributes.push({
            Name: attr.Name,
            Values: isNullOrTrue(attr.Value) ? [attr.Values] : []
        })
    }
    for (const k of toObjKeys){
        const v = (user as any)[k]
        if (isNullOrTrue(v)) {
            attributes.push({
                Name: k,
                Values: [v]
            })
        }
    }
    return {
        ...user,
        attributes: JSON.stringify(attributes),
    }

}

const serverConfig: ICurdConfig<LDAP.User> = {
    editDialogWidth: 700,
    labelSpan: 4,
}

/**
 * 用户列表的操作
 * @constructor
 */
export const List = () => {

    const server = useRouteLoaderData("LDAPServerUsers") as LDAP.Server
    const [loading, setLoading] = useState(false)
    const [success,setSuccess] = useState('')

    const getList = useCallback((query: any) => {
        console.log('server...', server)

        return LDAPApis.getUsers({
            ...query,
            serverKey: server.key,
        }).then(res => {
            console.log('server', res)
            return res.data.data
        })

    }, [server])

    const getDetail = (data: Partial<LDAP.User>) => {
        if (!data.id) {
            return Promise.resolve({} as LDAP.User)
        }
        return LDAPApis.getUserDetail(data.id).then(res => {
            if (res.data?.data) {
                const user = parseUser(res.data.data);
                console.log('user', user)
                return user;
            }
            throw new Error('该服务不存在！')
        })
    }

    const onSaveUser = (data: Partial<LDAP.User>) => {
        const user = stringifyUser(data)
        if (data.id){
            return LDAPApis.saveUser(user)
                .then(res => {
                    return res.data.data as LDAP.User;
                })
        }
        return LDAPApis.add(user)
            .then(res => {
                return res.data.data as LDAP.User;
            })
    }

    const syncUsers = () => {
        setLoading(true)
        LDAPApis.syncUsers({serverKey: server.key})
            .then(res => {
                console.log('sync users', res)
                if (res.data?.data) {
                    setSuccess(`操作成功：同步：${res.data.data.count}条数据！`)
                } else {
                    Message.warning(res.data.msg || '同步异常！')
                }
            }).finally(() => {
            setLoading(false)
        })
    }

    const operationRender = (record: LDAP.User, _: number) => {

        return (<>
            <Button size="small">
                <Link to={`server/${record.id}/user`}>重置密码</Link>
            </Button>
        </>)
    }

    const config = useMemo(() => {

        return {
            ...serverConfig,
            operationRender
        } as ICurdConfig<LDAP.User>

    }, [])


    return (<>
        {
            success ? (<Alert type="success" message={success} style={{margin: 5}} closable={true} onClose={()=>setSuccess('')}/> ) : null
        }
        <CurdPage columns={columns} getList={getList} getDetail={getDetail}
                  operationRender={<>
                      <Button type="primary" icon={<SyncOutlined/>} onClick={syncUsers} loading={loading}>同步</Button>
                  </>}
                  onSave={onSaveUser}
                  config={config}/>
    </>)
}
