import { TerminalOutput } from '@/ai/components/TerminalOutput';
import { styled } from '@linaria/react';
import { useContext, useState } from 'react';
import { useLingui } from '@lingui/react/macro';
import {
  IconChevronDown,
  IconChevronUp,
  IconCode,
  IconCopy,
  IconDownload,
  IconFile,
  IconPlayerPlay,
  IconSquareRoundedCheck,
  IconSquareRoundedX,
} from 'twenty-ui/icon';
import { CodeEditor, LightIconButton } from 'twenty-ui/input';
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';

const StyledContainer = styled.div`
  border: 1px solid ${themeCssVariables.border.color.medium};
  border-radius: ${themeCssVariables.border.radius.md};
  display: flex;
  flex-direction: column;
  margin: ${themeCssVariables.spacing[2]} 0;
  overflow: hidden;
`;

const StyledHeader = styled.div<{ status: 'success' | 'error' | 'running' }>`
  align-items: center;
  background: ${themeCssVariables.background.secondary};
  border-bottom: 1px solid ${themeCssVariables.border.color.light};
  display: flex;
  gap: ${themeCssVariables.spacing[2]};
  justify-content: space-between;
  padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[3]};
`;

const StyledHeaderLeft = styled.div`
  align-items: center;
  display: flex;
  gap: ${themeCssVariables.spacing[2]};
`;

const StyledHeaderRight = styled.div`
  align-items: center;
  display: flex;
  gap: ${themeCssVariables.spacing[1]};
`;

const StyledStatusBadge = styled.div<{
  status: 'success' | 'error' | 'running';
}>`
  align-items: center;
  background: ${({ status }) =>
    status === 'success'
      ? themeCssVariables.background.transparent.success
      : status === 'error'
        ? themeCssVariables.background.transparent.danger
        : themeCssVariables.background.transparent.medium};
  border-radius: ${themeCssVariables.border.radius.pill};
  color: ${({ status }) =>
    status === 'success'
      ? themeCssVariables.color.turquoise
      : status === 'error'
        ? themeCssVariables.color.red
        : themeCssVariables.font.color.secondary};
  corner-shape: round;
  display: flex;
  font-size: ${themeCssVariables.font.size.xs};
  font-weight: ${themeCssVariables.font.weight.medium};
  gap: ${themeCssVariables.spacing[1]};
  padding: ${themeCssVariables.spacing['0.5']} ${themeCssVariables.spacing[2]};
`;

const StyledTitle = styled.span`
  color: ${themeCssVariables.font.color.primary};
  font-size: ${themeCssVariables.font.size.md};
  font-weight: ${themeCssVariables.font.weight.medium};
`;

const StyledSection = styled.div`
  border-top: 1px solid ${themeCssVariables.border.color.light};
`;

const StyledSectionHeader = styled.div`
  align-items: center;
  background: ${themeCssVariables.background.secondary};
  cursor: pointer;
  display: flex;
  gap: ${themeCssVariables.spacing[2]};
  justify-content: space-between;
  padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[3]};
  transition: background calc(${themeCssVariables.animation.duration.fast} * 1s);

  &:hover {
    background: ${themeCssVariables.background.tertiary};
  }
`;

const StyledSectionHeaderLeft = styled.div`
  align-items: center;
  color: ${themeCssVariables.font.color.secondary};
  display: flex;
  font-size: ${themeCssVariables.font.size.sm};
  font-weight: ${themeCssVariables.font.weight.medium};
  gap: ${themeCssVariables.spacing[1]};
`;

const StyledCodeEditorContainer = styled.div`
  max-height: 300px;
  overflow: hidden;
`;

const StyledFilesGrid = styled.div`
  display: grid;
  gap: ${themeCssVariables.spacing[2]};
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  padding: ${themeCssVariables.spacing[3]};
`;

const StyledFileCard = styled.div`
  border: 1px solid ${themeCssVariables.border.color.light};
  border-radius: ${themeCssVariables.border.radius.sm};
  display: flex;
  flex-direction: column;
  overflow: hidden;
`;

const StyledFilePreview = styled.div`
  align-items: center;
  aspect-ratio: 16 / 9;
  background: ${themeCssVariables.background.tertiary};
  display: flex;
  justify-content: center;
  overflow: hidden;
`;

const StyledPreviewImage = styled.img`
  height: 100%;
  object-fit: contain;
  width: 100%;
`;

const StyledFileInfo = styled.div`
  align-items: center;
  background: ${themeCssVariables.background.secondary};
  display: flex;
  gap: ${themeCssVariables.spacing[2]};
  justify-content: space-between;
  padding: ${themeCssVariables.spacing['1.5']} ${themeCssVariables.spacing[2]};
`;

const StyledFileName = styled.span`
  color: ${themeCssVariables.font.color.primary};
  font-size: ${themeCssVariables.font.size.sm};
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
`;

const StyledDownloadLink = styled.a`
  align-items: center;
  color: ${themeCssVariables.font.color.secondary};
  display: flex;

  &:hover {
    color: ${themeCssVariables.font.color.primary};
  }
`;

type CodeExecutionDisplayProps = {
  code: string;
  stdout: string;
  stderr: string;
  exitCode?: number;
  files?: Array<{
    fileId: string;
    filename: string;
    url: string;
    mimeType?: string;
  }>;
  isRunning?: boolean;
};

const isPreviewableMimeType = (mimeType?: string): boolean => {
  if (!mimeType) {
    return false;
  }

  return ['image/png', 'image/jpeg', 'image/gif', 'image/webp'].includes(
    mimeType,
  );
};

export const CodeExecutionDisplay = ({
  code,
  stdout,
  stderr,
  exitCode,
  files = [],
  isRunning = false,
}: CodeExecutionDisplayProps) => {
  const { theme } = useContext(ThemeContext);
  const { t } = useLingui();
  const { copyToClipboard } = useCopyToClipboard();
  const [isCodeExpanded, setIsCodeExpanded] = useState(false);
  const [isOutputExpanded, setIsOutputExpanded] = useState(true);
  const [isFilesExpanded, setIsFilesExpanded] = useState(true);

  const status: 'success' | 'error' | 'running' = isRunning
    ? 'running'
    : exitCode === 0
      ? 'success'
      : 'error';

  const StatusIcon =
    status === 'success'
      ? IconSquareRoundedCheck
      : status === 'error'
        ? IconSquareRoundedX
        : IconPlayerPlay;

  const statusText = isRunning
    ? t`Running...`
    : exitCode === 0
      ? t`Completed`
      : t`Failed`;

  const hasOutput = stdout || stderr;
  const hasFiles = files.length > 0;

  return (
    <StyledContainer>
      <StyledHeader status={status}>
        <StyledHeaderLeft>
          <IconCode size={theme.icon.size.md} />
          <StyledTitle>{t`Python Code Execution`}</StyledTitle>
        </StyledHeaderLeft>
        <StyledHeaderRight>
          <StyledStatusBadge status={status}>
            <StatusIcon size={theme.icon.size.sm} />
            {statusText}
          </StyledStatusBadge>
        </StyledHeaderRight>
      </StyledHeader>

      <StyledSection>
        <StyledSectionHeader onClick={() => setIsCodeExpanded(!isCodeExpanded)}>
          <StyledSectionHeaderLeft>
            <IconCode size={theme.icon.size.sm} />
            {t`Code`}
          </StyledSectionHeaderLeft>
          <StyledHeaderRight>
            <LightIconButton
              Icon={IconCopy}
              onClick={(e) => {
                e.stopPropagation();
                copyToClipboard(code);
              }}
              title={t`Copy code`}
              size="small"
              accent="tertiary"
            />
            {isCodeExpanded ? (
              <IconChevronUp size={theme.icon.size.sm} />
            ) : (
              <IconChevronDown size={theme.icon.size.sm} />
            )}
          </StyledHeaderRight>
        </StyledSectionHeader>
        <AnimatedExpandableContainer
          isExpanded={isCodeExpanded}
          mode="fit-content"
        >
          <StyledCodeEditorContainer>
            <CodeEditor
              value={code}
              language="python"
              height="300px"
              options={{
                readOnly: true,
                domReadOnly: true,
                minimap: { enabled: false },
              }}
            />
          </StyledCodeEditorContainer>
        </AnimatedExpandableContainer>
      </StyledSection>

      {(hasOutput || isRunning) && (
        <StyledSection>
          <StyledSectionHeader
            onClick={() => setIsOutputExpanded(!isOutputExpanded)}
          >
            <StyledSectionHeaderLeft>{t`Output`}</StyledSectionHeaderLeft>
            {isOutputExpanded ? (
              <IconChevronUp size={theme.icon.size.sm} />
            ) : (
              <IconChevronDown size={theme.icon.size.sm} />
            )}
          </StyledSectionHeader>
          <AnimatedExpandableContainer
            isExpanded={isOutputExpanded}
            mode="fit-content"
          >
            <TerminalOutput
              stdout={stdout}
              stderr={stderr}
              isRunning={isRunning}
            />
          </AnimatedExpandableContainer>
        </StyledSection>
      )}

      {hasFiles && (
        <StyledSection>
          <StyledSectionHeader
            onClick={() => setIsFilesExpanded(!isFilesExpanded)}
          >
            <StyledSectionHeaderLeft>
              <IconFile size={theme.icon.size.sm} />
              {t`Generated Files`} ({files.length})
            </StyledSectionHeaderLeft>
            {isFilesExpanded ? (
              <IconChevronUp size={theme.icon.size.sm} />
            ) : (
              <IconChevronDown size={theme.icon.size.sm} />
            )}
          </StyledSectionHeader>
          <AnimatedExpandableContainer
            isExpanded={isFilesExpanded}
            mode="fit-content"
          >
            <StyledFilesGrid>
              {files.map((file) => {
                const filename = file.filename;

                return (
                  <StyledFileCard key={file.fileId}>
                    <StyledFilePreview>
                      {isPreviewableMimeType(file.mimeType) ? (
                        <StyledPreviewImage
                          src={file.url}
                          alt={filename}
                          loading="lazy"
                        />
                      ) : (
                        <IconFile size={48} color={theme.font.color.tertiary} />
                      )}
                    </StyledFilePreview>
                    <StyledFileInfo>
                      <StyledFileName title={filename}>
                        {filename}
                      </StyledFileName>
                      <StyledDownloadLink
                        href={file.url}
                        download={filename}
                        title={t`Download ${filename}`}
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        <IconDownload size={theme.icon.size.sm} />
                      </StyledDownloadLink>
                    </StyledFileInfo>
                  </StyledFileCard>
                );
              })}
            </StyledFilesGrid>
          </AnimatedExpandableContainer>
        </StyledSection>
      )}
    </StyledContainer>
  );
};
