import { 
    TOOL_REGISTRY, 
    IMG2IMG_MODEL_FX, 
    IMG2IMG_MODEL_NB, 
    IMG2VID_MODEL_KDP,
    
    VID2SSQ_MODEL_LOCAL,
    VID2SSQ_MODEL_CLOUD

} from "./constants";

// # GLOBAL STATE
export type ToolsContextType = {
    activeIo: IoNames;
    setActiveIo: React.Dispatch<React.SetStateAction<IoNames>>;

    activeToolId: ToolIds;
    setActiveToolId: React.Dispatch<React.SetStateAction<ToolIds>>;

    // tool specific states
    tools: [
        ToolImg2ImgContextState,
        ToolImg2VidContextState,
        ToolVid2SsqContextState
        // add more tools here 
    ]

    // progress object states
    progress: {
        busy: Busy,
        log: LogEntry[],
        updateProgress: (params: UpdateProgressParams) => void,
    };

    // outputs
    outputs: OutputHistoryType[];
    addOutput: (newOutput: OutputHistoryType) => void;

    outputActiveIndex: number;
    setOutputActiveIndex: React.Dispatch<React.SetStateAction<number>>;
    outputActiveSubIndex: number;
    setOutputActiveSubIndex: React.Dispatch<React.SetStateAction<number>>;
    refreshOutputs?: (force?: boolean) => Promise<void>;
    invalidateOutputs?: () => void;    
    errorOutputs: any;
};
export type IoNames = 'input' | 'output';

// # TOOLS 
export type ToolIds = 'img2img' | 'img2vid' | 'vid2ssq'; // also lives in API

// # IMG2IMG
export type Img2ImgModelIds = 'fx' | 'nb'; 

// fx
export type Img2ImgModelContextFx = {
    local: {
        
    };
    input: {
        prompt: string;
        num_images: typeof IMG2IMG_MODEL_FX.config.num_imagesOptions[number]; //1 | 2 | 4
        output_format: typeof IMG2IMG_MODEL_FX.config.output_formatOptions[number]; // 'jpeg' | 'png'
        enhance_prompt: boolean;
        aspect_ratio: typeof IMG2IMG_MODEL_FX.config.aspect_ratioOptions[number]; 
        image_url: string; 
    };
};
// nb
export type Img2ImgModelContextNb = {
    local: {
        
    };
    input: {
        prompt: string;
        image_urls: string[]; 
        num_images: typeof IMG2IMG_MODEL_NB.config.num_imagesOptions[number]; //1 | 2 | 4
        output_format: typeof IMG2IMG_MODEL_NB.config.output_formatOptions[number]; // 'jpeg' | 'png'
        aspect_ratio: typeof IMG2IMG_MODEL_NB.config.aspect_ratioOptions[number]; 
    };
};
export type ToolImg2ImgContextState = {
    id: 'img2img';
    currentModelId: Img2ImgModelIds;
    setCurrentModelId: (id: Img2ImgModelIds) => void;
    models: [
        {
            id: 'fx';
            modelState: Img2ImgModelContextFx;
            setModelState: React.Dispatch<React.SetStateAction<Img2ImgModelContextFx>>;
        },
        {
            id: 'nb',
            modelState: Img2ImgModelContextNb;
            setModelState: React.Dispatch<React.SetStateAction<Img2ImgModelContextNb>>;
        }
    ]
};

// # IMG2VID
export type Img2VidModelIds = 'hlo' | 'kdp';
// export type Img2VidMandatoryModelProps = {
//     id: Img2VidModelIds; // Model ID-slug used internally
//     title: string; // Display name
//     description: string; // Description
//     initialState: any; // add specific state type here
// };

// hlo
export type Img2VidModelContextHlo = {
    local: {
    };
    input: {
        prompt: string;
        image_url: string; 
        prompt_optimizer: boolean;
        end_image_url : string | undefined; 
    };
};
// kdp
export type Img2VidModelContextKdp = {
    local: {
    };
    input: {
        prompt: string;
        image_url: string; 
        duration: typeof IMG2VID_MODEL_KDP.config.durationOptions[number];
        negative_prompt: string;
    };
};
export type ToolImg2VidContextState = {
    id: 'img2vid';
    currentModelId: Img2VidModelIds;
    setCurrentModelId: (id: Img2VidModelIds) => void;
    models: [
    {
        id: 'hlo';
        modelState: Img2VidModelContextHlo;
        setModelState: React.Dispatch<React.SetStateAction<Img2VidModelContextHlo>>;
    },
    {   
        id: 'kdp',
        modelState: Img2VidModelContextKdp;
        setModelState: React.Dispatch<React.SetStateAction<Img2VidModelContextKdp>>;
    }
  ]
};

// vid2ssq
export type Vid2SsqModelIds = 'local' | 'cloud';

// local
export type Vid2SsqModelContextLocal = {
    local: {
    };
    input: {
        video_url: string;  // this is the s3 URL
        prefix: string;
        quality: typeof VID2SSQ_MODEL_LOCAL.config.qualityOptions[number];
        downsize: boolean;
    };
};
// cloud
export type Vid2SsqModelContextCloud = {
    local: {
    };
    input: {
        // prompt: string;
        // image_url: string; 
        // prompt_optimizer: boolean;
        // end_image_url : string; 
    };
};

export type ToolVid2SsqContextState = {
    id: 'vid2ssq';
    currentModelId: Vid2SsqModelIds;
    setCurrentModelId: (id: Vid2SsqModelIds) => void;
    models: [
    {
        id: 'local';
        modelState: Vid2SsqModelContextLocal;
        setModelState: React.Dispatch<React.SetStateAction<Vid2SsqModelContextLocal>>;
    },
    {
        id: 'cloud';
        modelState: Vid2SsqModelContextCloud;
        setModelState: React.Dispatch<React.SetStateAction<Vid2SsqModelContextCloud>>;
    }
  ]
};

// ********* PROGRESS TYPES *********
//
//

export type Busy = false | 'generating' | 'uploading'

export type LogEntry = {
  timestamp: number;
  level: 'info' | 'success' | 'warning' | 'error';
  message: string;
  data?: any;
};

export type UpdateProgressParams =  {
    busy?: Busy,
    log?: {level: LogEntry['level'], message: LogEntry['message'], data?: any}
}
//
//
// ********* OUTPUT TYPES *********
//
//

export type OutputImageType = {
    id: string; // from db
    model_id: Img2ImgModelIds; 
    tool_id: ToolIds; 
    input_object: any // TODO: improve typing?
    //time_submitted: number; // should be from db, but the api do not return it yet
    output_urls: string[];
};
export type OutputVideoType = {
    id: string; // from db
    model_id: Img2VidModelIds; 
    tool_id: ToolIds;     
    input_object: any // TODO: improve typing?
    //time_submitted: number; // should be from db, but the api do not return it yet
    output_urls: string[];
};
export type OutputSsqType = {
    id: string; // made up?
    tool_id: ToolIds; 
    model_id: Vid2SsqModelIds;  // TODO 
    input_object: any // TODO: improve typing?
    //time_submitted: number; // should be from db, but the api do not return it yet
    output_urls: string[]; // ssq file url TODO - nonsense
}
export type OutputType = OutputImageType | OutputVideoType | OutputSsqType;


export type OutputHistoryType = OutputType & {
    // additional fields from db, any key and value combo
    [key: string]: any;
};




// API RESPONSE TYPES - also existing in API repository, when changing, update it there too.
// app\v2\media-tools\types-media-tools.ts
// COPY PASTE STARTS HERE
export type SsqApi = SsqApiSuccess | SsqApiError;
export type SsqApiSuccess = {
    success: true; // mandatory
    
    job_id?: string;            // not really always present, but could be here, dependending on endpoint 
    status?: string;            // not really always present, but could be here, dependending on endpoint
    queue_position?: number;    // not really always present, but could be here, dependending on endpoint and queue status
    logs?: any[];               // not really always present, but could be here, dependending on endpoint, different from LogEntry type
    output_urls?: string[];     // not really always present, but could be here, dependending on endpoint
    timeElapsed?: number;       // not really always present, but could be here, dependending on endpoint
    [key: string]: any;         // any other fields depending on endpoint
    fsPublicData?: FsPublicData;         // optional field for public data
};

export type SsqApiError = {
    success: false; // mandatory
    error: string;  // mandatory
    fsPublicData?: FsPublicData;         // optional field for public data
};
// COPY PASTE ENDS HERE

// New, check and make sure it matches! 
export type FsPublicData = {
    isMatchingSiteId: boolean,
    isMatchinUrl: boolean,
    isMatchingSk: boolean,
    planLimit: {
        plan_id: number,
        name: string,
        usage30dLimit: number
    },
    usage30d: {
        details: {
            media_tools_usage: number,
            blocks_usage: number,
            contanim_usage: number
        },
        usage_total: number,
        usage_remaining: number
    },
    hasCredits: true,
}
