'use client';

import ScoreCard from '@/components/ScoreCard';
import ScoreCardRow from '@/components/ScoreCardRow';
import { formattedDateRangeForPhotos } from '@/photo';
import { FaArrowRight, FaCircleInfo, FaRegCalendar } from 'react-icons/fa6';
import { MdAspectRatio } from 'react-icons/md';
import { PiWarningBold } from 'react-icons/pi';
import { TbSparkles } from 'react-icons/tb';
import { BiGitBranch, BiGitCommit, BiLogoGithub } from 'react-icons/bi';
import {
  TEMPLATE_REPO_BRANCH,
  TEMPLATE_REPO_OWNER,
  TEMPLATE_REPO_NAME,
  VERCEL_GIT_COMMIT_SHA_SHORT,
  VERCEL_GIT_COMMIT_MESSAGE,
  TEMPLATE_REPO_URL_FORK,
  TEMPLATE_REPO_URL_README,
  CATEGORY_VISIBILITY,
  USED_DEPRECATED_ENV_VARS,
} from '@/app/config';
import {
  getAllInsights,
  getGitHubMetaForCurrentApp,
  hasTemplateRecommendations,
  PhotoStats,
} from '.';
import EnvVar from '@/components/EnvVar';
import { IoCheckmarkCircleOutline, IoSyncCircle } from 'react-icons/io5';
import clsx from 'clsx/lite';
import { PATH_ADMIN_PHOTOS_UPDATES } from '@/app/path';
import { LiaBroomSolid } from 'react-icons/lia';
import { IoMdGrid } from 'react-icons/io';
import { RiSpeedMiniLine } from 'react-icons/ri';
import AdminLink from '../AdminLink';
import AdminEmptyState from '../AdminEmptyState';
import { pluralize } from '@/utility/string';
import Tooltip from '@/components/Tooltip';
import { useAppState } from '@/app/AppState';
import ScoreCardContainer from '@/components/ScoreCardContainer';
import IconLens from '@/components/icons/IconLens';
import IconCamera from '@/components/icons/IconCamera';
import IconRecipe from '@/components/icons/IconRecipe';
import IconFilm from '@/components/icons/IconFilm';
import IconFocalLength from '@/components/icons/IconFocalLength';
import IconTag from '@/components/icons/IconTag';
import IconPhoto from '@/components/icons/IconPhoto';
import { HiOutlineDocumentText } from 'react-icons/hi';
import { ReactNode } from 'react';
import MaskedScroll from '@/components/MaskedScroll';
import IconNext from '@/components/icons/IconNext';
import Link from 'next/link';

const DEBUG_COMMIT_SHA = '4cd29ed';
const DEBUG_COMMIT_MESSAGE = 'Long commit message for debugging purposes';
const DEBUG_BEHIND_BY = 9;
const DEBUG_PHOTOS_NEED_SYNC_COUNT = 7;

const TEXT_COLOR_WARNING  = 'text-amber-600 dark:text-amber-500';
const TEXT_COLOR_BLUE     = 'text-blue-600 dark:text-blue-500';

const readmeAnchor = (anchor: string) =>
  <AdminLink href={`${TEMPLATE_REPO_URL_README}#${anchor}`}>
    README/{anchor}
  </AdminLink>;

const renderLabeledEnvVar = (
  label: string,
  variable: string,
  value?: string,
  icon?: ReactNode,
) =>
  <div className="flex flex-col gap-0.5">
    <span className="text-xs uppercase font-medium tracking-wider">
      {label}
    </span>
    {icon
      ? <div className="flex items-center gap-1">
        {icon} <EnvVar {...{ variable, value }} />
      </div>
      :<EnvVar {...{ variable, value }} />}
  </div>;

const renderHighlightText = (
  text: string,
  color: 'blue' | 'yellow' = 'blue',
  truncate = true,
) =>
  <span className={clsx(
    'px-1.5 pb-[1px] rounded-md',
    truncate && 'max-w-full inline-block',
    truncate && 'text-ellipsis whitespace-nowrap overflow-x-clip',
    color === 'blue' && 'text-blue-600 bg-blue-100/60',
    color === 'blue' && 'dark:text-blue-400 dark:bg-blue-900/50',
    color === 'yellow' && 'text-amber-700 bg-amber-100/50',
    color === 'yellow' && 'dark:text-amber-400 dark:bg-amber-900/35',
  )}>
    {text}
  </span>;

const renderWarningIconLarge =
  <PiWarningBold
    size={17}
    className={clsx(
      'translate-x-[0.5px]',
      TEXT_COLOR_WARNING,
    )}
  />;

const renderWarningIconSmall =
  <PiWarningBold
    size={14}
    className="translate-y-[0.5px] text-extra-dim"
  />;

export default function AdminAppInsightsClient({
  codeMeta,
  nextVersion,
  insights,
  usedDeprecatedEnvVars,
  photoStats: {
    photosCount,
    photosCountHidden,
    photosCountNeedSync,
    camerasCount,
    lensesCount,
    tagsCount,
    recipesCount,
    filmsCount,
    focalLengthsCount,
    dateRange,
  },
}: {
  codeMeta?: Awaited<ReturnType<typeof getGitHubMetaForCurrentApp>>
  nextVersion: string
  insights: ReturnType<typeof getAllInsights>
  usedDeprecatedEnvVars: typeof USED_DEPRECATED_ENV_VARS
  photoStats: PhotoStats
}) {
  const { shouldDebugInsights: debug } = useAppState();

  const {
    deprecatedEnvVars,
    noFork,
    forkBehind,
    noAi,
    noRateLimiting,
    noConfiguredDomain,
    noConfiguredMetaTitle,
    noConfiguredMetaDescription,
    photosNeedSync,
    photoMatting,
    gridFirst,
    noStaticOptimization,
  } = insights;

  const { descriptionWithSpaces } =
    formattedDateRangeForPhotos(undefined, dateRange);

  const branchLink = <a
    className="truncate"
    href={codeMeta?.urlBranch}
    target="blank"
  >
    {codeMeta?.branch ?? TEMPLATE_REPO_BRANCH}
  </a>;

  const renderTooltipContent = (content: ReactNode) =>
    <Tooltip
      content={content}
      classNameTrigger="ml-1.5"
      supportMobile
    />;

  return (
    <ScoreCardContainer>
      {(codeMeta || debug) && <>
        <ScoreCard title="Source code">
          {(codeMeta?.didError || debug) &&
            <ScoreCardRow
              icon={<IoSyncCircle
                size={18}
                className={TEXT_COLOR_WARNING}
              />}
              content={<>
                <span>Could not analyze source code</span>
                {renderTooltipContent(
                  'Could not connect to GitHub API. Try refreshing.',
                )}
              </>}
            />}
          {((!codeMeta?.didError && noFork) || debug) &&
            <ScoreCardRow
              icon={<FaCircleInfo 
                size={15}
                className="text-blue-500 translate-y-[1px]"
              />}
              content="This template is not forked"
              expandContent={<>
                <AdminLink href={TEMPLATE_REPO_URL_FORK}>
                  Fork original template
                </AdminLink>
                {' '}
                to receive the latest fixes and features.
                {' '}
                Additional instructions in
                {' '}
                {readmeAnchor('receiving-updates')}.
              </>}
            />}
          {((!codeMeta?.didError && forkBehind) || debug) && <ScoreCardRow
            icon={<IoSyncCircle
              size={18}
              className="text-blue-500"
            />}
            content={<>
              This fork is
              {' '}
              {renderHighlightText(
                pluralize(codeMeta?.behindBy ?? DEBUG_BEHIND_BY, 'commit'),
                'blue',
              )}
              {' '}
              behind
            </>}
            expandContent={<>
              <AdminLink href={codeMeta?.urlRepo ?? ''}>
                Sync your fork
              </AdminLink>
              {' '}
              to receive the latest fixes and features.
            </>}
          />}
          <ScoreCardRow
            icon={<BiLogoGithub size={17} />}
            content={<div
              className="flex flex-wrap gap-x-4 gap-y-1 overflow-auto"
            >
              <div className="flex items-center gap-1 *:whitespace-nowrap">
                <a
                  href={codeMeta?.urlOwner}
                  target="blank"
                >
                  {codeMeta?.owner ?? TEMPLATE_REPO_OWNER}
                </a>
                <div>/</div>
                <a
                  href={codeMeta?.urlRepo}
                  target="blank"
                >
                  {codeMeta?.repo ?? TEMPLATE_REPO_NAME}
                </a>
              </div>
              <div className="hidden sm:flex items-center gap-1 min-w-0">
                <BiGitBranch size={17} />
                {branchLink}
              </div>
            </div>}
          />
          <ScoreCardRow
            className="sm:hidden"
            icon={<BiGitBranch size={17} />}
            content={branchLink}
          />
          <ScoreCardRow
            icon={<BiGitCommit
              size={18}
              className="translate-y-[-0.5px]"
            />}
            content={<a
              href={codeMeta?.urlCommit}
              target="blank"
              className="flex items-center gap-2"
            >
              <span className="text-medium hidden sm:inline-block">
                {VERCEL_GIT_COMMIT_SHA_SHORT ?? DEBUG_COMMIT_SHA}
              </span>
              <span className="truncate">
                {VERCEL_GIT_COMMIT_MESSAGE ?? DEBUG_COMMIT_MESSAGE}
              </span>
            </a>}
          />
          <ScoreCardRow
            icon={<IconNext className="self-start translate-y-px" />}
            content={<Link
              // eslint-disable-next-line max-len
              href={`https://github.com/vercel/next.js/releases/tag/v${nextVersion}`}
              target="blank"
            >
              Next.js {nextVersion}
            </Link>}
          />
        </ScoreCard>
      </>}
      <ScoreCard title="Template recommendations">
        {(hasTemplateRecommendations(insights) || debug)
          ? <>
            {(deprecatedEnvVars || debug) && <ScoreCardRow
              icon={renderWarningIconLarge}
              content={isExpanded => renderHighlightText(
                'Update environment variables',
                'yellow',
                !isExpanded,
              )}
              expandContent={<div className="flex flex-col gap-2">
                Future versions of this template may not build correctly
                with the following deprecated environment variables:
                <div className="space-y-1">
                  {usedDeprecatedEnvVars.map(({ old, replacement }) => (
                    <MaskedScroll
                      key={old}
                      className={clsx(
                        'inline-flex items-center gap-3',
                        'overflow-y-hidden',
                      )}
                      direction="horizontal"
                    >
                      <div className={clsx(
                        'inline-flex items-center gap-1.5',
                        'text-xs font-medium',
                      )}>
                        {renderWarningIconSmall}
                        {old}
                      </div>
                      <FaArrowRight
                        size={11}
                        className="shrink-0 text-extra-dim"
                      />
                      <EnvVar variable={replacement} maskScroll={false} />
                    </MaskedScroll>
                  ))}
                </div>
              </div>}
            />}
            {(noRateLimiting || debug) && <ScoreCardRow
              icon={renderWarningIconLarge}
              content={isExpanded => renderHighlightText(
                'Enable rate limiting',
                'yellow',
                !isExpanded,
              )}
              expandContent={<>
                Create Upstash Redis store from storage tab on
                Vercel dashboard and link to this project to
                prevent unexpected usage by enabling rate limiting.
              </>}
            />}
            {(noConfiguredDomain || debug) && <ScoreCardRow
              icon={renderWarningIconLarge}
              content={isExpanded => renderHighlightText(
                'Configure domain',
                'yellow',
                !isExpanded,
              )}
              expandContent={<>
                Not setting an explicit domain may cause certain features
                to behave unexpectedly. Domains are stored in
                {' '}
                <EnvVar
                  variable="NEXT_PUBLIC_DOMAIN"
                  trailingContent="."
                />
              </>}
            />}
            {(
              noConfiguredMetaTitle ||
              noConfiguredMetaDescription ||
              debug
            ) && <ScoreCardRow
              icon={<HiOutlineDocumentText
                size={18}
                className="translate-x-[1px] translate-y-[-1px]"
              />}
              content="Configure meta"
              expandContent={<>
                Configure site title (visible in search results and browser tab)
                and site description (visible in search results):
                {' '}
                <div className="flex flex-col gap-y-4 mt-3">
                  {(
                    noConfiguredMetaTitle ||
                    debug
                  ) && renderLabeledEnvVar(
                    'Site title',
                    'NEXT_PUBLIC_META_TITLE',
                  )}
                  {(
                    noConfiguredMetaDescription ||
                    debug
                  ) && renderLabeledEnvVar(
                    'Site description',
                    'NEXT_PUBLIC_META_DESCRIPTION',
                  )}
                </div>
              </>}
            />}
            {(noStaticOptimization || debug) && <ScoreCardRow
              icon={<RiSpeedMiniLine
                size={19}
                className="translate-x-[1px] translate-y-[-1.5px]"
              />}
              content="Speed up page load times"
              expandContent={<>
                Improve load times by enabling static optimization:
                <div className="flex flex-col gap-y-4 mt-3">
                  {renderLabeledEnvVar(
                    'Photo pages',
                    'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTOS',
                    '1',
                  )}
                  {renderLabeledEnvVar(
                    'Photo OG images',
                    'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_OG_IMAGES',
                    '1',
                  )}
                  {renderLabeledEnvVar(
                    'Category pages (tags, cameras, etc.)',
                    'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORIES',
                    '1',
                  )}
                  {renderLabeledEnvVar(
                    'Category OG images',
                    'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORY_OG_IMAGES',
                    '1',
                  )}
                  <span>
                    See {readmeAnchor('performance')} for cost implications.
                  </span>
                </div>
              </>}
            />}
            {(noAi || debug) && <ScoreCardRow
              icon={<TbSparkles size={17} />}
              content="Improve SEO + accessibility with AI"
              expandContent={<>
                Enable automatic AI text generation
                {' '}
                by setting <EnvVar
                  variable="OPENAI_SECRET_KEY"
                  trailingContent="."
                />
                {' '}
                Further instruction and cost considerations in
                {' '}
                {readmeAnchor('ai-text-generation')}.
              </>}
            />}
            {(photoMatting || debug) && <ScoreCardRow
              icon={<MdAspectRatio
                size={17}
                className="rotate-90 translate-x-[-1px]"
              />}
              content="Vertical photos may benefit from matting"
              expandContent={<>
                Enable photo matting to make
                {' '}
                portrait and landscape photos appear more consistent
                {' '}
                <EnvVar
                  variable="NEXT_PUBLIC_MATTE_PHOTOS"
                  value="1"
                  trailingContent="."
                />
              </>}
            />}
            {(gridFirst || debug) && <ScoreCardRow
              icon={<IoMdGrid size={18} className="translate-y-[-1px]" />}
              content="Grid homepage"
              expandContent={<>
                Now that you have enough photos, consider switching your
                {' '}
                default view to grid by setting
                {' '}
                <EnvVar
                  variable="NEXT_PUBLIC_GRID_HOMEPAGE"
                  value="1"
                  trailingContent="."
                />
              </>}
            />}
          </>
          : <AdminEmptyState
            icon={<IoCheckmarkCircleOutline />}
            includeContainer={false}
          >
            No recommendations found
          </AdminEmptyState>}
      </ScoreCard>
      <ScoreCard title="Library Stats">
        {(photosNeedSync || debug) && <ScoreCardRow
          icon={<LiaBroomSolid
            size={19}
            className={clsx(
              'translate-y-[-2px]',
              TEXT_COLOR_BLUE,
            )}
          />}
          content={<>
            {renderHighlightText(
              pluralize(
                photosCountNeedSync || DEBUG_PHOTOS_NEED_SYNC_COUNT,
                'photo',
              ),
              'blue',
            )}
            {' '}
            with updates
            {renderTooltipContent(<>
              Missing data or AI&#8209;generated text
            </>)}
          </>}
          expandPath={PATH_ADMIN_PHOTOS_UPDATES}
        />}
        <ScoreCardRow
          icon={<IconPhoto
            size={15}
            className="translate-y-[0.5px]"
          />}
          content={<>
            {pluralize(photosCount, 'photo')}
            {photosCountHidden > 0 && ` (${photosCountHidden} hidden)`}
          </>}
        />
        {CATEGORY_VISIBILITY.map(category => {
          switch (category) {
            case 'cameras':
              return <ScoreCardRow
                key={category}
                icon={<IconCamera
                  size={15}
                  className="translate-y-[0.5px]"
                />}
                content={pluralize(camerasCount, 'camera')}
              />;
            case 'lenses':
              return <ScoreCardRow
                key={category}
                icon={<IconLens
                  size={15}
                  className="translate-y-[0.5px]"
                />}
                content={pluralize(lensesCount, 'lens', 'lenses')}
              />;
            case 'tags':
              return <ScoreCardRow
                key={category}
                icon={<IconTag
                  size={15}
                  className="translate-x-[1px] translate-y-[1px]"
                />}
                content={pluralize(tagsCount, 'tag')}
              />;
            case 'recipes':
              return recipesCount > 0
                ? <ScoreCardRow
                  key={category}
                  icon={<IconRecipe
                    size={18}
                    className="translate-x-[0.5px] translate-y-[-0.5px]"
                  />}
                  content={pluralize(recipesCount, 'recipe')}
                />
                : null;
            case 'films':
              return filmsCount > 0
                ? <ScoreCardRow
                  key={category}
                  icon={<IconFilm size={15} />}
                  content={pluralize(filmsCount, 'film')}
                />
                : null;
            case 'focal-lengths':
              return <ScoreCardRow
                key={category}
                icon={<IconFocalLength size={14} />}
                content={pluralize(focalLengthsCount, 'focal length')}
              />;
          }
        })}
        {descriptionWithSpaces && <ScoreCardRow
          icon={<FaRegCalendar
            size={13}
            className="translate-y-[1.5px]"
          />}
          content={descriptionWithSpaces}
        />}
      </ScoreCard>
    </ScoreCardContainer>
  );
}
