import React, { useState, } from "react";
import { makeStyles, createStyles } from "@mui/styles";
import { toast } from "react-toastify" 

import { 
	Tooltip,
	Chip,
	Typography,
	IconButton,

	Avatar,
	AvatarGroup,
} from "@mui/material"

import {
	ErrorOutline as ErrorOutlineIcon,
} from "@mui/icons-material"

import {
	green,
	yellow,
	red,
	grey,
} from "../views/AngularWorkflow.jsx"

import WorkflowTemplatePopup2 from "../components/WorkflowTemplatePopup2.jsx"
import { validateJson, GetIconInfo } from "../views/Workflows2.jsx";
import theme from "../theme.jsx";
const itemHeight = 24

export const getParentNodes = (workflow, action, count) => {
	if (count === undefined) {
		count = 0
	}

	// 50 levels of parent nodes
	if (count > 50) {
		return []
	}

    if (action === undefined || action === null) {
      return []
    }

	if (workflow.actions === undefined || workflow.actions === null) {
		workflow.actions = []
	}

	if (workflow.triggers === undefined || workflow.triggers === null) {
		workflow.triggers = []
	}

	if (workflow.branches === undefined || workflow.branches === null) {
		workflow.branches = []
	}

    var allkeys = [action.id];
    var handled = [];
    var results = [];

    // maxiter = max amount of parent nodes to loop
    // also handles breaks if there are issues
    var iterations = 0;
    var maxiter = 10;
    while (true) {
      for (let parentkey in allkeys) {
		if (allkeys[parentkey] === undefined) {
			continue
		}

		var currentnode = workflow.actions.find((element) => element.id === allkeys[parentkey])
		if (currentnode === undefined) {
			currentnode = workflow.triggers.find((element) => element.id === allkeys[parentkey])

			if (currentnode === undefined) {
				//console.log("Could not find parent node for: ", allkeys[parentkey])
				continue
			}
		}

	    if (handled.includes(currentnode.id)) {
	      continue
	    } else {
	      handled.push(currentnode.id);
	      results.push(currentnode);
	    }

        // Get the name / label here too?
        if (currentnode.length === 0) {
          continue;
        }

		// FIXME: recursion
		var incomingEdges = []
		for (var branchkey in workflow.branches) {
			const branch = workflow.branches[branchkey]
			if (branch.destination_id !== currentnode.id) {
				continue
			}

			// FIXME: Go up in the levels
			// This somehow creates infinite recursion for now, so 
			// we are skipping it.
			// This function is also not used for cytoscape recursion,
			// so it doesn't matter much (yet)
			/*
			const parents = getParentNodes(workflow, {
				id: branch.source_id,
			}, count+1)
			if (parents.length > 0) {
				incomingEdges = incomingEdges.concat(parents)
			}
			*/

			incomingEdges.push(branch)
		}

        for (let i = 0; i < incomingEdges.length; i++) {
          var tmp = incomingEdges[i];
          if (tmp.decorator === true) {
            continue
          }

          if (!allkeys.includes(tmp.source_id)) {
            allkeys.push(tmp.source_id)
          }
        }
      }

      if (results.length === allkeys.length || iterations === maxiter) {
        break
      }

      iterations += 1
    }

    // Remove on the end as we don't want to remove everything
    results = results.filter((data) => data.id !== action.id)
    results = results.filter((data) => data.type === "ACTION" || data.app_name === "Shuffle Workflow" || data.app_name === "User Input" || data.app_name === "shuffle-subflow")
    results.push({ label: "Execution Argument", type: "INTERNAL" })

    return results
}

const WorkflowValidationTimeline = (props) => {
	const { globalUrl, userdata, workflow, originalWorkflow, apps, getParents, execution, showHoverColor, } = props

	const [hovering, setHovering] = useState(false)
	const [decidedColor, setDecidedColor] = useState(grey)
	const [isClicked, setIsClicked] = useState(false)

	const showMiddle = false
	if (workflow === undefined || workflow === null) {
		return null
	}

	if (workflow.validation === undefined || workflow.validation === null) {
		return null
	}

	if (workflow.actions === undefined || workflow.actions === null) {
		workflow.actions = []
	}

	if (workflow.triggers === undefined || workflow.triggers === null) {
		workflow.triggers = []	
	}

	if (workflow.branches === undefined || workflow.branches === null) {
		workflow.branches = []	
	}

	var results = []
	if (execution !== undefined) {
		results = execution.results
	}

	// 1. Find startnode
	// 2. Map childnodes from it
	var startnodeId = workflow.start	

	if (execution !== undefined && execution !== null) {
		startnodeId = execution.start
	}

	// Find parent of startnodeId and if it's a webhook
	var relevantactions = []
	for (var key in workflow.branches) {
		const branch = workflow.branches[key]
		if (branch.destination_id !== startnodeId) {
			continue
		}

		for (var triggerkey in workflow.triggers) {
			const trigger = workflow.triggers[triggerkey]
			if (trigger.trigger_type !== "WEBHOOK") {
				continue
			}

			if (trigger.id === branch.source_id) {
				trigger.order = -1
				relevantactions.push(trigger)
				break
			}
		}
	}

	for (var key in workflow.actions) {
		const action = workflow.actions[key]
		if (action.id === startnodeId) {
			action.order = 0
			relevantactions.push(action)
			continue
		}

		var parents = []
		if (getParents !== undefined) {
			parents = getParents(action)
		} else {
			parents = getParentNodes(workflow, action)
		}

		if (action.app_name === "Integration Framework" || action.app_name === "Integration") {
			for (var paramkey in action.parameters) {
				const param = action.parameters[paramkey]
				if (param.name === "app_name") {
					action.app_name = param.value.charAt(0).toUpperCase() + param.value.slice(1)
				}
			}
		}

		if (parents !== undefined && parents !== null && parents.length > 0) {
			const parentfound = parents.find((element) => element.id === startnodeId)
			if (parentfound !== undefined) {

				// FIXME: add order here based on how many steps away from the startnode
				// This just has the parent count
				action.order = parents.length

				relevantactions.push(action)
			}
		}
	}

	if (getParents === undefined) {
		var newactions = []
		for (var key in workflow.triggers) {
			const trigger = workflow.triggers[key]
			if (trigger.trigger_type !== "SUBFLOW" && trigger.trigger_type !== "USERINPUT") {
				continue
			}

			for (var branchkey in workflow.branches) {
				const branch = workflow.branches[branchkey]

				// Checking for OUTBOUND branches from it. 
				// This will mean it's NOT the last node and is easy to visualize
				if (branch.source_id !== trigger.id) {
					continue
				}

				trigger.order = 2
			}


			// Just in case (:
			if (workflow.actions.find((element) => element.id === trigger.id) === undefined) {
				newactions.push(trigger)
				//workflow.actions.push(trigger)
			}
		}

		relevantactions.push(...newactions)
	}

	if (relevantactions.length <= 1) {
		return null
	}

	// Sort according to how many parents a node has. MAY be wrong~
	relevantactions.sort((a, b) => {
		if (a.order === undefined) {
			return 1
		}

		if (b.order === undefined) {
			return -1
		}

		return a.order - b.order
	})

	// FIXME: Add other relevant items as well from subflows (?)
	var nodecolor = grey
	var branchcolor = grey
	var skipped = false

	var previousTools = false
	var scheduleNotStarted = false

	if (workflow.validation !== undefined && workflow.validation !== null && workflow.validation.validation_ran === false) {
		//console.log("Validation didn't run or get set for workflow. Why?")
		return null
	}

	if (workflow.validation !== undefined && workflow.validation !== null && workflow.validation.errors !== undefined && workflow.validation.errors !== null && workflow.validation.errors.length > 0) {
		var newErrors = []
		for (var key in workflow.validation.errors) {
			const error = workflow.validation.errors[key]
			if (error.type === "SCHEDULE") {
				scheduleNotStarted = true 
				continue
			}

			newErrors.push(error)
		}

		workflow.validation.errors = newErrors
	}

	// Use this variable to control visualization
	//const showMiddle = false
	// border: workflow.validation.valid ? `2px solid ${green}` : "1px solid rgba(255,255,255,0.4)",
	var middleError = ""
	var startBranchColor = ""
	var middleBranchColor = ""


	const showHoverForClick = showHoverColor === true ? true : false
	return (
		<div 
			style={{ 
				padding: "10px 5px 10px 5px", 
				borderRadius: theme.palette?.borderRadius, 

				border: hovering === true && showHoverForClick === true ? `1px solid ${decidedColor}` : "1px solid rgba(255,255,255,0.0)",
				cursor: hovering === true && showHoverForClick === true ? "pointer" : "default",
			}}
			onMouseEnter={() => {
				if (isClicked === false) {
					setHovering(true)
				}
			}}
			onMouseLeave={() => {
				if (isClicked === false) {
					setHovering(false)
				}
			}}
			onClick={() => {
				if (showHoverForClick === true) {
					setIsClicked(true)
				}
			}}
		>

			{isClicked === false ? null :
				<WorkflowTemplatePopup2 
					globalUrl={globalUrl}
					userdata={userdata}

					isModalOpenDefault={isClicked}
					workflowBuilt={true}
					setIsClicked={setIsClicked}
					inputWorkflowId={workflow.id}	
				/>
			}

			<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}> 

			  {scheduleNotStarted === true ?  
				  null
			  : null}

			  {relevantactions.map((action, index) => {
				action.result = {}
				if (results !== undefined) {
					const foundResult = results.find((element) => element.action.id === action.id)
					if (foundResult !== undefined) {
						action.result = foundResult

						action.status = foundResult.status
					} else {
						action.status = "SUCCESS"
					}
				}

				const lastitem = index === relevantactions.length - 1

				if (!lastitem) {
					if (action.app_name === "Shuffle Tools") {
						if (action.status === "SUCCESS") {
							branchcolor = red

							// Check action.result for the actual status
							const validate = validateJson(action.result.result)
    						if (validate.valid) {
								if (validate.result.success === true) {
									nodecolor = green
									branchcolor = green
								} else {
									// Green by default
									nodecolor = green 
									branchcolor = green 
								}
							} else {
								nodecolor = green
								branchcolor = green
							}
						} else if (action.status === "SKIPPED") {
							branchcolor = grey
						} else {
							// FIXME: How do we handle this? 
							if (action.status === undefined) {
								nodecolor = grey 
								branchcolor = grey 
							} else {
								nodecolor = red 
								branchcolor = red
							}
						}

						previousTools = true 

						if (startnodeId !== action.id) {
							//return null
						}
					} else {
						if (action.status === "SUCCESS") {
							nodecolor = green
						} else if (action.status === "SKIPPED") {
							nodecolor = grey
						} else {
							if (action.status === undefined) {
								nodecolor = green
							} else {
								nodecolor = red
							}
						}
					}
				} else {
					nodecolor = grey
				}

				if (action.status === "SKIPPED") {
					skipped = true
				}

				var image = ""
				if (action.large_image !== undefined && action.large_image !== null && action.large_image !== "") {
					image = action.large_image
				} else {
					if (originalWorkflow !== undefined) {
						for (var key in originalWorkflow.actions) {
							if (originalWorkflow.actions[key].id === action.id) {
								image = originalWorkflow.actions[key].large_image
								break
							}
						}

						if (image === "") {
							for (var key in originalWorkflow.triggers) {
								if (originalWorkflow.triggers[key].id === action.id) {
									image = originalWorkflow.triggers[key].large_image
									break
								}
							}

						}
					}
				}

				var founderror = ""
				//console.log("WORKFLOW VALIDATION: ", workflow.validation)
				if (workflow.validation !== undefined && workflow.validation !== null && workflow.validation.errors !== undefined && workflow.validation.errors !== null) {
					const foundError = workflow.validation.errors.find((element) => element.action_id === action.id)
					if (foundError !== undefined) {
						founderror = foundError.error
						nodecolor = red 
						branchcolor = red 
					} else {
						//console.log("NO ERROR: ", action.id)
					}
				}

				var appgroup = []
				if (action.app_name === "shuffle-subflow") {
					if (action.status === "SUCCESS") {
						nodecolor = green
						branchcolor = green
					}

					if (workflow.validation.subflow_apps !== undefined && workflow.validation.subflow_apps !== null && workflow.validation.subflow_apps.length > 0) {
						nodecolor = red
						branchcolor = red

						for (var subflowkey in workflow.validation.subflow_apps) {
							const subflowApp = workflow.validation.subflow_apps[subflowkey]
							founderror += "- " + subflowApp.error+"\n"

							if (subflowApp.error === action.id) {
								appgroup.push(subflowApp)
							}
						}
					}
				}

				if (!showMiddle && relevantactions.length > 2 && index > 0 && index === relevantactions.length - 2) {
					if (founderror.length > 0) {
						middleError += action.label+": "+founderror+"\n\n"

						middleBranchColor = branchcolor
					}

					if (index === relevantactions.length-2 && relevantactions.length > 2) {

						const selectedIcon = middleError.length > 0 ? 
							<Tooltip 
								title={
									<Typography variant="body1" style={{margin: 5, whiteSpace: "pre-line", }}>
										{middleError}
									</Typography>
								}
								inputProps={{
									paperProps: {
										backgroundColor: "red",
									}
								}}
							>
								<IconButton style={{width: 30, height: 30, backgroundColor: "rgba(255,255,255,0.0)", borderRadius: 30, marginTop: 2, }}>
									<ErrorOutlineIcon style={{color: "red", }} /> 
								</IconButton>
							</Tooltip>
						: null

						return selectedIcon
					} else {
						return null
					}
				}

				// Returns for anything non-middle
				if (relevantactions.length > 2 && index >= 1 && index < relevantactions.length - 2) {
					if (founderror.length > 0) {
						middleError += action.label+": "+founderror+"\n\n"
					}

					return null
				}

				if (skipped && !lastitem) {
					nodecolor = grey
					branchcolor = grey
				}

				if (previousTools) {
					previousTools = false
				} else {
					branchcolor = nodecolor
				}

				if (action.trigger_type === "WEBHOOK") {
					nodecolor = green
					branchcolor = green
				} 

				var flex = index !== 0 && index !== relevantactions.length - 1 ? 1 : 3
				if (nodecolor === green) {
					branchcolor = green
				} else if (nodecolor === yellow) {
					branchcolor = yellow
				} else if (nodecolor === red) {
					branchcolor = red
				}

				if (index === 0) {
					startBranchColor = branchcolor
				} else if (index !== 0 && index !== relevantactions.length - 1) {
					// FIXME: This doesn't work yet
					middleBranchColor = branchcolor
				}

				if (lastitem) {	
					if (middleError.length === 0) {
						branchcolor = startBranchColor
					} else {
						//branchcolor = middleBranchColor 
					}

					if (founderror === "") {
						nodecolor = green
					}
				}

				// FIXME: This could mean the workflow hasn't ran yet
				if (workflow.validation.valid === false && (workflow.validation.errors === undefined || workflow.validation.errors === null || workflow.validation.errors.length == 0) && (workflow.validation.subflow_apps === undefined || workflow.validation.subflow_apps === null || workflow.validation.subflow_apps.length == 0)) {
					nodecolor = grey 
					branchcolor = grey
				} 

				const branchTooltip = branchcolor === yellow ? "Check nodes for errors" : ""
				const appname = action.app_name.replaceAll('_', ' ').slice(0, 16)

				const chipBackground = nodecolor === green ? "rgba(2,203,112, 0.2)" : nodecolor === grey ? "#494949": "rgba(245,52,52,0.8)" 
				const chipColor = nodecolor === green ? "#02cb70" : nodecolor === grey ? "#CDCDCD" : "white" 

				//const ballcolor = lastitem ? nodecolor : branchcolor 
				const ballcolor = branchcolor 
				const ballsize = 8
				const topMargin = 20

				const chipStyle = {
					height: 40, 
					minWidth: 125, 
					maxWidth: 125, 
					borderRadius: 50, 
					color: chipColor, 
					backgroundColor: chipBackground,

					//border: `2px solid ${chipBackground}`, 
					//backgroundColor: "rgba(0,0,0,0.0)", 
				}

				if (image === "") {
					console.log("MISSING IMAGE: ", appname, image, action)
				}

				if (decidedColor === grey && nodecolor === green) {
					setDecidedColor(red)
				}

				if (decidedColor !== red && nodecolor === red) {
					setDecidedColor(red)
				}

				return (
					<div style={{display: "flex", flex: flex, justifyContent: "right", }}> 
						{lastitem ? 
							<Tooltip title={branchTooltip}>
								<div style={{display: "flex", width: "100%", position: "relative",}}>
									<div style={{marginLeft: 0, marginRight: 0, marginTop: topMargin, height: 3, width: "100%", backgroundColor: branchcolor, }} />
									<div style={{position: "absolute", right: -3, top: topMargin-2.5, backgroundColor: ballcolor, width: ballsize, height: ballsize, borderRadius: 10, }}/>
								</div>
							</Tooltip>
						: null}

						{appgroup.length > 0 ? 
							<AvatarGroup max={4} style={{height: itemHeight+8, }}> 
								{appgroup.map((subflowApp, subflowIndex) => {
									var appimage = ""
									if (apps !== undefined && apps !== null && apps.length > 0) {
										for (var key in apps) {
											const app = apps[key]
											if (app.name === subflowApp.app_name) {
												appimage = apps[key].large_image
												break
											}
										}
									}

									return ( 
										<Tooltip title={`App: ${subflowApp.app_name} - subflow app`}>
										<Avatar
											style={{ 
												border: `4px solid ${nodecolor}`,
											}}
											src={appimage}
										/>
										</Tooltip>
									)
								})}
							</AvatarGroup>
						: 
							<Tooltip title={
								<Typography variant="body1" style={{margin: 5, color: "white", }}>
									{founderror.length > 0 ? founderror : `App: ${appname} - Action: ${action.label}`} 
								</Typography>
							} placement="top">
								<Chip label={`${appname}`} style={chipStyle}  icon={
									<Avatar
										variant="round"
										sx={{ backgroundColor: nodecolor, width: itemHeight, height: itemHeight, borderRadius: 50, border: `1px solid ${nodecolor}`,}}
									>
										{image !== "" ? 
											<img 
												src={image} 
												style={{
													width: itemHeight, 
													height: itemHeight,  
												}} 
											/> 
										: null}
									</Avatar>
								} />

							</Tooltip>
						}

						{lastitem ? null :
							<Tooltip title={branchTooltip}>
								<div style={{display: "flex", width: "100%", position: "relative",}}>
									<div style={{position: "absolute", left: -3, top: topMargin-2.5, backgroundColor: ballcolor, color: ballcolor, width: ballsize, height: ballsize, borderRadius: 10, }}/>
									<div style={{marginLeft: 0, marginRight: 0, marginTop: 20, height: 3, width: "100%", backgroundColor: branchcolor, }} />
								</div>
							</Tooltip>
						}
					</div>
				)
			  })}
			</div>

		</div>
	)
}

export default WorkflowValidationTimeline
