import { type ReactNode, useEffect, useMemo, useState } from 'react';

import { Condition } from '@quotalab/react';
import { getObjectValues, isEmpty } from '@quotalab/utils';

import {
  componentNameStyle,
  nameColumnStyle,
  progressCardStyle,
  progressRateTxtStyle,
} from './component-progress-table.css';
import { Flex, Txt } from '../../src/components';
import Table from '../components/Table/table';

type ComponentProgressData = {
  path: string;
  name: string;
  hasTest: boolean;
  hasStory: boolean;
};

const isProgressData = (data: unknown): data is ComponentProgressData => {
  return (
    typeof data === 'object' &&
    data !== null &&
    'path' in data &&
    'name' in data &&
    'hasTest' in data &&
    'hasStory' in data
  );
};

const getVSCFilePath = (path: string) => `vscode://file/${path}`;

const componentProgress = (items: ComponentProgressData[], key: keyof ComponentProgressData) =>
  isEmpty(items) ? 0 : (items.filter((item) => item[key]).length / items.length) * 100;

const ComponentProgressTable = () => {
  const [componentProgressData, setComponentProgressData] = useState<ComponentProgressData[]>([]);

  const isEmpty = useMemo(() => componentProgressData.length === 0, [componentProgressData]);

  const getComponentProgressData = async () => {
    try {
      const data = await fetch('components-coverage.json');
      const convertedData = await data.json();

      if (Array.isArray(convertedData)) {
        setComponentProgressData(convertedData.filter(isProgressData));
      }
    } catch {}
  };

  const storyCompleteRate = useMemo(
    () => componentProgress(componentProgressData, 'hasStory'),
    [componentProgressData]
  );

  const testCompleteRate = useMemo(() => componentProgress(componentProgressData, 'hasTest'), [componentProgressData]);

  useEffect(() => {
    getComponentProgressData();
  }, []);

  const convertedData = getObjectValues(componentProgressData)
    .filter(isProgressData)
    .sort((a, b) => a.name.localeCompare(b.name));

  return (
    <Flex direction="column" gap={8}>
      <Table>
        <Table.Row>
          <Table.HeaderCell className={nameColumnStyle}>컴포넌트</Table.HeaderCell>
          <Table.HeaderCell>Story</Table.HeaderCell>
          <Table.HeaderCell>Test</Table.HeaderCell>
        </Table.Row>
        <Condition
          expression={isEmpty}
          then={
            <Table.Row>
              <Table.Cell>
                <Txt sizing="bodyMedium" weight={600} as="a">
                  Empty
                </Txt>
              </Table.Cell>
            </Table.Row>
          }
          else={convertedData.map((data) => (
            <Table.Row key={data.name}>
              <Table.Cell>
                <Txt weight={600} className={componentNameStyle} as="a" href={getVSCFilePath(data.path)}>
                  {data.name}
                </Txt>
              </Table.Cell>
              <Table.Cell>
                <ProgressTxt isDone={data.hasStory} />
              </Table.Cell>
              <Table.Cell>
                <ProgressTxt isDone={data.hasTest} />
              </Table.Cell>
            </Table.Row>
          ))}
        />
      </Table>
      <Flex gap={8}>
        <ProgressCard title="스토리 커버리지" percent={storyCompleteRate} />
        <ProgressCard title="테스트 커버리지" percent={testCompleteRate} />
      </Flex>
    </Flex>
  );
};

const ProgressTxt = ({ isDone }: { isDone: boolean }) => {
  return (
    <Condition
      expression={isDone}
      then={
        <Txt color="textSuccess" sizing="bodyMedium">
          Done
        </Txt>
      }
      else={
        <Txt color="textPlaceholder" sizing="bodyMedium" whiteSpace="nowrap">
          To do
        </Txt>
      }
    />
  );
};

const ProgressCard = ({ title, percent }: { title: ReactNode; percent: number }) => {
  return (
    <Flex width="100%" className={progressCardStyle} justify="space-between" align="center">
      <Txt sizing="bodyMedium" weight={600}>
        {title}
      </Txt>
      <Flex align="flex-end">
        <Txt as="span" weight={600} sizing="titleLarge" color="textSuccess" className={progressRateTxtStyle}>
          {percent.toFixed(0)}%
        </Txt>
        <Txt as="span" color="textPlaceholder" sizing="bodyMedium">
          /100%
        </Txt>
      </Flex>
    </Flex>
  );
};

export default ComponentProgressTable;
