import axios from "axios";
import { useState } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Label } from "../ui/label";
import { Maximize2, Minimize2, Trash2Icon } from "lucide-react";
import { ActionType } from "@prisma/client";


const actionTypes = [
    {
        "name": "Overwrite local file content",
        "value": ActionType.WRITE_TO_FILE
    },
    {
        "name": "Append to local file",
        "value": ActionType.APPEND_TO_FILE
    },
    {
        "name": "Cause a transformation on OBS scene item",
        "value": ActionType.OBS_TRANSFORM
    },
    {
        "name": "Play an audio file locally",
        "value": ActionType.AUDIO_FILE
    },
]


interface RedeemableAction {
    name: string
    type: string | undefined
    data: { [key: string]: string }
    edit?: boolean
    showEdit?: boolean
    isNew: boolean
    obsTransformations: { label: string, placeholder: string, description: string }[]
    adder: (name: string, type: ActionType, data: { [key: string]: string }) => void
    remover: (action: { name: string, type: string, data: any }) => void
}


const RedemptionAction = ({
    name,
    type,
    data,
    edit,
    showEdit = true,
    isNew = false,
    obsTransformations = [],
    adder,
    remover
}: RedeemableAction) => {
    const [open, setOpen] = useState(false)
    const [actionName, setActionName] = useState(name)
    const [actionType, setActionType] = useState<{ name: string, value: ActionType } | undefined>(actionTypes.find(a => a.value == type?.toUpperCase()))
    const [actionData, setActionData] = useState<{ [key: string]: string }>(data)
    const [isEditable, setIsEditable] = useState(edit)
    const [isMinimized, setIsMinimized] = useState(!isNew)
    const [oldData, setOldData] = useState<{ n: string, t: ActionType | undefined, d: { [k: string]: string } } | undefined>(undefined)

    function Save(name: string, type: ActionType | undefined, data: { [key: string]: string }, isNew: boolean) {
        // TODO: validation
        if (!name) {
            return
        }
        if (!type) {
            return
        }
        if (!data) {
            return
        }

        let info: any = {
            name,
            type
        }

        info = { ...info, ...data }

        if (isNew) {
            axios.post("/api/settings/redemptions/actions", info)
                .then(d => {
                    adder(name, type, data)
                    setActionName("")
                    setActionType(undefined)
                    setActionData({})
                })
        } else {
            axios.put("/api/settings/redemptions/actions", info)
                .then(d => {
                    setIsEditable(false)
                })
        }
    }

    function Cancel(data: { n: string, t: ActionType | undefined, d: { [k: string]: string } } | undefined) {
        if (!data)
            return

        setActionName(data.n)
        setActionType(actionTypes.find(a => a.value == data.t))
        setActionData(data.d)
        setIsEditable(false)
        setOldData(undefined)
    }

    function Delete() {
        axios.delete("/api/settings/redemptions/actions?action_name=" + name)
            .then(d => {
                remover(d.data)
            })
    }

    return (
        <div
            className="bg-orange-300 p-3 border-2 border-orange-400 rounded-lg w-[830px]">
            {isMinimized &&
                <div
                    className="flex">
                    <Label
                        className="mr-2 grow text-lg align-middle"
                        htmlFor="name">
                        {actionName}
                    </Label>
                    <Button
                        className="flex inline-block self-end"
                        onClick={e => setIsMinimized(!isMinimized)}>
                        {isMinimized ? <Maximize2 /> : <Minimize2 />}
                    </Button>
                </div>
                || !isMinimized &&
                <div>
                    <div
                        className="pb-3">
                        <Label
                            className="mr-2"
                            htmlFor="name">
                            Action name
                        </Label>
                        <Input
                            className="inline-block w-[300px]"
                            id="name"
                            placeholder="Enter a name for this action"
                            onChange={e => setActionName(e.target.value)}
                            value={actionName}
                            readOnly={!isNew} />
                        <Label
                            className="ml-10 mr-2"
                            htmlFor="type">
                            Action type
                        </Label>
                        {!isEditable &&
                            <Input
                                className="inline-block w-[300px] justify-between"
                                name="type"
                                value={actionType?.name}
                                readOnly />
                            || isEditable &&
                            <Popover
                                open={open}
                                onOpenChange={setOpen}>
                                <PopoverTrigger asChild>
                                    <Button
                                        variant="outline"
                                        role="combobox"
                                        aria-expanded={open}
                                        className="w-[300px] justify-between"
                                    >{!actionType ? "Select one..." : actionType.name}</Button>
                                </PopoverTrigger>
                                <PopoverContent>
                                    <Command>
                                        <CommandInput
                                            placeholder="Filter actions..."
                                            autoFocus={true} />
                                        <CommandList>
                                            <CommandEmpty>No action found.</CommandEmpty>
                                            <CommandGroup>
                                                {actionTypes.map((action) => (
                                                    <CommandItem
                                                        value={action.name}
                                                        key={action.value}
                                                        onSelect={(value) => {
                                                            setActionType(actionTypes.find(v => v.name.toLowerCase() == value.toLowerCase()))
                                                            setOpen(false)
                                                        }}>
                                                        {action.name}
                                                    </CommandItem>
                                                ))}
                                            </CommandGroup>
                                        </CommandList>
                                    </Command>
                                </PopoverContent>
                            </Popover>
                        }
                    </div>
                    <div>
                        {actionType && (actionType.value == ActionType.WRITE_TO_FILE || actionType.value == ActionType.APPEND_TO_FILE) &&
                            <div>
                                <Label
                                    className="mr-2"
                                    htmlFor="file_path">
                                    File path
                                </Label>
                                <Input
                                    className="w-[300px] justify-between inline-block"
                                    name="file_path"
                                    placeholder={actionType.value == ActionType.WRITE_TO_FILE ? "Enter the local file path to the file to overwrite" : "Enter the local file path to the file to append to"}
                                    value={actionData["file_path"]}
                                    onChange={e => setActionData({ ...actionData, "file_path": e.target.value })}
                                    readOnly={!isEditable} />
                                <Label
                                    className="ml-10 mr-2"
                                    htmlFor="file_content">
                                    File content
                                </Label>
                                <Input
                                    className="w-[300px] justify-between inline-block"
                                    name="file_content"
                                    placeholder="Enter the content that should be written"
                                    value={actionData["file_content"]}
                                    onChange={e => setActionData({ ...actionData, "file_content": e.target.value })}
                                    readOnly={!isEditable} />
                            </div>
                        }
                        {actionType && actionType.value == ActionType.OBS_TRANSFORM &&
                            <div>
                                {obsTransformations.map(t =>
                                    <div
                                        className="mt-3">
                                        <Label
                                            className="mr-2"
                                            htmlFor={t.label.toLowerCase()}>
                                            {t.label.split("_").map(w => w.substring(0, 1).toUpperCase() + w.substring(1).toLowerCase()).join(" ")}
                                        </Label>
                                        <Input
                                            className="w-[300px] justify-between inline-block"
                                            name={t.label.toLowerCase()}
                                            placeholder={t.placeholder}
                                            value={actionData[t.label]}
                                            onChange={e => {
                                                let c = { ...actionData }
                                                c[t.label] = e.target.value
                                                setActionData(c)
                                            }}
                                            readOnly={!isEditable} />
                                    </div>
                                )}
                            </div>
                        }
                        {actionType && actionType.value == ActionType.AUDIO_FILE &&
                            <div>
                                <Label
                                    className="mr-2"
                                    htmlFor="file_path">
                                    File path
                                </Label>
                                <Input
                                    className="w-[300px] justify-between inline-block"
                                    name="file_path"
                                    placeholder={"Enter the local file path where the audio file is at"}
                                    value={actionData["file_path"]}
                                    onChange={e => setActionData({ ...actionData, "file_path": e.target.value })}
                                    readOnly={!isEditable} />
                            </div>
                        }
                    </div>
                    <div>
                        {isEditable &&
                            <Button
                                className="m-3"
                                onClick={() => Save(actionName, actionType?.value, actionData, isNew)}>
                                {isNew ? "Add" : "Save"}
                            </Button>
                        }
                        {isEditable && !isNew &&
                            <Button
                                className="m-3"
                                onClick={() => Cancel(oldData)}>
                                Cancel
                            </Button>
                        }
                        {showEdit && !isEditable &&
                            <Button
                                className="m-3"
                                onClick={() => {
                                    setOldData({ n: actionName, t: actionType?.value, d: actionData })
                                    setIsEditable(true)
                                }}>
                                Edit
                            </Button>
                        }
                        {!isEditable &&
                            <Button
                                className="m-3 bg-red-500 hover:bg-red-600 align-bottom"
                                onClick={() => Delete()}>
                                <Trash2Icon />
                            </Button>
                        }
                        {!isNew &&
                            <Button
                                className="m-3 align-middle"
                                onClick={e => setIsMinimized(!isMinimized)}>
                                {isMinimized ? <Maximize2 /> : <Minimize2 />}
                            </Button>
                        }
                    </div>
                </div>
            }
        </div>
    );
}

export default RedemptionAction;