import { useEffect } from 'react'
import { ControllerRenderProps, UseFormReturn } from 'react-hook-form'
import type { CloudProvider } from 'shared-data'
import {
  Badge,
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'

import { smartRegionToExactRegion } from './ProjectCreation.utils'
import { useProjectCreationPostgresVersionsQuery } from '@/data/config/project-creation-postgres-versions-query'
import { useProjectUnpausePostgresVersionsQuery } from '@/data/config/project-unpause-postgres-versions-query'
import { PostgresEngine, ReleaseChannel } from '@/data/projects/new-project.constants'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'

interface PostgresVersionDetails {
  postgresEngine?: Exclude<PostgresEngine, '13' | '14'>
  releaseChannel?: ReleaseChannel
}

interface PostgresVersionSelectorProps {
  cloudProvider: CloudProvider
  dbRegion: string
  organizationSlug?: string
  field: ControllerRenderProps<any, 'postgresVersionSelection'>
  form: UseFormReturn<any>
  type?: 'create' | 'unpause'
  layout?: 'vertical' | 'horizontal'
  label?: string
}

const formatValue = ({
  postgres_engine,
  release_channel,
}: {
  postgres_engine: string
  release_channel: string
}) => {
  return `${postgres_engine}|${release_channel}`
}

export const extractPostgresVersionDetails = (value: string): PostgresVersionDetails => {
  if (!value) {
    return { postgresEngine: undefined, releaseChannel: undefined }
  }

  const [postgresEngine, releaseChannel] = value.split('|')
  return { postgresEngine, releaseChannel } as PostgresVersionDetails
}

export const PostgresVersionSelector = ({
  cloudProvider,
  dbRegion,
  organizationSlug,
  field,
  form,
  type = 'create',
  layout = 'horizontal',
  label = 'Postgres version',
}: PostgresVersionSelectorProps) => {
  const { data: project } = useSelectedProjectQuery()

  const dbRegionExact = smartRegionToExactRegion(dbRegion)

  const {
    data: createVersions,
    isPending: isLoadingProjectCreateVersions,
    isSuccess,
  } = useProjectCreationPostgresVersionsQuery(
    {
      cloudProvider,
      dbRegion: dbRegionExact,
      organizationSlug,
    },
    { enabled: type === 'create' }
  )

  const { data: unpauseVersions, isPending: isLoadingProjectUnpauseVersions } =
    useProjectUnpausePostgresVersionsQuery(
      { projectRef: project?.ref },
      { enabled: type === 'unpause' }
    )

  const versions =
    type === 'create'
      ? (createVersions?.available_versions ?? [])
      : (unpauseVersions?.available_versions ?? [])
  const availableVersions = versions.sort((a, b) => a.version.localeCompare(b.version)).reverse()
  const { postgresVersionSelection } = form.watch()

  useEffect(() => {
    if (availableVersions.length > 0) {
      const gaVersion = availableVersions.find((x) => x.release_channel === 'ga')
      const defaultValue = gaVersion ? formatValue(gaVersion) : formatValue(availableVersions[0])
      form.setValue('postgresVersionSelection', defaultValue)
    }
  }, [isSuccess, availableVersions, form])

  return (
    <FormItemLayout label={label} layout={layout}>
      <Select
        value={postgresVersionSelection}
        onValueChange={field.onChange}
        disabled={
          availableVersions.length === 0 ||
          (type === 'create' && isLoadingProjectCreateVersions) ||
          (type === 'unpause' && isLoadingProjectUnpauseVersions)
        }
      >
        <SelectTrigger className="[&>:nth-child(1)]:w-full [&>:nth-child(1)]:flex [&>:nth-child(1)]:items-start">
          <SelectValue placeholder="Select a Postgres version for your project" />
        </SelectTrigger>
        <SelectContent>
          <SelectGroup>
            {availableVersions.map((value) => {
              const postgresVersion = value.version
                .split('briven-postgres-')[1]
                .replace('-orioledb', '')
              return (
                <SelectItem
                  key={formatValue(value)}
                  value={formatValue(value)}
                  className="w-full [&>:nth-child(2)]:w-full"
                >
                  <div className="flex flex-row items-center justify-between w-full">
                    <span className="text-foreground">{postgresVersion}</span>
                    <div className="flex flex-row gap-x-2">
                      {value.release_channel !== 'ga' && (
                        <Badge variant="warning">{value.release_channel}</Badge>
                      )}
                      {value.postgres_engine.includes('oriole') && (
                        <Badge variant="default">OrioleDB</Badge>
                      )}
                    </div>
                  </div>
                </SelectItem>
              )
            })}
          </SelectGroup>
        </SelectContent>
      </Select>
    </FormItemLayout>
  )
}
