import { faBan, faChartLine, faEdit, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { BusinessCenter, Lock, LockOpen } from '@mui/icons-material';
import { Box, Button, ButtonGroup, CardActionArea, CardContent, Chip, IconButton, Skeleton, Tooltip, Typography } from '@mui/material';
import React, { lazy, Suspense, useCallback, useContext, useState } from 'react';
import { useTranslation } from 'react-i18next';
import SlotNameWithIcon from '../Components/Artifact/SlotNameWIthIcon';
import CardLight from '../Components/Card/CardLight';
import CharacterAutocomplete from '../Components/Character/CharacterAutocomplete';
import LocationName from '../Components/Character/LocationName';
import ColorText from '../Components/ColoredText';
import ConditionalWrapper from '../Components/ConditionalWrapper';
import InfoTooltip from '../Components/InfoTooltip';
import SqBadge from '../Components/SqBadge';
import { Stars } from '../Components/StarDisplay';
import StatIcon from '../Components/StatIcon';
import Artifact from '../Data/Artifacts/Artifact';
import { ArtifactSheet } from '../Data/Artifacts/ArtifactSheet';
import { DatabaseContext } from '../Database/Database';
import KeyMap, { cacheValueString } from '../KeyMap';
import useArtifact from '../ReactHooks/useArtifact';
import usePromise from '../ReactHooks/usePromise';
import { allSubstatKeys, ICachedArtifact, ICachedSubstat, SubstatKey } from '../Types/artifact';
import { CharacterKey, Rarity } from '../Types/consts';
import { clamp, clamp01 } from '../Util/Util';
import PercentBadge from './PercentBadge';
import { probability } from './RollProbability';

const ArtifactEditor = lazy(() => import('./ArtifactEditor'))

type Data = {
  artifactId?: string,
  artifactObj?: ICachedArtifact,
  onClick?: (id: string) => void,
  onDelete?: (id: string) => void, mainStatAssumptionLevel?: number,
  effFilter?: Set<SubstatKey>,
  probabilityFilter?: Dict<SubstatKey, number>
  disableEditSetSlot?: boolean
  editor?: boolean,
  canExclude?: boolean
  canEquip?: boolean,
  extraButtons?: JSX.Element
}
const allSubstatFilter = new Set(allSubstatKeys)

export default function ArtifactCard({ artifactId, artifactObj, onClick, onDelete, mainStatAssumptionLevel = 0, effFilter = allSubstatFilter, probabilityFilter, disableEditSetSlot = false, editor = false, canExclude = false, canEquip = false, extraButtons }: Data): JSX.Element | null {
  const { t } = useTranslation(["artifact", "ui"]);
  const { database } = useContext(DatabaseContext)
  const databaseArtifact = useArtifact(artifactId)
  const sheet = usePromise(ArtifactSheet.get((artifactObj ?? databaseArtifact)?.setKey), [artifactObj, databaseArtifact])
  const equipOnChar = (charKey: CharacterKey | "") => database.setArtLocation(artifactId!, charKey)
  const editable = !artifactObj
  const [showEditor, setshowEditor] = useState(false)
  const onHideEditor = useCallback(() => setshowEditor(false), [setshowEditor])
  const onShowEditor = useCallback(() => editable && setshowEditor(true), [editable, setshowEditor])

  const wrapperFunc = useCallback(children => <CardActionArea onClick={() => artifactId && onClick?.(artifactId)} sx={{ flexGrow: 1, display: "flex", flexDirection: "column" }} >{children}</CardActionArea>, [onClick, artifactId],)
  const falseWrapperFunc = useCallback(children => <Box sx={{ flexGrow: 1, display: "flex", flexDirection: "column" }} >{children}</Box>, [])

  const art = artifactObj ?? databaseArtifact
  if (!art) return null

  const { id, lock, slotKey, rarity, level, mainStatKey, substats, exclude, location = "" } = art
  const mainStatLevel = Math.max(Math.min(mainStatAssumptionLevel, rarity * 4), level)
  const mainStatUnit = KeyMap.unit(mainStatKey)
  const levelVariant = "roll" + (Math.floor(Math.max(level, 0) / 4) + 1)
  const { currentEfficiency, maxEfficiency } = Artifact.getArtifactEfficiency(art, effFilter)
  const artifactValid = maxEfficiency !== 0
  const slotName = sheet?.getSlotName(slotKey) || "Unknown Piece Name"
  const slotDesc = sheet?.getSlotDesc(slotKey)
  const slotDescTooltip = slotDesc && <InfoTooltip title={<Box>
    <Typography variant='h6'>{slotName}</Typography>
    <Typography>{slotDesc}</Typography>
  </Box>} />
  const setEffects = sheet?.setEffects
  const setDescTooltip = sheet && setEffects && <InfoTooltip title={
    <span>
      {Object.keys(setEffects).map(setNumKey => <span key={setNumKey}>
        <Typography variant="h6"><SqBadge color="success">{t(`artifact:setEffectNum`, { setNum: setNumKey })}</SqBadge></Typography>
        <Typography>{sheet.setEffectDesc(setNumKey as any)}</Typography>
      </span>)}
    </span>
  } />
  return <Suspense fallback={<Skeleton variant="rectangular" sx={{ width: "100%", height: "100%", minHeight: 350 }} />}>
    {editor && <Suspense fallback={false}>
      <ArtifactEditor
        artifactIdToEdit={showEditor ? artifactId : ""}
        cancelEdit={onHideEditor}
        disableEditSetSlot={disableEditSetSlot}
      />
    </Suspense>}
    <CardLight sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
      <ConditionalWrapper condition={!!onClick} wrapper={wrapperFunc} falseWrapper={falseWrapperFunc}>
        <Box className={`grad-${rarity}star`} sx={{ position: "relative", width: "100%" }}>
          {!onClick && <IconButton color="primary" disabled={!editable} onClick={() => database.updateArt({ lock: !lock }, id)} sx={{ position: "absolute", right: 0, bottom: 0, zIndex: 2 }}>
            {lock ? <Lock /> : <LockOpen />}
          </IconButton>}
          <Box sx={{ pt: 2, px: 2, position: "relative", zIndex: 1 }}>
            {/* header */}
            <Box component="div" sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1 }}>
              <Chip size="small" label={<strong>{` +${level}`}</strong>} color={levelVariant as any} />
              <Typography component="span" noWrap sx={{ backgroundColor: "rgba(100,100,100,0.35)", borderRadius: "1em", px: 1 }}><strong>{slotName}</strong></Typography>
              <Box flexGrow={1} sx={{ textAlign: "right" }}>
                {slotDescTooltip}
              </Box>
            </Box>
            <Typography color="text.secondary" variant="body2">
              <SlotNameWithIcon slotKey={slotKey} />
            </Typography>
            <Typography variant="h6" color={`${KeyMap.getVariant(mainStatKey)}.main`}>
              <span>{StatIcon[mainStatKey]} {KeyMap.get(mainStatKey)}</span>
            </Typography>
            <Typography variant="h5">
              <strong>
                <ColorText color={mainStatLevel !== level ? "warning" : undefined}>{cacheValueString(Artifact.mainStatValue(mainStatKey, rarity, mainStatLevel) ?? 0, KeyMap.unit(mainStatKey))}{mainStatUnit}</ColorText>
              </strong>
            </Typography>
            <Stars stars={rarity} colored />
            {/* {process.env.NODE_ENV === "development" && <Typography color="common.black">{id || `""`} </Typography>} */}
          </Box>
          <Box sx={{ height: "100%", position: "absolute", right: 0, top: 0 }}>
            <Box
              component="img"
              src={sheet?.slotIcons[slotKey] ?? ""}
              width="auto"
              height="100%"
              sx={{ float: "right" }}
            />
          </Box>
        </Box>
        <CardContent sx={{ flexGrow: 1, display: "flex", flexDirection: "column", pt: 1, pb: 0, width: "100%" }}>
          {substats.map((stat: ICachedSubstat) => <SubstatDisplay key={stat.key} stat={stat} effFilter={effFilter} rarity={rarity} />)}
          <Box sx={{ display: "flex", my: 1 }}>
            <Typography color="text.secondary" component="span" variant="caption" sx={{ flexGrow: 1 }}>{t`artifact:editor.curSubEff`}</Typography>
            <PercentBadge value={currentEfficiency} max={900} valid={artifactValid} />
          </Box>
          {currentEfficiency !== maxEfficiency && <Box sx={{ display: "flex", mb: 1 }}>
            <Typography color="text.secondary" component="span" variant="caption" sx={{ flexGrow: 1 }}>{t`artifact:editor.maxSubEff`}</Typography>
            <PercentBadge value={maxEfficiency} max={900} valid={artifactValid} />
          </Box>}
          <Box flexGrow={1} />
          {probabilityFilter && <strong>Probability: {(probability(art, probabilityFilter) * 100).toFixed(2)}%</strong>}
          <Typography color="success.main">{sheet?.name ?? "Artifact Set"} {setDescTooltip}</Typography>
        </CardContent>
      </ConditionalWrapper>
      <Box sx={{ p: 1, display: "flex", gap: 1, justifyContent: "space-between", alignItems: "center" }}>
        {editable && canEquip
          ? <CharacterAutocomplete sx={{ flexGrow: 1 }} size="small" showDefault
            defaultIcon={<BusinessCenter />} defaultText={t("ui:inventory")}
            value={location} onChange={equipOnChar} />
          : <LocationName location={location} />}
        {editable && <ButtonGroup sx={{ height: "100%" }}>
          {editor && <Tooltip title={<Typography>{t`artifact:edit`}</Typography>} placement="top" arrow>
            <Button color="info" size="small" onClick={onShowEditor} >
              <FontAwesomeIcon icon={faEdit} className="fa-fw" />
            </Button>
          </Tooltip>}
          {canExclude && <Tooltip title={<Typography>{t`artifact:excludeArtifactTip`}</Typography>} placement="top" arrow>
            <Button onClick={() => database.updateArt({ exclude: !exclude }, id)} color={exclude ? "error" : "success"} size="small" >
              <FontAwesomeIcon icon={exclude ? faBan : faChartLine} className="fa-fw" />
            </Button>
          </Tooltip>}
          {!!onDelete && <Button color="error" size="small" onClick={() => onDelete(id)} disabled={lock}>
            <FontAwesomeIcon icon={faTrashAlt} className="fa-fw" />
          </Button>}
          {extraButtons}
        </ButtonGroup>}
      </Box>
    </CardLight >
  </Suspense>
}
function SubstatDisplay({ stat, effFilter, rarity }: { stat: ICachedSubstat, effFilter: Set<SubstatKey>, rarity: Rarity }) {
  if (!stat.value) return null
  const numRolls = stat.rolls?.length ?? 0
  const maxRoll = stat.key ? Artifact.maxSubstatValues(stat.key) : 0
  const rollData = stat.key ? Artifact.getSubstatRollData(stat.key, rarity) : []
  const rollOffset = 7 - rollData.length
  const rollColor = `roll${clamp(numRolls, 1, 6)}`
  const efficiency = stat.efficiency ?? 0
  const effOpacity = clamp01(0.5 + (efficiency / (100 * 5)) * 0.5) //divide by 6 because an substat can have max 6 rolls
  const statName = KeyMap.getStr(stat.key)
  const unit = KeyMap.unit(stat.key)
  const inFilter = stat.key && effFilter.has(stat.key)
  return (<Box display="flex" gap={1} alignContent="center">
    <Typography sx={{ flexGrow: 1 }} color={(numRolls ? `${rollColor}.main` : "error.main") as any} component="span">{StatIcon[stat.key]} {statName}{`+${cacheValueString(stat.value, KeyMap.unit(stat.key))}${unit}`}</Typography>
    {inFilter && <Box display="flex" gap={0.25} height="1.3em">
      {stat.rolls.sort().map((v, i) => <SmolProgress key={`${i}${v}`} value={100 * v / maxRoll} color={`roll${clamp(rollOffset + rollData.indexOf(v), 1, 6)}.main`} />)}
    </Box>}
    <Typography sx={{ opacity: effOpacity, minWidth: 40, textAlign: "right" }}>{inFilter ? `${efficiency.toFixed()}%` : "-"}</Typography>
  </Box>)
}
export function SmolProgress({ color = "red", value = 50 }) {
  return <Box sx={{ width: 7, height: "100%", bgcolor: color, overflow: "hidden", borderRadius: 1, display: "inline-block" }}>
    <Box sx={{ width: 10, height: `${100 - clamp(value, 0, 100)}%`, bgcolor: "gray" }} />
  </Box>
}