<script lang="ts">
  import {Input, Textarea} from '../base';
  import {Button, Checkbox, FloatingTrigger, Select} from '../base/index.js';
  import {useNodesData, useSvelteFlow} from '@xyflow/svelte';
  import {contentTypes, startFormTypes} from '#consts';
  import type {Parameter} from '#types';
  import {store} from '#store/stores.svelte';
  import {getCurrentNodeId} from '#components/utils/NodeUtils';
  import {
    renameStartFieldReferencesInNodes,
    removeStartFormField,
    START_NODE_TYPE,
    SYSTEM_START_PARAM_NAME,
    updateStartFormField,
  } from '../../utils/workflowNodeFields';

  const { parameter, index }: {
        parameter: Parameter,
        index: number
    } = $props();


    let currentNodeId = getCurrentNodeId();
    let node = useNodesData(currentNodeId);
    let param = $derived.by(() => {
        return {
            ...parameter,
            ...(node?.current?.data?.parameters as Array<Parameter>)[index]
        };
    });
    let isSystemStartParam = $derived.by(() => {
        return param.systemReserved === true && param.name === SYSTEM_START_PARAM_NAME;
    });
    let isStartNodeInputParam = $derived.by(() => {
        return node?.current?.type === START_NODE_TYPE && param.refType === 'input';
    });
    let availableFormTypes = $derived.by(() => {
        if (isSystemStartParam) {
            return startFormTypes.filter((item) => item.value === 'input' || item.value === 'textarea');
        }
        return startFormTypes;
    });
    let displayFormTypeValue = $derived.by(() => {
        if (isStartNodeInputParam && param.contentType === 'file') {
            return ['file'];
        }
        return param.formType ? [param.formType] : [];
    });
    let displayParamName = $derived.by(() => {
        if (isSystemStartParam) {
            return '用户问题';
        }
        return param.name;
    });

    const { updateNodeData } = useSvelteFlow();

    const toStartFormFieldType = (value: string) => {
        if (value === 'input') {
            return 'text';
        }
        return value;
    };

    const trimString = (value: unknown) => {
        return value == null ? '' : String(value).trim();
    };

    const applyStartFieldPatch = (fieldKey: string, patch: Record<string, any>) => {
        const currentFieldId = trimString(param.id);
        store.updateNodes((nodes) => {
            const edges = store.getEdges();
            let nextFieldKey = fieldKey;
            const nextNodes = nodes.map((currentNode) => {
                if (currentNode.id !== currentNodeId) {
                    return currentNode;
                }
                const nextData = updateStartFormField(currentNode.data as Record<string, any>, fieldKey, patch);
                const nextSchema = Array.isArray(nextData.startFormSchema) ? nextData.startFormSchema : [];
                const matchedField = nextSchema.find((field) => {
                    return (currentFieldId && trimString(field?.id) === currentFieldId)
                        || trimString(field?.key) === fieldKey;
                });
                nextFieldKey = trimString(matchedField?.key) || fieldKey;
                return {
                    ...currentNode,
                    data: {
                        ...((currentNode.data || {}) as Record<string, any>),
                        ...nextData
                    }
                };
            });
            return renameStartFieldReferencesInNodes(
                nextNodes,
                edges,
                currentNodeId,
                fieldKey,
                nextFieldKey
            );
        });
    };

    const updateParameter = (key: string, value: any) => {
        if (isStartNodeInputParam) {
            const fieldKey = param.name || '';
            if (!fieldKey) {
                return;
            }
            let patch: Record<string, any> = {};
            if (key === 'name') {
                patch = { key: value };
            } else if (key === 'required') {
                patch = { required: Boolean(value) };
            } else if (key === 'formType') {
                patch = { type: toStartFormFieldType(value) };
            } else if (key === 'formLabel') {
                patch = { label: value };
            } else if (key === 'formDescription') {
                patch = { description: value };
            } else if (key === 'formPlaceholder') {
                patch = { placeholder: value };
            } else if (key === 'enums') {
                patch = { options: Array.isArray(value) ? value : [] };
            } else if (key === 'contentType') {
                patch = { type: value === 'file' ? 'file' : 'text' };
            }
            if (Object.keys(patch).length === 0) {
                return;
            }
            applyStartFieldPatch(fieldKey, patch);
            return;
        }
        updateNodeData(currentNodeId, (node) => {
            let parameters = node.data.parameters as Array<Parameter>;
            (parameters[index] as any)[key] = value;
            return {
                parameters
            };
        });
    };

    const updateParamByEvent = (name: string, event: Event) => {
        const newValue = (event.target as any).value;
        updateParameter(name, newValue);
    };

    const updateName = (event: Event) => {
        const newValue = (event.target as any).value;
        updateParameter('name', newValue);
    };

    const updateRequired = (event: Event) => {
        const checked = (event.target as any).checked;
        updateParameter('required', checked);
    };

    const updateFormType = (item: any) => {
        const newValue = item.value;
        updateParameter('formType', newValue);
        if (isSystemStartParam) {
            updateParameter('contentType', 'text');
        }
    };

    const updateContentType = (item: any) => {
        const newValue = item.value;
        updateParameter('contentType', newValue);
    };


    let triggerObject: any;
    const handleDelete = () => {
        if (isStartNodeInputParam) {
            updateNodeData(currentNodeId, (node) => {
                return removeStartFormField(node.data as Record<string, any>, param.name);
            });
            triggerObject?.hide();
            return;
        }
        updateNodeData(currentNodeId, (node) => {
            let parameters = node.data.parameters as Array<Parameter>;
            parameters.splice(index, 1);
            return {
                parameters: [...parameters]
            };
        });
        triggerObject?.hide();
    };

</script>


<div class="input-item">
    <Input style="width: 100%;" value={displayParamName} placeholder="请输入参数名称"
           disabled={param.nameDisabled === true}
           oninput={updateName} />
</div>
<div class="input-item">
    <Checkbox checked={param.required} disabled={param.requiredDisabled === true} onchange={updateRequired} />
</div>
<div class="input-item">
    <FloatingTrigger placement="bottom" bind:this={triggerObject}>
        <Button class="input-btn-more">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                <path
                    d="M4.5 10.5C3.675 10.5 3 11.175 3 12C3 12.825 3.675 13.5 4.5 13.5C5.325 13.5 6 12.825 6 12C6 11.175 5.325 10.5 4.5 10.5ZM19.5 10.5C18.675 10.5 18 11.175 18 12C18 12.825 18.675 13.5 19.5 13.5C20.325 13.5 21 12.825 21 12C21 11.175 20.325 10.5 19.5 10.5ZM12 10.5C11.175 10.5 10.5 11.175 10.5 12C10.5 12.825 11.175 13.5 12 13.5C12.825 13.5 13.5 12.825 13.5 12C13.5 11.175 12.825 10.5 12 10.5Z"></path>
            </svg>
        </Button>
        {#snippet floating()}
            <div class="input-more-setting">
                {#if param.systemReserved}
                    <div class="input-more-item">
                        系统入口参数，名称和必填规则固定，可调整展示标题、说明、占位符和输入方式。
                    </div>
                {/if}
                <div class="input-more-item">
                    数据内容：
                    <Select items={contentTypes} style="width: 100%" defaultValue={["text"]}
                            value={param.contentType ? [param.contentType] : []}
                            disabled={param.systemReserved === true || isStartNodeInputParam}
                            onSelect={updateContentType}
                    />
                </div>
                <div class="input-more-item">
                    输入方式：
                    <Select items={availableFormTypes} style="width: 100%" defaultValue={["input"]}
                            value={displayFormTypeValue}
                            onSelect={updateFormType}
                    />
                </div>

                {#if param.formType === "radio" || param.formType === "checkbox" || param.formType === "select" }
                    <div class="input-more-item">
                        数据选项：
                        <Textarea rows={3} style="width: 100%;" onchange={(event)=>{
                        updateParameter('enums', ((event.target as HTMLTextAreaElement)?.value || '').trim().split("\n"))
                    }} disabled={param.systemReserved === true} value={param.enums?.join("\n")} placeholder="一行一个选项" />
                    </div>
                {/if}

                <div class="input-more-item">
                    数据标题：
                    <Textarea rows={1} style="width: 100%;" onchange={(event)=>{
                        updateParamByEvent('formLabel', event)
                    }} value={param.formLabel} />
                </div>

                <div class="input-more-item">
                    数据描述：
                    <Textarea rows={2} style="width: 100%;" onchange={(event)=>{
                        updateParamByEvent('formDescription', event)
                    }} value={param.formDescription} />
                </div>

                <div class="input-more-item">
                    占位符：
                    <Textarea rows={2} style="width: 100%;" onchange={(event)=>{
                        updateParamByEvent('formPlaceholder', event)
                    }} value={param.formPlaceholder} />
                </div>


                <div class="input-more-item" style:display={param.deleteDisabled === true ? 'none' : 'flex'}>
                    <Button onclick={handleDelete}>删除</Button>
                </div>
            </div>
        {/snippet}
    </FloatingTrigger>
</div>


<style lang="less">
  .input-item {
    display: flex;
    align-items: center;
  }

  .input-more-setting {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 10px;
    background: var(--tf-bg-surface);
    border: 1px solid var(--tf-border-color-strong);
    border-radius: 5px;
    width: 200px;
    box-shadow: var(--tf-shadow-medium);

    .input-more-item {
      display: flex;
      flex-direction: column;
      gap: 3px;
      font-size: 12px;
      color: var(--tf-text-secondary);
    }
  }

</style>
