/*
 * Copyright (C)  2022 Kristóf Marussy <kristof@marussy.com>
 *
 * This file is part of Sophie.
 *
 * Sophie is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: AGPL-3.0-only
 */

import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import Accordion from '@mui/material/Accordion';
import AccordionDetails from '@mui/material/AccordionDetails';
import AccordionSummary from '@mui/material/AccordionSummary';
import Box from '@mui/material/Box';
import Tab from '@mui/material/Tab';
import Tabs from '@mui/material/Tabs';
import Typography from '@mui/material/Typography';
import { styled } from '@mui/material/styles';
import type { Certificate } from '@sophie/shared';
import { observer } from 'mobx-react-lite';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';

import type Service from '../../stores/Service';

import SingleCertificateDetails from './SingleCertificateDetails';
import TrustCertificateDialog from './TrustCertificateDialog';

const SUMMARY_ID = 'Sophie-CertificateDetails-header';
const DETAILS_ID = 'Sophie-CertificateDetails-content';

function getCertificateChain(endEntityCertificate: Certificate): Certificate[] {
  const chain: Certificate[] = [];
  let certificate: Certificate | undefined = endEntityCertificate;
  while (certificate !== undefined) {
    chain.push(certificate);
    certificate = certificate.issuerCert as Certificate;
  }
  return chain;
}

const DetailsBox = styled(Box)(({ theme }) => ({
  padding: `0 ${theme.spacing(2)}`,
}));

function CertificateDetails({
  service,
}: {
  service: Service;
}): JSX.Element | null {
  const { t } = useTranslation(undefined, {
    keyPrefix: 'error.certificateError.details',
  });
  const [certificateIndex, setCertificateIndex] = useState(0);

  const { id: serviceId, state } = service;
  const { type: errorType } = state;

  if (errorType !== 'certificateError') {
    // eslint-disable-next-line unicorn/no-null -- React requires `null` to skip rendering.
    return null;
  }

  const { certificate, trust } = state;

  const chain = getCertificateChain(certificate);

  if (chain.length === 0) {
    // eslint-disable-next-line unicorn/no-null -- React requires `null` to skip rendering.
    return null;
  }

  const id = `${serviceId}-certificateDetails`;

  const trustCertificateDialog = (
    <TrustCertificateDialog
      trust={trust}
      onClick={() => service.temporarilyTrustCurrentCertificate()}
    />
  );

  return (
    <Accordion
      disableGutters
      variant="outlined"
      sx={{ '&::before': { display: 'none' }, borderRadius: 1 }}
    >
      <AccordionSummary
        id={SUMMARY_ID}
        aria-controls={DETAILS_ID}
        expandIcon={<ExpandMoreIcon />}
      >
        <Typography>{t('title')}</Typography>
      </AccordionSummary>
      <AccordionDetails
        sx={{
          px: 0,
          pt: 0,
        }}
      >
        {chain.length >= 2 ? (
          <>
            <Tabs
              aria-label={t<string>('tabsLabel')}
              value={certificateIndex < chain.length ? certificateIndex : false}
              onChange={(_event, value) => setCertificateIndex(value as number)}
              variant="fullWidth"
            >
              {chain.map((member, i) => (
                <Tab
                  key={member.fingerprint}
                  value={i}
                  id={`${id}-tab-${i}`}
                  aria-controls={`${id}-tabpanel-${i}`}
                  label={
                    member.subjectName === ''
                      ? member.fingerprint
                      : member.subjectName
                  }
                />
              ))}
            </Tabs>
            <DetailsBox
              sx={(theme) => ({
                paddingTop: 1,
                borderTop: `1px solid ${theme.palette.divider}`,
              })}
            >
              {chain.map((member, i) => (
                <div
                  key={member.fingerprint}
                  role="tabpanel"
                  hidden={certificateIndex !== i}
                  id={`${id}-tabpanel-${i}`}
                  aria-labelledby={`${id}-tab-${i}`}
                >
                  {certificateIndex === i && (
                    <>
                      <SingleCertificateDetails
                        detailsId={id}
                        certificate={member}
                        onIssuerClick={
                          i < chain.length - 1
                            ? () => setCertificateIndex(i + 1)
                            : undefined
                        }
                        onDownloadClick={() =>
                          service.downloadCertificate(member.fingerprint)
                        }
                      />
                      {i === 0 && trustCertificateDialog}
                    </>
                  )}
                </div>
              ))}
            </DetailsBox>
          </>
        ) : (
          <DetailsBox>
            <SingleCertificateDetails
              detailsId={id}
              certificate={chain[0]}
              onDownloadClick={() =>
                service.downloadCertificate(chain[0].fingerprint)
              }
            />
            {trustCertificateDialog}
          </DetailsBox>
        )}
      </AccordionDetails>
    </Accordion>
  );
}

export default observer(CertificateDetails);
