import { useEffect, useMemo, useRef, useState } from '@wordpress/element';
import {
	Button,
    Dropdown,
	DropdownMenu,
	MenuGroup,
	MenuItem,
	Modal,
	Tooltip,
	Popover,
	Flex,
	FlexItem,
	Spinner,
  Notice,
	__experimentalHeading as Heading,
    Icon,
    //@ts-ignore
} from '@wordpress/components';
import {
	download as iconDownload,
	edit as iconEdit,
	info as iconInfo,
	chevronLeft,
	chevronRight,
	page as iconLayers,
	gallery as iconSend,
	image as iconImage,
	video as iconVideo,
	media as iconSsq,
	video as iconPlay,
    title,
    captureVideo,
    capturePhoto,
    chevronDown,
    //@ts-ignore
} from '@wordpress/icons';

import type { OutputHistoryType } from './types';
import { useToolsContext } from './ContextProvider';
import React from 'react';


// --- utils ---
const isVideo = (output: OutputHistoryType) => { return ['img2vid'].includes(output.tool_id) }
const isImage = (output: OutputHistoryType) => { return ['img2img', 'vid2ssq'].includes(output.tool_id) }
const isSsq = (output: OutputHistoryType) => { return ['vid2ssq'].includes(output.tool_id) }

const downloadUrl = (url: string) => {
	const a = document.createElement('a');
	a.href = url;
	a.download = '';
	a.rel = 'noopener';
	document.body.appendChild(a);
	a.click();
	a.remove();
};

type Size = 's' | 'm' | 'l';
type OutputsDProps = {
    size: Size;
    //onEdit?: (output: OutputHistoryType, url?: string) => void;
    onSendTo?: (output: OutputHistoryType, dest: { tool: string , model: string }, url?: string) => void;
    onDownload?: (output: OutputHistoryType, url?: string) => void;
    onAddToCanvas2D?: (output: OutputHistoryType) => void;
};

export default function OutputsD({
    size,
    //onEdit,
    onSendTo,
    onDownload,
    onAddToCanvas2D
}: OutputsDProps) {

    const { outputs, outputActiveIndex, setOutputActiveIndex, outputActiveSubIndex, setOutputActiveSubIndex, errorOutputs } = useToolsContext();

    // modal
    const [ isModalOpen, setIsModalOpen ] = useState(false);

    return (
        <>
            <div style={{display:"flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16, }}>
                <p style={{fontSize: "11px", fontWeight: 500, lineHeight: 1.4, textTransform: "uppercase"}}>Outputs</p>
                <Dropdown
                    popoverProps={ { placement: 'bottom-end', animate: false } }
                    renderToggle={ ( { isOpen, onToggle }: any ) => (
                        <Button
                            icon={ chevronDown }
                            iconPosition="right"
                            variant="tertiary"
                            onClick={ onToggle }
                            aria-expanded={ isOpen }
                        >
                            Recent
                        </Button>
                    ) }
                    renderContent={ ({isOpen, onToggle, onClose}: any) => (
                        <div style={{width: 400, maxHeight: 400, }}>
                          {/* <button onClick={onToggle}>close dropdown</button> */}
                          <OutputsRecent 
                              size={size}
                              onToggle={onToggle}
                          />    
                          {errorOutputs && (
                            <Notice status="error" isDismissible={false} >
                              An error occured: {JSON.stringify( errorOutputs )}
                            </Notice> 
                          )}                            
                        </div>                
                    ) }
                />
            </div>

            {outputActiveIndex === -1 ? (
                <>
                    <div 
                        // to match the height of the outputs preview below
                        style={{ 
                            padding: 16, 
                            textAlign: 'center', 
                            color: '#888', 
                            width: '100%', 
                            //aspectRatio: '1 / 1', 
                            height: 450,
                            display: 'flex', 
                            alignItems: 'center', 
                            justifyContent: 'center' 
                        }}
                    >

                        No recent outputs. Use generator on the left, or select from the recent outputs above.

                    </div>
                    <div style={{height: 53}}/> {/* to match the height of the actions bar below */}
                </>
            ) : (
                <>
                    <OutputPreview 
                      setIsModalOpen={setIsModalOpen} 
                      height={"450px"} 
                    />
                    <ActionsBar
                        //onEdit={//onEdit}
                        onSendTo={onSendTo}
                        onDownload={onDownload}
                        onAddToCanvas2D={onAddToCanvas2D}
                        // setIsModalOpen={undefined} // not needed here, because it is already closed when performing actions in this instance
                    />   
                </>
            )}

            { isModalOpen && (
                <Modal title="Output" onRequestClose={ () => setIsModalOpen( false ) } overlayClassName="ssq-full-h-modal" isFullScreen>
                   <style>{`
                     .ssq-full-h-modal .components-modal__content > div:nth-child(2) { height: 100%!important; }
                   `}</style>                  
                      <OutputPreview 
                        //setIsModalOpen={undefined} // not needed here, because it is already opened
                        height={"calc(100% - 100px)"}
                      />
                      <ActionsBar
                          //onEdit={//onEdit}
                          onSendTo={onSendTo}
                          onDownload={onDownload}
                          onAddToCanvas2D={onAddToCanvas2D}
                          setIsModalOpen={setIsModalOpen} // is needed here to close the modal after action
                      />   
                </Modal>
            ) }

        </>
    )
}


function OutputPreview({ height, setIsModalOpen }: { height: string; setIsModalOpen?: React.Dispatch<React.SetStateAction<boolean>> }) {
    const { outputs, outputActiveIndex, setOutputActiveIndex, outputActiveSubIndex, setOutputActiveSubIndex } = useToolsContext();
    // get the selected output and subindex url
    const output = outputs[outputActiveIndex];
    const currentUrl = output?.output_urls[outputActiveSubIndex] || '';

    // multiple
    const multiple = output.output_urls.length;    // !!! THROWING ERROR HERE SOMETIMES

    const mediaRef = useRef<HTMLVideoElement | HTMLImageElement | null>(null);
    const [videoReady, setVideoReady] = useState(false);

	const handleMouseEnter = () => {
		const el = mediaRef.current as HTMLVideoElement | null;
		if (el && 'play' in el) {
			el.muted = true;
			el.play().catch(() => {});
		}
	};
	const handleMouseLeave = () => {
		const el = mediaRef.current as HTMLVideoElement | null;
		if (el && 'pause' in el) el.pause();
		//if (el) el.currentTime = 0;
	};
	const handleVideoLoaded = () => setVideoReady(true);

    const handleNextSubOutput = () => {
        console.log('next sub output');
        // increment subindex
        setOutputActiveSubIndex( (prev) => prev + 1 );
    }
    const handlePreviousSubOutput = () => {
        console.log('previous sub output');
        // decrement subindex
        setOutputActiveSubIndex( (prev) => prev - 1 );
    }

    
 
    return (
        <>
            <div
                onMouseEnter={handleMouseEnter}
                onMouseLeave={handleMouseLeave}
                onClick={ ()=> setIsModalOpen && setIsModalOpen(true) }
                style={{
                    position: 'relative',
                    width: '100%',
                    height: height,
                    display: 'block',
                    padding: 0,
                    border: 0,
                    background: 'transparent',
                }}            
            >
                {
                    isVideo(output) && (
                    <>
                        {!videoReady && (
                            <div
                                style={{
                                    position: 'absolute',
                                    inset: 0,
                                    display: 'flex',
                                    alignItems: 'center',
                                    justifyContent: 'center',
                                    background: '#222',
                                    color: '#fff',
                                    zIndex: 2,
                                }}
                            >
                                <span
                                    style={{
                                        fontSize: 32,
                                        opacity: 0.7,
                                        display: 'flex',
                                        alignItems: 'center',
                                        justifyContent: 'center',
                                    }}
                                >
                                    {iconPlay}
                                </span>
                            </div>
                        )}
                        <video
                            ref={mediaRef as any}
                            preload="metadata"
                            playsInline
                            muted
                            poster={undefined}
                            src={currentUrl}
                            style={{
                                position: 'absolute',
                                inset: 0,
                                width: '100%',
                                height: '100%',
                                objectFit: 'contain',
                                opacity: videoReady ? 1 : 0,
                                transition: 'opacity 0.2s',
                            }}
                            onLoadedMetadata={handleVideoLoaded}
                            tabIndex={-1}
                        />
                    </>             
                )}
                { isImage(output) && (
                    <>
                            <img
                                ref={mediaRef as any}
                                src={currentUrl}
                                //alt={output.prompt_ref || output.id}
                                loading="lazy"
                                style={{
                                    position: 'absolute',
                                    inset: 0,
                                    width: '100%',
                                    height: '100%',
                                    objectFit: 'contain',
                                }}
                            />                
                    </>
                )}
            </div>
            { multiple > 1 && (
                <div style={{ position: 'relative', height: '40px'}}>
                    {/* Next Sub Output Button */}
                    <div style={{ position: 'absolute', bottom: 8, right: 8, zIndex: 3, display: 'flex', gap: 4 }}>
                        <Button
                            icon={chevronRight}
                            label="Next"
                            disabled={outputActiveSubIndex >= (output.output_urls.length - 1)}
                            onClick={handleNextSubOutput}
                        />
                    </div>
                    { /* Previous Sub Output Button */}
                    <div style={{ position: 'absolute', bottom: 8, left: 8, zIndex: 3, display: 'flex', gap: 4 }}>
                        <Button
                            icon={chevronLeft}
                            label="Previous"
                            disabled={outputActiveSubIndex <= 0}
                            onClick={handlePreviousSubOutput}
                        />
                    </div>
                    {/* Output Count (bottom center) */}
                    <div style={{ position: 'absolute', bottom: 8, left: '50%', transform: 'translateX(-50%)', zIndex: 3, display: 'flex', gap: 4 }}>
                        <span>{outputActiveSubIndex + 1} / {output.output_urls.length}</span>
                    </div>
                </div>
            )} 
        </>
    )
}

// --- Card Actions ---
function ActionsBar({
    onEdit,
    onSendTo,
    onDownload,
    onAddToCanvas2D,
    setIsModalOpen
}: {
    onEdit?: (o: OutputHistoryType, url?: string) => void;
    onSendTo?: (o: OutputHistoryType, dest: { tool: string; model: string }, url?: string) => void;
    onDownload?: (o: OutputHistoryType, url?: string) => void;
    onAddToCanvas2D?: (o: OutputHistoryType) => void;
    setIsModalOpen?: React.Dispatch<React.SetStateAction<boolean>>;
}) {
    const { outputs, outputActiveIndex, outputActiveSubIndex, activeIo } = useToolsContext();
    // get the selected output and subindex url
    const output = outputs[outputActiveIndex];
    const currentUrl = output?.output_urls[outputActiveSubIndex] || '';

    const [showJson, setShowJson] = useState(false);
    const infoButtonRef = useRef<HTMLButtonElement | null>(null);

    const sendToArrayImage = [
        {tool:'img2img', model: 'fx', title: 'Image to Image - Flux Kontext'},
        {tool:'img2img', model: 'nb', title: 'Image to Image - Nano Banana'},
        {tool:'img2vid', model: 'hlo', title: 'Image to Video - Hailuo'},
        {tool:'img2vid', model: 'kdp', title: 'Image to Video - Kling'},
        //{tool:'vid2ssq', model: 'local', title: 'Video to SSQ (Local Model)'}
    ]

    const sendToArrayVideo = [
        {tool:'vid2ssq', model: 'local', title: 'Video to SSQ (Local Model)'}
    ]

    return (
        <div
            role="group"
            aria-label="actions"
            style={{
                display: 'flex',
                justifyContent: 'space-evenly',
                alignItems: 'center',
                gap: 6,
                padding: 8,
                background: '#fafafa',
            }}
        >
            <Button
                icon={iconDownload}
                label="Download"
                showTooltip
                onClick={() => {
                  onDownload ? onDownload(output, currentUrl) : currentUrl ? downloadUrl(currentUrl) : undefined
                  setIsModalOpen && setIsModalOpen(false);
                }}
                style={{ flex: 1, minWidth: 0 }}
            />
        
            {/* 
              // Not sure if we need Edit button here, as we have Send to which covers more use cases
              <Button 
                icon={iconEdit} 
                label="Edit" 
                showTooltip
                onClick={() => {
                  onEdit?.(output, currentUrl)
                  setIsModalOpen && setIsModalOpen(false);
                }}
                style={{ flex: 1, minWidth: 0 }} 
            /> */}
            { isSsq(output) && (
                  <>
                    <Button
                        variant="primary"
                        onClick={() => {
                          onAddToCanvas2D?.(output);
                          setIsModalOpen && setIsModalOpen(false);
                        }}
                      >
                        Add to Canvas 2D
                    </Button>
                  </>
            )}
            <DropdownMenu
                icon={iconSend}
                label="Send to"
                toggleProps={{ 
                  'aria-label': 'Send to', 
                  style: { flex: 1, minWidth: 0 }, 
                  variant:`${ isSsq(output) ? "secondary" : (activeIo === "output" ? "primary" : "secondary") }`, 
                  children: 'Send to' 
                }}
                popoverProps={{ placement: 'bottom-start' }}
            >
                {({ onClose }: any) => (
                    <MenuGroup label="Destinations">
                        {isImage(output) &&
                            <>
                                {sendToArrayImage.map(dest => (
                                    <MenuItem
                                        key={dest.tool}
                                        onClick={() => {
                                            onSendTo?.(output, { tool: dest.tool, model: dest.model }, currentUrl);
                                            onClose();
                                            setIsModalOpen && setIsModalOpen(false);
                                        }}
                                    >
                                        {dest.title}
                                    </MenuItem>
                                ))}                       
                            </>
                        }
                        {isVideo(output) &&
                            <>
                                {sendToArrayVideo.map(dest => (
                                    <MenuItem
                                        key={dest.tool}
                                        onClick={() => {
                                            onSendTo?.(output, { tool: dest.tool, model: dest.model }, currentUrl);
                                            onClose();
                                            setIsModalOpen && setIsModalOpen(false);
                                        }}
                                    >
                                        {dest.title}
                                    </MenuItem>
                                ))}
                            </>
                        }
                    </MenuGroup>
                )}
            </DropdownMenu>
            <Button
                ref={infoButtonRef}
                icon={iconInfo}
                label="Show JSON"
                showTooltip
                onClick={() => setShowJson(s => !s)}
                aria-expanded={showJson}
                aria-haspopup="dialog"
                style={{ flex: 1, minWidth: 0 }}
            />
            {showJson && infoButtonRef.current && (
                <Popover anchor={infoButtonRef.current} onClose={() => setShowJson(false)} placement="bottom-end">
                    <div style={{ minWidth: 400, maxWidth: 600, maxHeight: 360, overflow: 'auto', padding: 8 }}>
                        <Heading level={6}>Raw Output</Heading>
                        <pre style={{ whiteSpace: 'pre-wrap', overflowWrap: 'anywhere', fontSize: 12 }}>
                            {JSON.stringify(output, null, 2)}
                        </pre>
                    </div>
                </Popover>
            )}
        </div>
    );
}


function OutputsRecent({
    size, // not sure size is relevant (this was in the outputs panel, now it is in a dropdown)
    onToggle

}: { 
    size: Size;
    onToggle: () => void;
}){

    const { outputs, outputActiveIndex, setOutputActiveIndex, outputActiveSubIndex, setOutputActiveSubIndex, refreshOutputs } = useToolsContext();
    const columns = size === 's' ? 2 : size === 'm' ? 3 : 4;

    const [ loading, setLoading ] = useState(false);

    // fetch when gallery is actually mounted (i.e. dropdown opened)
    useEffect(() => {
        // non-forced fetch will use cache window in the store
        refreshOutputs?.().catch(() => {});
    }, []); // run only on mount

    return (
        <>
            <div
                style={{
                    display: 'grid',
                    gridTemplateColumns: `repeat(${columns}, 1fr)`,
                    gap: 8,
                    //padding: 8,
                    width: '100%',
                    
                    overflowY: 'auto',
                    overflowX: 'hidden', // !!! TODO: bug, wrong size, does not respect 100% width of parent
                    height: 300,
                }}
            >
                {outputs.map((o: OutputHistoryType, i: number) => (
                    <OutputCard
                        key={i}
                        index={i}
                        // selectedIndex={selectedIndex}
                        // output={o}
                        onClick={(o:OutputHistoryType) => {
                            console.log('output card clicked', o);
                            // set selected index
                            const index = outputs.findIndex(out => out.id === o.id);
                            setOutputActiveIndex(index);
                            onToggle(); // closes dropdown
                        }}
                    />
                ))}
                { loading && (
                    <div
                        style={{
                            gridColumn: 'span 4',
                            textAlign: 'center',
                            padding: 16,
                            color: 'gray',
                        }}
                    >
                        Loading outputs...
                    </div>
                )}
            </div>
        </>
    )
}

function OutputCard({
    index,
    onClick
}: {
    index: number;
    onClick: (o: OutputHistoryType) => void;
}){
    const { outputs } = useToolsContext();
    console.log('OutputCard rendering index:', index);
    const output = outputs[index];

    // get first url
    const url = output.output_urls[0] || ''; // !!! TODO: Throwing error sometimes

    // multiple
    const multiple = output.output_urls.length;

    // hover video play
    const mediaRef = useRef<HTMLVideoElement | HTMLImageElement | null>(null);
    const [videoReady, setVideoReady] = useState(false);

	const handleMouseEnter = () => {
		const el = mediaRef.current as HTMLVideoElement | null;
		if (el && 'play' in el) {
			el.muted = true;
			el.play().catch(() => {});
		}
	};
	const handleMouseLeave = () => {
		const el = mediaRef.current as HTMLVideoElement | null;
		if (el && 'pause' in el) el.pause();
		//if (el) el.currentTime = 0;
	};
	const handleVideoLoaded = () => setVideoReady(true);


    return (
        <div
            onClick={() => onClick(output)}
            onMouseEnter={handleMouseEnter}
            onMouseLeave={handleMouseLeave}            
            style={{
                position: 'relative',
                width: '100%',
                aspectRatio: '1 / 1',
                display: 'block',
                cursor: 'pointer',
            }}
        >
            { isImage(output) && (
                <>
                    <img src={url} alt={output.input_object?.prompt} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                    <div style={{
                        position: 'absolute',
                        top: 4,
                        left: 4,
                        background: 'rgba(0, 0, 0, 0.5)',
                        color: 'white',
                        fill: 'white',
                        padding: '2px 4px',
                        borderRadius: 4,
                        fontSize: 12,

                        display: 'flex', 
                        alignItems: 'center',
                        justifyContent: 'center',
                        

                    }}>
                        <Icon icon={capturePhoto} size={16} /> <span>{multiple ? multiple : null}</span>
                    </div>
                </>
            )}
            { isVideo(output) && (
                <>
                    <video 
                        ref={mediaRef as any}
                        preload="metadata"
                        playsInline
                        muted
                        loop
                        poster={undefined}
                        src={url} 
                        style={{ width: '100%', height: '100%', objectFit: 'cover' }} 
                        onLoadedMetadata={handleVideoLoaded}
                        tabIndex={-1}                        
                    />
                    <div style={{
                        position: 'absolute',
                        top: 4,
                        left: 4,
                        background: 'rgba(0, 0, 0, 0.5)',
                        color: 'white',
                        fill: 'white',
                        padding: '2px 4px',
                        borderRadius: 4,
                        fontSize: 12,
                    }}>
                        <Icon icon={captureVideo} size={16} />
                    </div>                    
                </>
            )}
        </div>
    );
}

/*

const outputsExample = 
[
  {
    "id": "f22cfb17-ba2b-4fea-bd48-f7caca073ebd",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "make it blue ish filter",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/13-40135126-mt-08-76407467-mt-sync-0.png",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 20,
    "prompt_ref": "make it blue ish filter",
    "time_submitted": "2025-10-13T09:08:58.945Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-32950081-mt-f22cfb17-ba2b-4fea-bd48-f7caca073ebd-0.jpg"
    ]
  },
  {
    "id": "c93d813d-efe7-4699-a8de-404a6d6ad1b7",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "make jesus like statue",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/13-39127162-mt-screenshot2025-09-25220414.png",
      "num_images": 4,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 80,
    "prompt_ref": "make jesus like statue",
    "time_submitted": "2025-10-13T08:52:21.700Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-39151538-mt-c93d813d-efe7-4699-a8de-404a6d6ad1b7-0.jpg",
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-39153585-mt-c93d813d-efe7-4699-a8de-404a6d6ad1b7-1.jpg",
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-39155211-mt-c93d813d-efe7-4699-a8de-404a6d6ad1b7-2.jpg",
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-39156518-mt-c93d813d-efe7-4699-a8de-404a6d6ad1b7-3.jpg"
    ]
  },
  {
    "id": "a344202d-7aa2-45fa-9828-504d032ed28b",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "make it look like ancient mayans designed this image ",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/13-38995441-mt-screenshot2025-09-21203629.png",
      "num_images": 4,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 80,
    "prompt_ref": "make it look like ancient mayans designed this image ",
    "time_submitted": "2025-10-13T08:50:12.134Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-39022588-mt-a344202d-7aa2-45fa-9828-504d032ed28b-0.jpg",
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-39024838-mt-a344202d-7aa2-45fa-9828-504d032ed28b-1.jpg",
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-39026203-mt-a344202d-7aa2-45fa-9828-504d032ed28b-2.jpg",
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-39027438-mt-a344202d-7aa2-45fa-9828-504d032ed28b-3.jpg"
    ]
  },
  {
    "id": "e8d6cda6-eee2-4c8b-87f5-3f05ef72e3dc",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "helloxxxxxx",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/13-35352872-mt-lightenedversion.jpg",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 20,
    "prompt_ref": "helloxxxxxx",
    "time_submitted": "2025-10-13T07:49:16.611Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/13-35369763-mt-e8d6cda6-eee2-4c8b-87f5-3f05ef72e3dc-0.jpg"
    ]
  },
  {
    "id": "3e7a9e76-adac-43bc-8dab-f431932e89f3",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "hello world",
      "image_url": "",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "IN_PROGRESS",
    "cost_int": null,
    "prompt_ref": "hello world",
    "time_submitted": "2025-10-12T19:08:48.291Z",
    "output_urls": []
  },
  {
    "id": "366637bf-709e-4737-9ccf-c9943bc7de23",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "hello world",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/12-75909838-mt-chatgptimageaug122025031701pm.png",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 20,
    "prompt_ref": "hello world",
    "time_submitted": "2025-10-12T19:05:13.185Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/12-68722587-mt-366637bf-709e-4737-9ccf-c9943bc7de23-0.jpg"
    ]
  },
  {
    "id": "c790712d-5327-4be0-911d-e773abaa0f6c",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "hello world",
      "image_url": "",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "IN_PROGRESS",
    "cost_int": null,
    "prompt_ref": "hello world",
    "time_submitted": "2025-10-12T19:03:26.008Z",
    "output_urls": []
  },
  {
    "id": "6a2c80c4-d8d0-4817-b0f8-9c4d274dd631",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "sdf",
      "image_url": "",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "IN_PROGRESS",
    "cost_int": null,
    "prompt_ref": "sdf",
    "time_submitted": "2025-10-12T19:01:00.248Z",
    "output_urls": []
  },
  {
    "id": "e11db357-d131-4b6c-bd8d-f5041aa80ade",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "sdf",
      "image_url": "",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "IN_PROGRESS",
    "cost_int": null,
    "prompt_ref": "sdf",
    "time_submitted": "2025-10-12T19:00:05.524Z",
    "output_urls": []
  },
  {
    "id": "79161a4f-b031-408a-82db-d587af656414",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "make it green",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/12-53158708-mt-logoblack.png",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 20,
    "prompt_ref": "make it green",
    "time_submitted": "2025-10-12T12:46:02.563Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/12-53173603-mt-79161a4f-b031-408a-82db-d587af656414-0.jpg"
    ]
  },
  {
    "id": "bf838c5c-b095-4555-98be-8a098348f938",
    "tool_id": "img2vid",
    "model_id": "kdp",
    "input_object": {
      "prompt": "nazdar",
      "duration": 10,
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-83041889-mt-lightenedversion.jpg",
      "negative_prompt": "motion blur, blur, distort, and low quality"
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 250,
    "prompt_ref": "nazdar",
    "time_submitted": "2025-10-10T08:09:52.374Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/10-36755016-mt-bf838c5c-b095-4555-98be-8a098348f938-0.mp4"
    ]
  },
  {
    "id": "34cb5cf0-9ec3-48f3-a763-eb623482897a",
    "tool_id": "img2vid",
    "model_id": "kdp",
    "input_object": {
      "prompt": "all hell breaks loose",
      "duration": 10,
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-83041889-mt-lightenedversion.jpg",
      "negative_prompt": "motion blur, blur, distort, and low quality"
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 250,
    "prompt_ref": "all hell breaks loose",
    "time_submitted": "2025-10-09T21:04:18.638Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/09-83222816-mt-34cb5cf0-9ec3-48f3-a763-eb623482897a-0.mp4"
    ]
  },
  {
    "id": "79c24bb6-7b7b-49ad-9abb-cd558cd3246d",
    "tool_id": "img2vid",
    "model_id": "hlo",
    "input_object": {
      "prompt": "",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-56689106-mt-takschvalne.jpg",
      "end_image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-56710165-mt-lightenedversion.jpg",
      "prompt_optimizer": true
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 250,
    "prompt_ref": "",
    "time_submitted": "2025-10-09T15:44:10.933Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/09-64144521-mt-79c24bb6-7b7b-49ad-9abb-cd558cd3246d-0.mp4"
    ]
  },
  {
    "id": "115e8a8f-3d2a-4c1b-95a7-02dc41e868bd",
    "tool_id": "img2vid",
    "model_id": "hlo",
    "input_object": {
      "prompt": "",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-56689106-mt-takschvalne.jpg",
      "end_image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-56710165-mt-lightenedversion.jpg",
      "prompt_optimizer": true
    },
    "site_id": "267239812",
    "status": "IN_PROGRESS",
    "cost_int": null,
    "prompt_ref": "",
    "time_submitted": "2025-10-09T15:06:59.272Z",
    "output_urls": []
  },
  {
    "id": "9bc609a3-fbba-4c95-9b2f-dfd9f8db5160",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "make it green",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-61445794-mt-lightenedversion.jpg",
      "num_images": 1,
      "output_format": "png",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 20,
    "prompt_ref": "make it green",
    "time_submitted": "2025-10-09T15:05:06.662Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/09-61517986-mt-9bc609a3-fbba-4c95-9b2f-dfd9f8db5160-0.png"
    ]
  },
  {
    "id": "f6f2ba5b-36ba-41a2-9679-499ec716c529",
    "tool_id": "img2img",
    "model_id": "fx",
    "input_object": {
      "prompt": "make it green",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-61445794-mt-lightenedversion.jpg",
      "num_images": 1,
      "output_format": "jpeg",
      "enhance_prompt": false
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 20,
    "prompt_ref": "make it green",
    "time_submitted": "2025-10-09T15:04:09.591Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/09-61460771-mt-f6f2ba5b-36ba-41a2-9679-499ec716c529-0.jpg"
    ]
  },
  {
    "id": "e20bf85c-090a-4b62-82de-5efe35d3baa4",
    "tool_id": "img2vid",
    "model_id": "hlo",
    "input_object": {
      "prompt": "",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-56689106-mt-takschvalne.jpg",
      "end_image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-56710165-mt-lightenedversion.jpg",
      "prompt_optimizer": true
    },
    "site_id": "267239812",
    "status": "IN_PROGRESS",
    "cost_int": null,
    "prompt_ref": "",
    "time_submitted": "2025-10-09T14:44:25.030Z",
    "output_urls": []
  },
  {
    "id": "32ad8ba7-3b7a-4000-a4bb-8bccc8460298",
    "tool_id": "img2vid",
    "model_id": "hlo",
    "input_object": {
      "prompt": "",
      "image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-56689106-mt-takschvalne.jpg",
      "end_image_url": "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-56710165-mt-lightenedversion.jpg",
      "prompt_optimizer": true
    },
    "site_id": "267239812",
    "status": "IN_PROGRESS",
    "cost_int": null,
    "prompt_ref": "",
    "time_submitted": "2025-10-09T13:45:18.893Z",
    "output_urls": []
  },
  {
    "id": "4525e1c9-1c20-4f20-a60c-e110fa85cc16",
    "tool_id": "img2img",
    "model_id": "nb",
    "input_object": {
      "prompt": "make a photo of the bird driving the car down the california coastline",
      "image_urls": [
        "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-48112334-mt-nano-banana-edit-input-2.png",
        "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-54258821-mt-a0.jpg"
      ],
      "num_images": 1,
      "output_format": "jpeg"
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 20,
    "prompt_ref": "make a photo of the bird driving the car down the california coastline",
    "time_submitted": "2025-10-09T13:04:25.583Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/09-54280861-mt-4525e1c9-1c20-4f20-a60c-e110fa85cc16-0.jpg"
    ]
  },
  {
    "id": "078d80d7-7170-4851-88f0-293c0f9b2c42",
    "tool_id": "img2img",
    "model_id": "nb",
    "input_object": {
      "prompt": "make a photo of the man driving the car down the california coastline",
      "image_urls": [
        "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-48112334-mt-nano-banana-edit-input-2.png",
        "https://scrollsequence-v2-uploads.s3.us-east-1.amazonaws.com/2025-10/09-48246069-mt-aleskozelsky.jpg"
      ],
      "num_images": 1,
      "output_format": "jpeg"
    },
    "site_id": "267239812",
    "status": "COMPLETED",
    "cost_int": 20,
    "prompt_ref": "make a photo of the man driving the car down the california coastline",
    "time_submitted": "2025-10-09T12:01:30.111Z",
    "output_urls": [
      "https://scrollsequence-v2-outputs.s3.us-east-1.amazonaws.com/2025-10/09-50504068-mt-078d80d7-7170-4851-88f0-293c0f9b2c42-0.jpg"
    ]
  },
  {
    "id": "b5af87ea-3d0b-418d-b03d-fbfd1f5c0fb4",
    "tool_id": "img2vid",
    "model_id": "hlo",
    "input_object": {
      "prompt": "",
      "image_url": "",
      "num_videos": 1,
      "video_length": 10,
      "output_format": "mp4"
    },
    "site_id": "267239812",
    "status": "starting",
    "cost_int": null,
    "prompt_ref": "",
    "time_submitted": "2025-10-09T12:01:17.773Z",
    "output_urls": []
  }
]




*/