import { useEffect, useState } from 'react';
import { Link as RouterLink, useNavigate, useParams } from 'react-router';

import { Box, Button, Link, Typography } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import type { CSSObject } from 'tss-react';
import { makeStyles } from 'tss-react/mui';

import { darkBackground, gray } from '../../../themes/common';
import { notify } from '../../common/notify';
import { MasterfilesVersionDialog } from '../components/MasterfilesVersionDialog';
import { ModuleSummary } from '../components/ModuleSummary';
import { MASTER_VERSION, MASTERFILES_MODULE, MASTERFILES_REPOSITORY, PROJECT_CREATED_KEY } from '../constants';
import { useAppDispatch, useAppSelector } from '../store';
import { fetchCategoryModules } from '../store/modulesSlice/thunks';
import { selectCategoryModules } from '../store/modulesSlice/selectors';
import {
  selectAddedModules,
  selectCurrentProject,
  selectModulesLoaded,
  selectVcsSync
} from '../store/projectsSlice/selectors';
import { addModuleToProject, loadProjectInfo, refreshProjectStatus } from '../store/projectsSlice/thunks';

const CATEGORIES = ['security', 'compliance'];

const useStyles = makeStyles()(theme => ({
  welcome: { display: 'flex', paddingTop: 59, position: 'relative' },
  welcomeText: { maxWidth: 435 },
  welcomeSubtitle: { marginTop: 8 },
  welcomeButton: { marginTop: 34 },
  illustration: {
    backgroundImage:
      theme.palette.mode === 'dark'
        ? 'url("/images/build/build_illustration_dark.svg")'
        : 'url("/images/build/build_illustration.svg")',
    width: 358,
    height: 231,
    marginLeft: 90,
    backgroundSize: 'cover'
  },
  quickstartHelp: { color: gray[500], marginTop: 24 },
  quickstartCard: {
    padding: '16px 21px 24px 21px',
    backgroundColor: theme.palette.mode === 'dark' ? darkBackground[800] : gray[50],
    borderRadius: 10,
    marginTop: 8
  },
  quickstartTop: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    borderBottom: `1px solid ${theme.palette.divider}`,
    paddingBottom: 12,
    marginBottom: 12,
    '& h2': { margin: 0 }
  },
  quickstartBody: {
    ...(theme.typography.subtitle1 as CSSObject),
    color: theme.palette.text.secondary,
    maxWidth: 720,
    '& ol': { counterReset: 'custom-counter', listStyle: 'none', paddingLeft: 24 },
    '& li': { marginTop: 16, counterIncrement: 'custom-counter', position: 'relative', paddingLeft: 12 },
    '& li > div': { ...(theme.typography.h6 as CSSObject), marginBottom: 3, color: theme.palette.text.primary },
    '& li::before': {
      content: 'counter(custom-counter)',
      color: theme.palette.common.white,
      ...(theme.typography.h6 as CSSObject),
      position: 'absolute',
      backgroundColor: gray[800],
      borderRadius: '50%',
      textAlign: 'center',
      width: 24,
      height: 24,
      top: 0,
      left: -24,
      lineHeight: '24px'
    }
  },
  categoryTitle: {
    borderBottom: `1px solid ${theme.palette.divider}`,
    marginBottom: 12,
    paddingBottom: 8,
    marginTop: 38,
    '& h2': { margin: 0 }
  },
  categoryGrid: { display: 'flex', flexWrap: 'wrap' },
  moduleItem: {
    flexBasis: '44%',
    maxWidth: 430,
    marginRight: 55,
    paddingBottom: 12,
    marginBottom: 12
  },
  moduleVersion: { marginTop: 8 }
}));

const CategoryModules = ({ category }: { category: string }) => {
  const { classes } = useStyles();
  const modules = useAppSelector(selectCategoryModules(category));
  if (modules.length === 0) return null;
  return (
    <Box>
      <Box className={classes.categoryTitle}>
        <Typography variant="h2">Modules for {category}</Typography>
      </Box>
      <Box className={classes.categoryGrid}>
        {modules.map(module => (
          <Box key={module.name} className={classes.moduleItem}>
            <ModuleSummary module={module} />
            <Typography variant="subtitle2" className={classes.moduleVersion}>
              version: {module.version}
            </Typography>
          </Box>
        ))}
      </Box>
    </Box>
  );
};

export const ProjectView = () => {
  const { classes } = useStyles();
  const dispatch = useAppDispatch();
  const navigate = useNavigate();
  const { id } = useParams();

  const project = useAppSelector(selectCurrentProject);
  const addedModules = useAppSelector(selectAddedModules);
  const modulesLoaded = useAppSelector(selectModulesLoaded);
  const vcsSync = useAppSelector(selectVcsSync);

  const [quickstartDismissed, setQuickstartDismissed] = useState(false);
  const [masterfilesOpen, setMasterfilesOpen] = useState(false);

  useEffect(() => {
    if (!id) return;
    localStorage.setItem('projectID', id);
    dispatch(loadProjectInfo(id));
    CATEGORIES.forEach(category => dispatch(fetchCategoryModules(category)));
  }, [id, dispatch]);

  // Offer to install masterfiles right after a project is created (non-classic)
  // when it isn't present yet, mirroring the legacy addedModules watcher.
  useEffect(() => {
    if (!modulesLoaded || !project || project.classic_policy_set !== false) return;
    if (sessionStorage.getItem(PROJECT_CREATED_KEY) !== String(project.id)) return;
    if (addedModules.some(module => module.name === MASTERFILES_MODULE)) return;
    sessionStorage.removeItem(PROJECT_CREATED_KEY);
    setMasterfilesOpen(true);
  }, [modulesLoaded, project, addedModules]);

  const onMasterfilesConfirm = (version: string) => {
    if (!project) return;
    setMasterfilesOpen(false);
    const payload =
      version === MASTER_VERSION
        ? { projectId: project.id, url: MASTERFILES_REPOSITORY }
        : { projectId: project.id, name: MASTERFILES_MODULE, version };
    dispatch(addModuleToProject(payload))
      .unwrap()
      .then(() => {
        notify.success('Module successfully added.');
        dispatch(refreshProjectStatus(project.id));
        dispatch(loadProjectInfo(project.id));
      })
      .catch(() => notify.error('Unable to add masterfiles module.'));
  };

  const showQuickstart =
    project != null &&
    !project.classic_policy_set &&
    !quickstartDismissed &&
    !(
      addedModules.length > 1 &&
      addedModules.some(module => module.name === MASTERFILES_MODULE) &&
      project.pushed_at != null &&
      vcsSync?.isSynchronised
    );

  return (
    <>
      <Box className={classes.welcome}>
        <Box className={classes.welcomeText}>
          <Typography variant="h1">Welcome to CFEngine Build</Typography>
          <Typography variant="subtitle1" className={classes.welcomeSubtitle}>
            Here you can add and configure modules easily to your projects and help you to automate the process with
            less effort.
          </Typography>
          <Box className={classes.welcomeButton}>
            <Button
              variant="contained"
              color="secondary"
              endIcon={<KeyboardArrowRightIcon />}
              onClick={() => navigate('/modules')}
            >
              Find modules
            </Button>
          </Box>
        </Box>
        <Box className={classes.illustration} />
      </Box>

      {showQuickstart && (
        <Box>
          <Typography className={classes.quickstartHelp}>
            You have not yet finished the setup. Follow the guide to start your project today!
          </Typography>
          <Box className={classes.quickstartCard}>
            <Box className={classes.quickstartTop}>
              <Typography variant="h2">Quickstart guide</Typography>
              <Button
                variant="text"
                color="inherit"
                startIcon={<CloseIcon />}
                onClick={() => setQuickstartDismissed(true)}
              >
                Dismiss
              </Button>
            </Box>
            <Box className={classes.quickstartBody}>
              <span>
                Get started using CFEngine build to manage, set up and deploy your first set of modules in Mission
                Portal.
              </span>
              <ol>
                <li>
                  <div>Add masterfiles module</div>
                  <span>
                    <Link component={RouterLink} to="/modules/masterfiles">
                      masterfiles
                    </Link>{' '}
                    is the default policy that is
                    included in the CFEngine packages, so it is already running on your hub.
                  </span>
                </li>
                <li>
                  <div>Add another module</div>
                  <span>
                    Explore and add modules you would like. We recommend adding{' '}
                    <Link component={RouterLink} to="/modules/inventory-sudoers">
                      inventory-sudoers
                    </Link>{' '}
                    or{' '}
                    <Link component={RouterLink} to="/modules/compliance-report-os-is-vendor-supported/">
                      supported-operating-system
                    </Link>{' '}
                    to start.
                  </span>
                </li>
                <li>
                  <div>Deploy policy set</div>
                  <span>Click Deploy button on the top of the page to deploy your changes.</span>
                </li>
                <li>
                  <div>Set up git repo sync</div>
                  <span>Set up the git repo sync to update the working files from Mission Portal.</span>
                </li>
              </ol>
            </Box>
          </Box>
        </Box>
      )}

      {CATEGORIES.map(category => (
        <CategoryModules key={category} category={category} />
      ))}

      <MasterfilesVersionDialog
        open={masterfilesOpen}
        onClose={() => setMasterfilesOpen(false)}
        onConfirm={onMasterfilesConfirm}
      />
    </>
  );
};
