import React, { useCallback, useEffect, useState } from 'react';
import { Button, Form, Input, notification } from 'antd';
import dayjs, { Dayjs } from 'dayjs';
import { i18nText } from '../../../i18nKeys';
import { Tag } from '../../../types/tags';
import { Slot } from '../../../types/experts';
import { RoomEdit, RoomEditDTO } from '../../../types/rooms';
import { getRoomById, updateRoom } from '../../../actions/rooms';
import { Loader } from '../../view/Loader';
import { CustomInput } from '../../view/CustomInput';
import { CustomSelect } from '../../view/CustomSelect';
import { CustomSwitch } from '../../view/CustomSwitch';
import { CustomMultiSelect } from '../../view/CustomMultiSelect';
import { CustomDatePicker } from '../../view/CustomDatePicker';

type EditRoomFormProps = {
    roomId: number,
    locale: string,
    jwt: string,
    mode: 'create' | 'edit';
    afterSubmit?: () => void;
}

type RoomFormState = {
    title?: string;
    description?: string;
    date?: Dayjs;
    maxCount?: number;
    startAt?: string;
    supervisor?: boolean;
    tags?: number[];
};

export const EditRoomForm = ({ roomId, locale, jwt, mode, afterSubmit }: EditRoomFormProps) => {
    const [form] = Form.useForm<RoomFormState>();
    const [editingRoom, setEditingRoom] = useState<RoomEditDTO>();
    const dateValue = Form.useWatch('date', form);
    const [loading, setLoading] = useState<boolean>(false);
    const [fetchLoading, setFetchLoading] = useState<boolean>(false);

    useEffect(() => {
        setFetchLoading(true);
        getRoomById(locale, jwt, roomId)
            .then((data) => {
                setEditingRoom(data);
                const { item } = data || {};

                if (mode === 'edit' && item) {
                    form.setFieldsValue({
                        title: item.title,
                        description: item.description,
                        date: item?.scheduledStartAtUtc ? dayjs(item.scheduledStartAtUtc) : undefined,
                        maxCount: item.maxClients,
                        startAt: item?.scheduledStartAtUtc,
                        supervisor: item.isNeedSupervisor,
                        tags: item.tagIds || undefined
                    })
                }
            })
            .finally(() => {
                setFetchLoading(false);
            })
    }, []);

    const getAvailableSlots = useCallback((): string[] => {
        const dateList = new Set<string>();
        if (editingRoom?.availableSlots) {
            editingRoom.availableSlots.forEach(({ startTime }) => {
                const [date] = startTime.split('T');
                dateList.add(dayjs(date).format('YYYY-MM-DD'));
            });

            return Array.from(dateList);
        }

        return [];
    }, [editingRoom?.availableSlots]);

    const getTimeOptions = (slots?: Slot[], curDate?: Dayjs) => {
        const date = curDate ? curDate.format('YYYY-MM-DD') : '';
        if (slots && slots?.length && date) {
            return slots.filter(({ startTime }) => dayjs(startTime).format('YYYY-MM-DD') === date)
                .map(({ startTime, endTime }) => ({ value: startTime, label: `${dayjs(startTime).format('HH:mm')} - ${dayjs(endTime).format('HH:mm')}` }));
        }

        return [];
    }

    const getTagsOptions = (tags?: Tag[]) => {
        if (tags) {
            return tags.map(({ id, name }) => ({ value: id, label: <span>{name}</span> })) || [];
        }

        return [];
    }

    const onSubmit = () => {
        setLoading(true);
        const { title, description, startAt, maxCount, tags, supervisor } = form.getFieldsValue();
        const result: RoomEdit = {
            ...editingRoom,
            id: roomId,
            title,
            scheduledStartAtUtc: startAt,
            maxClients: maxCount,
            isNeedSupervisor: supervisor,
            tagIds: tags || []
        };

        if (description) {
            result.description = description;
        }

        updateRoom(locale, jwt, result)
            .then(() => {
                afterSubmit && afterSubmit();
            })
            .catch((err) => {
                notification.error({
                    message: 'Error',
                    description: err?.response?.data?.errMessage
                });
            })
            .finally(() => {
                setLoading(false)
            });
    }

    const disabledDate = (current: Dayjs) => current && !getAvailableSlots().includes(current.format('YYYY-MM-DD'));

    return (
        <Loader isLoading={fetchLoading}>
            <Form
                form={form}
                autoComplete="off"
                style={{ display: 'flex', gap: 16, flexDirection: 'column' }}
                onFinish={onSubmit}
                className="b-room-form"
            >
                <Form.Item
                    name="title"
                    rules={[{ required: true }]}
                    noStyle
                >
                    <CustomInput
                        size="small"
                        placeholder={i18nText('title', locale)}
                    />
                </Form.Item>
                <Form.Item name="description">
                    <Input.TextArea
                        className="b-textarea"
                        rows={4}
                        maxLength={1000}
                        placeholder={i18nText('description', locale)}
                    />
                </Form.Item>
                <div className="b-room-form__grid">
                    <Form.Item
                        name="date"
                        rules={[{ required: true }]}
                        noStyle
                    >
                        <CustomDatePicker
                            locale={locale}
                            label={i18nText('room.date', locale)}
                            disabledDate={disabledDate}
                        />
                    </Form.Item>
                    <Form.Item
                        name="startAt"
                        rules={[{ required: true }]}
                        noStyle
                    >
                        <CustomSelect
                            label={i18nText('room.time', locale)}
                            options={getTimeOptions(editingRoom?.availableSlots, dateValue)}
                            disabled={!dateValue}
                        />
                    </Form.Item>
                    <Form.Item
                        name="maxCount"
                        rules={[{ required: true }]}
                        noStyle
                    >
                        <CustomSelect
                            label={i18nText('room.maxParticipants', locale)}
                            options={Array.from({ length: 16 }).map((_, i) => ({ value: i+1, label: i+1 }))}
                        />
                    </Form.Item>
                    <Form.Item
                        name="supervisor"
                        valuePropName="checked"
                        label={i18nText('room.presenceOfSupervisor', locale)}
                        className="b-room-switch"
                    >
                        <CustomSwitch />
                    </Form.Item>
                </div>
                <Form.Item
                    name="tags"
                    noStyle
                >
                    <CustomMultiSelect
                        label={i18nText('topics', locale)}
                        options={getTagsOptions(editingRoom?.tags)}
                    />
                </Form.Item>
                <Button
                    className="card-detail__apply"
                    htmlType="submit"
                    loading={loading}
                    disabled={loading}
                >
                    {i18nText('room.save', locale)}
                </Button>
            </Form>
        </Loader>
    );
};
