import { Avatar, Button, Select, Space, Table, message } from "antd";
import { useCallback, useEffect, useRef, useState } from "react";
import debounce from 'lodash/debounce';
import { IUser, userReq } from "../request/user";
import { IDoc, IDocUserRole, docReq } from "../request/doc";
import { TableRefreshButton } from "./table-refresh-button";
import { RoleSelect } from "./role-selector";
import { Role } from "../enum";

interface IShareProps {
    docId: string;
}

export function Share(props: IShareProps) {
    const [users, setUsers] = useState<IDocUserRole[]>([]);
    const [doc, setDoc] = useState<IDoc>({ id: props.docId, name: '', type: '' } as IDoc);

    const refreshUsers = async (docId: string) => {
        const users = await docReq.getAccessUsers(docId);
        setUsers(users);
    }

    const inviteUsers = async (userIds: string[], role: Role) => {
        await docReq.inviteUsers(props.docId, userIds, role);
        refreshUsers(props.docId);
    };

    const updateRole = async (userId: string, role: Role) => {
        await docReq.updateRole(props.docId, userId, role);
        refreshUsers(props.docId);
    };

    const copyShareLink = async (role: Role) => {
        const link = (await docReq.createShareLink(props.docId, role)).link;
        const shareUrl = `${location.host}/open-share-link/${link}`;
    
        if (navigator.clipboard && window.isSecureContext) {
            // 如果在 HTTPS 环境下，使用 navigator.clipboard.writeText
            navigator.clipboard.writeText(shareUrl)
                .then(() => {
                    message.success({
                        content: 'Copy Successful!',
                        duration: 1,
                    });
                })
                .catch((error) => {
                    message.error({
                        content: 'Copy Fail!' + error,
                        duration: 1,
                    });
                });
        } else {
            // 如果在 HTTP 环境下，使用备用方案
            const textarea = document.createElement('textarea');
            textarea.value = shareUrl;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            document.body.removeChild(textarea);
    
            message.success({
                content: 'Copy Successful!',
                duration: 1,
            });
        }
    };

    useEffect(() => {
        docReq.get(props.docId).then((d) => setDoc(d));
        refreshUsers(props.docId);
    }, [props.docId])

    return <ShareComponent
        doc={doc}
        disabled={doc.role !== Role.owner ? true : undefined}
        accessUsers={users}
        onUpdateUserRole={updateRole}
        onCopyShareLink={copyShareLink}
        refreshUsers={() => refreshUsers(props.docId)}
        onInvite={inviteUsers}
    ></ShareComponent>
}

interface IShareComponentProps {
    doc: IDoc;
    accessUsers: IDocUserRole[];
    refreshUsers: () => void;
    defaultShareLinkRole?: Role;
    defaultInviteRole?: Role;
    disabled?: boolean;
    onInvite: (userIds: string[], role: Role) => void;
    onUpdateUserRole: (userId: string, role: Role) => void;
    onCopyShareLink: (role: Role) => void;
}
function ShareComponent(props: IShareComponentProps) {
    return <div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
        <h2 style={{ margin: '0px 0px 10px 0px' }}>Share "{props.doc.name}"</h2>
        <InviteUser {...props}></InviteUser>

        <h3>People with access</h3>
        <AccessUsers {...props}></AccessUsers>

        <h3>Share Link</h3>
        <ShareLink {...props}></ShareLink>
    </div>
}


interface IUserMentionsProps {
    value: IUser[];
    style: React.CSSProperties;
    onChange: (value: IUser[]) => void;
    disabled?: boolean;
}
const UserMentions: React.FC<IUserMentionsProps> = (props) => {
    const [loading, setLoading] = useState(false);
    const [searchUsers, setSearchUsers] = useState<IUser[]>([]);
    const ref = useRef<string>();


    const loadSearchUsers = (key: string) => {
        setLoading(true);
        userReq.search(key)
            .then((items: IUser[]) => {
                if (ref.current !== key && key !== '') return;

                setLoading(false);
                const selectedUserIds = props.value.map(v => v.id);
                setSearchUsers(items.filter(u => !selectedUserIds.includes(u.id)).slice(0, 10));
            });
    };

    const debounceLoadUsers = useCallback(debounce(loadSearchUsers, 300), []);

    const onSearch = (search: string) => {
        console.log('Search:', search);
        ref.current = search;
        setSearchUsers([]);

        debounceLoadUsers(search);
    };

    const onChange = (userIds: string[]) => {
        const users = searchUsers.filter(u => userIds.includes(u.id));
        props.onChange(users);
    };

    useEffect(() => {
        loadSearchUsers('');
    }, []);

    return (
        <Select
            style={props.style}
            placeholder="invite by username"
            mode="multiple"
            disabled={props.disabled}
            allowClear
            optionFilterProp={"label"}
            loading={loading}
            onSearch={onSearch}
            options={searchUsers.map((u) => ({ label: u.username, value: u.id }))}
            value={props.value.map(u => u.id)}
            onChange={onChange}
        />
    );
};

const InviteUser: React.FC<IShareComponentProps> = (props) => {
    const [users, setUsers] = useState<IUser[]>([]);
    const [inviteRole, setInviteRole] = useState<Role>(props.defaultInviteRole ?? Role.viewer);

    const onInvite = () => {
        props.onInvite(users.map(u => u.id), inviteRole);
        setUsers([]);
    }

    return (
        <Space size="middle" style={{ display: 'flex' }}>
            <UserMentions disabled={props.disabled} style={{ flex: 1, width: '180px' }} value={users} onChange={(v) => { setUsers(v) }} />
            <RoleSelect disabled={props.disabled} value={inviteRole} onUpdate={setInviteRole} />
            <Button type="primary" disabled={props.disabled || users.length === 0} onClick={onInvite}>Invite</Button>
        </Space >
    )
}

const AccessUsers: React.FC<IShareComponentProps> = (props) => {
    return (
        <>
            <TableRefreshButton refresh={props.refreshUsers}></TableRefreshButton>
            <Table
                style={{ flex: 1 }}
                dataSource={props.accessUsers}
                showHeader={false}
                pagination={false}
                size="middle"
                rowKey={(r) => r.userId}
                columns={[
                    {
                        key: "username",
                        dataIndex: 'username',
                        render: (v: string) => (
                            <Space>
                                <Avatar shape='square'><b>{v.substring(0, 1)}</b></Avatar>
                                <span>{v}</span>
                            </Space>
                        )
                    },
                    {
                        key: "role",
                        dataIndex: "role",
                        render: (role: Role, record) => (
                            <RoleSelect disabled={props.disabled} value={role} onUpdate={(r) => props.onUpdateUserRole(record.userId, r)}></RoleSelect>
                        )
                    }
                ]}
            ></Table>
        </>
    )
}

const ShareLink: React.FC<IShareComponentProps> = (props) => {
    const [shareLinkRole, setShareLinkRole] = useState<Role>(props.defaultShareLinkRole ?? Role.viewer);

    return (
        <div>
            <RoleSelect disabled={props.disabled} value={shareLinkRole} onUpdate={setShareLinkRole} />
            <Button disabled={props.disabled} style={{ float: 'right' }} type="primary" onClick={() => props.onCopyShareLink(shareLinkRole)}>Copy Share Link</Button>
        </div>
    )
}
