import {
  Badge,
  Button,
  Card,
  Center,
  Code,
  Group,
  Loader,
  SimpleGrid,
  Stack,
  Typography
} from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { IconFileSearch02 } from '@tidbcloud/uikit/icons'
import { useEffect, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'

import { cloudConfigControllerGetMetaProfile } from 'apiClient/services/devops'
import {
  CloudConfigControllerGetTemplateClusterType,
  CloudconfigClusterType,
  CloudconfigMetaProfile
} from 'apiClient/services/devops/interface'

type Props =
  | {
      profile?: CloudconfigMetaProfile
      profile_id?: undefined
      cluster_type?: undefined
      fetchIfNeeded?: false
    }
  | {
      profile?: undefined
      profile_id: string
      cluster_type: CloudconfigClusterType
      fetchIfNeeded?: true
    }

type ComponentImageTagRow = {
  component: string
  image_tag: unknown
  version: unknown
}

type ConfigCustomTemplateRow = {
  config_type: string
  id: unknown
}

const EmptyState = ({ label }: { label: string }) => (
  <Center h={96}>
    <Typography variant="body-sm" c="carbon.6">
      {label}
    </Typography>
  </Center>
)

const DetailItem = ({
  label,
  value
}: {
  label: string
  value?: React.ReactNode
}) => (
  <Stack gap={2}>
    <Typography variant="body-sm" c="carbon.6">
      {label}
    </Typography>
    <div
      style={{
        color: 'var(--mantine-color-carbon-9)',
        fontSize: 13,
        lineHeight: 1.5
      }}
    >
      {value || '-'}
    </div>
  </Stack>
)

const getCodeValue = (value?: unknown) => {
  if (!value) {
    return (
      <Typography variant="body-sm" c="carbon.5">
        -
      </Typography>
    )
  }

  const text = String(value)

  return (
    <Code
      title={text}
      style={{
        display: 'inline-block',
        maxWidth: 260,
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        verticalAlign: 'middle',
        whiteSpace: 'nowrap'
      }}
    >
      {text}
    </Code>
  )
}

export default function ReadOnlyMetaProfile(props: Props) {
  const [profile, setProfile] = useState<CloudconfigMetaProfile | undefined>(
    props.profile
  )
  const [loading, setLoading] = useState(false)

  const profileId = props.profile_id
  const clusterType = props.cluster_type

  useEffect(() => {
    if (props.profile) {
      setProfile(props.profile)
      return
    }

    if (!profileId || !clusterType) {
      return
    }

    let mounted = true
    setLoading(true)
    ;(async () => {
      try {
        const data = (
          await cloudConfigControllerGetMetaProfile(profileId, {
            cluster_type:
              clusterType as CloudConfigControllerGetTemplateClusterType
          })
        ).data

        if (mounted) {
          setProfile(data)
        }
      } catch (e) {
        console.error('fetch meta profile failed', e)
        if (mounted) {
          setProfile(undefined)
        }
      } finally {
        if (mounted) {
          setLoading(false)
        }
      }
    })()

    return () => {
      mounted = false
    }
  }, [clusterType, profileId, props.fetchIfNeeded, props.profile])

  const componentImageTags = profile?.component_image_tags || {}
  const componentVersions = profile?.component_versions || {}
  const configCustomTemplates = profile?.config_custom_templates || {}

  const componentImageTagRows = useMemo<ComponentImageTagRow[]>(() => {
    const components = Array.from(
      new Set([
        ...Object.keys(componentImageTags),
        ...Object.keys(componentVersions)
      ])
    )

    return components.map((component) => ({
      component,
      image_tag: componentImageTags[component],
      version: componentVersions[component]
    }))
  }, [componentImageTags, componentVersions])

  const configCustomTemplateRows = useMemo<ConfigCustomTemplateRow[]>(
    () =>
      Object.entries(configCustomTemplates).map(([configType, id]) => ({
        config_type: configType,
        id
      })),
    [configCustomTemplates]
  )

  const componentColumns = useMemo<MRT_ColumnDef<ComponentImageTagRow>[]>(
    () => [
      {
        accessorKey: 'component',
        header: 'Component',
        size: 180
      },
      {
        Cell: ({ row }) => getCodeValue(row.original.version),
        header: 'Version',
        id: 'version',
        size: 160
      },
      {
        Cell: ({ row }) => getCodeValue(row.original.image_tag),
        header: 'Image Tag',
        id: 'image_tag',
        size: 240
      }
    ],
    []
  )

  const templateColumns = useMemo<MRT_ColumnDef<ConfigCustomTemplateRow>[]>(
    () => [
      {
        accessorKey: 'config_type',
        header: 'Config Type',
        size: 220
      },
      {
        Cell: ({ row }) => (
          <Button
            component={Link}
            leftSection={<IconFileSearch02 size={16} />}
            size="sm"
            target="_blank"
            to={`/template/${row.original.id}?cluster_type=${profile?.cluster_type}`}
            rel="noreferrer"
            variant="subtle"
          >
            {String(row.original.id)}
          </Button>
        ),
        header: 'Template ID',
        id: 'id',
        size: 180
      }
    ],
    [profile?.cluster_type]
  )

  if (loading) {
    return (
      <Center h={200}>
        <Loader />
      </Center>
    )
  }

  if (!profile) {
    return <EmptyState label="No profile data" />
  }

  return (
    <Stack gap="md">
      <Card withBorder shadow="xs" padding="md" radius="sm">
        <Stack gap="md">
          <Typography variant="title-md">Profile Information</Typography>
          <SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
            <DetailItem label="Profile ID" value={profile.profile_id} />
            <DetailItem label="Profile Name" value={profile.profile_name} />
            <DetailItem label="Cluster Type" value={profile.cluster_type} />
            <DetailItem label="Description" value={profile.description} />
            <DetailItem
              label="Tags"
              value={
                profile.tags ? (
                  <Group gap={6}>
                    {Object.entries(profile.tags).map(([key, value]) => (
                      <Badge key={key} variant="light">
                        {key}: {String(value)}
                      </Badge>
                    ))}
                  </Group>
                ) : (
                  '-'
                )
              }
            />
          </SimpleGrid>
        </Stack>
      </Card>

      <Card withBorder shadow="xs" padding="md" radius="sm">
        <Stack gap="md">
          <Typography variant="title-md">Components</Typography>
          {componentImageTagRows.length === 0 ? (
            <EmptyState label="None" />
          ) : (
            <ProTable<ComponentImageTagRow>
              columns={componentColumns}
              data={componentImageTagRows}
              enableColumnActions={false}
              enableColumnFilters={false}
              enableDensityToggle={false}
              enableFullScreenToggle={false}
              enableHiding={false}
              enablePagination={false}
              enableSorting={false}
              enableTopToolbar={false}
              getRowId={(row) => row.component}
            />
          )}
        </Stack>
      </Card>

      <Card withBorder shadow="xs" padding="md" radius="sm">
        <Stack gap="md">
          <Typography variant="title-md">Config Custom Templates</Typography>
          {configCustomTemplateRows.length === 0 ? (
            <EmptyState label="None" />
          ) : (
            <ProTable<ConfigCustomTemplateRow>
              columns={templateColumns}
              data={configCustomTemplateRows}
              enableColumnActions={false}
              enableColumnFilters={false}
              enableDensityToggle={false}
              enableFullScreenToggle={false}
              enableHiding={false}
              enablePagination={false}
              enableSorting={false}
              enableTopToolbar={false}
              getRowId={(row) => String(row.id)}
            />
          )}
        </Stack>
      </Card>
    </Stack>
  )
}
