import {
  Button,
  Dialog,
  FormContainer,
  FormItem,
  Input,
  Notification,
  Select,
  Tabs,
  toast,
} from '@/components/ui'
import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav'
import { SeedTenantDataInput } from '@/proxy/admin/tenant/models'
import {
  deleteTenantDefaultConnectionString,
  getTenantDefaultConnectionString,
  postSeedTenantData,
  putTenantDefaultConnectionString,
} from '@/services/tenant.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik'
import { Suspense, useEffect, useRef, useState } from 'react'
import * as Yup from 'yup'
import { dataSourceTypeOptions } from '../listForm/edit/options'
import { DataSourceTypeEnum } from '@/proxy/form/models'
import { FaEye, FaEyeSlash } from 'react-icons/fa'

export interface ConnectionStringDto {
  id: string
  name: string
  value: string
  isNew?: boolean
  dataSourceType?: number
}

const schemaCs = Yup.object().shape({
  id: Yup.string().required(),
  name: Yup.string().required(),
  dataSourceType: Yup.number().required(),
  value: Yup.string().required(),
})

const schemaSeed = Yup.object().shape({
  id: Yup.string().required(),
  adminEmail: Yup.string().required(),
  adminPassword: Yup.string().required(),
})

function TenantConnectionString({
  open,
  onDialogClose,
  name,
  id,
}: {
  open: boolean
  onDialogClose: () => void
  name: string
  id: string
}) {
  const { translate } = useLocalization()
  const [currentTab, setCurrentTab] = useState('cs')
  const [loading, setLoading] = useState(true)
  const [connectionString, setConnectionString] = useState<ConnectionStringDto>()

  const fetchDataTenants = async () => {
    if (!id) {
      return
    }
    setLoading(true)
    const response = await getTenantDefaultConnectionString(id)
    let value = ''
    let isNew = false

    if (response.data.length == 0) {
      isNew = true
      value = ''
    } else {
      isNew = false
      value = response.data
    }

    setConnectionString({
      id,
      name: 'Default',
      value,
      isNew,
      ...(value && { dataSourceType: value.startsWith('Server') ? 1 : 2 }),
    })
    setLoading(false)
  }

  useEffect(() => {
    fetchDataTenants()
  }, [id])

  const deleteConnectionString = async () => {
    if (!id) {
      return
    }
    setLoading(true)

    try {
      await deleteTenantDefaultConnectionString(id)
      toast.push(
        <Notification type="success" duration={2000}>
          {translate('::AbpTenantManagement.Tenants.ConnectionStringDeleted')}
        </Notification>,
        {
          placement: 'top-end',
        },
      )
      onDialogClose()
    } catch (error) {
      toast.push(
        <Notification type="danger" duration={2000}>
          {'Hata'}
        </Notification>,
        {
          placement: 'top-end',
        },
      )
    } finally {
      setLoading(false)
    }
  }

  const handleSubmit = async (
    values: ConnectionStringDto,
    { setSubmitting }: FormikHelpers<ConnectionStringDto>,
  ) => {
    if (!id) {
      return
    }

    setLoading(true)
    setSubmitting(true)

    try {
      await putTenantDefaultConnectionString(id, values.value)
      toast.push(
        <Notification type="success" duration={2000}>
          {translate('::AbpTenantManagement.Tenants.ConnectionStringSaved')}
        </Notification>,
        {
          placement: 'top-end',
        },
      )

      await fetchDataTenants()
      //onDialogClose()
    } catch (error) {
      toast.push(
        <Notification type="danger" duration={2000}>
          {'Hata'}
        </Notification>,
        {
          placement: 'top-end',
        },
      )
    } finally {
      setLoading(false)
      setSubmitting(false)
    }
  }

  const [pwInputType, setPwInputType] = useState('password')

  const onPasswordVisibleClick = (e: React.MouseEvent<HTMLSpanElement>) => {
    e.preventDefault()
    setPwInputType(pwInputType === 'password' ? 'text' : 'password')
  }

  const passwordVisible = (
    <span className="cursor-pointer" onClick={(e) => onPasswordVisibleClick(e as any)}>
      {pwInputType === 'password' ? <FaEyeSlash /> : <FaEye />}
    </span>
  )

  const handleSubmitSeed = async (
    values: SeedTenantDataInput,
    { setSubmitting }: FormikHelpers<SeedTenantDataInput>,
  ) => {
    if (!id) {
      return
    }

    setLoading(true)
    setSubmitting(true)

    try {
      await postSeedTenantData(values)
      toast.push(
        <Notification type="success" duration={2000}>
          {translate('::AbpTenantManagement.Tenants.DatabaseSeeded')}
        </Notification>,
        {
          placement: 'top-end',
        },
      )

      onDialogClose()
    } catch (error) {
      const errorMessage =
        (error as any)?.response?.data?.error?.message ??
        (error as any)?.response?.data?.message ??
        (error as any)?.message ??
        'İşlem başarısız'

      toast.push(
        <Notification type="warning" duration={10000}>
          {errorMessage}
        </Notification>,
        {
          placement: 'top-end',
        },
      )
    } finally {
      setLoading(false)
      setSubmitting(false)
    }
  }

  if (!connectionString) {
    return <></>
  }

  return (
    <Dialog isOpen={open} onClose={onDialogClose} onRequestClose={onDialogClose}>
      <h5 className="mb-4">{name}</h5>
      <hr className="my-2"></hr>

      <Tabs value={currentTab} onChange={setCurrentTab}>
        <TabList>
          <TabNav key="cs" value="cs">
            Connection String
          </TabNav>
          <TabNav key="seed" value="seed">
            {connectionString.isNew
              ? translate('::Abp.Account.SignUp')
              : translate('::AbpTenantManagement.Tenants.DatabaseSeed')}
          </TabNav>
        </TabList>
      </Tabs>
      <div className="px-4 py-6">
        <Suspense fallback={<></>}>
          {currentTab === 'cs' && (
            <Formik
              initialValues={connectionString}
              validationSchema={schemaCs}
              onSubmit={handleSubmit}
            >
              {({ touched, errors, values, isSubmitting }) => {
                return (
                  <Form>
                    <FormContainer size="sm">
                      <FormItem
                        label={translate('AbpAccount::DisplayName:Name')}
                        invalid={errors.name && touched.name}
                        errorMessage={errors.name}
                      >
                        <Field
                          type="text"
                          autoComplete="off"
                          name="name"
                          placeholder="Name"
                          disabled
                          component={Input}
                        />
                      </FormItem>

                      <FormItem
                        label={translate('::ListForms.ListFormFieldEdit.LookupDataSourceType')}
                        invalid={errors.dataSourceType && touched.dataSourceType}
                        errorMessage={errors.dataSourceType}
                      >
                        <Field
                          type="text"
                          autoComplete="off"
                          name="dataSourceType"
                          placeholder={translate(
                            '::ListForms.ListFormFieldEdit.LookupDataSourceType',
                          )}
                        >
                          {({ field, form }: FieldProps<DataSourceTypeEnum>) => (
                            <Select
                              field={field}
                              form={form}
                              autoFocus
                              isClearable={true}
                              options={dataSourceTypeOptions}
                              value={dataSourceTypeOptions?.filter(
                                (option: any) => option.value === values.dataSourceType,
                              )}
                              onChange={(option) => {
                                form.setFieldValue(field.name, option?.value)

                                if (option?.value == 1)
                                  //PostgreSQL
                                  form.setFieldValue(
                                    'value',
                                    'Server=sql;Database=' +
                                      name +
                                      ';User Id=sa;password=@Password;Trusted_Connection=False;TrustServerCertificate=True;Connection Timeout=60;',
                                  )
                                else if (option?.value == 2)
                                  //MsSql
                                  form.setFieldValue(
                                    'value',
                                    'User ID=sa;Password=@Password;Host=postgres;Port=5432;Database=' +
                                      name +
                                      ';',
                                  )
                              }}
                            />
                          )}
                        </Field>
                      </FormItem>

                      <FormItem
                        label="Connection String"
                        invalid={errors.value && touched.value}
                        errorMessage={errors.value}
                      >
                        <Field
                          textArea="true"
                          type="text"
                          autoComplete="off"
                          name="value"
                          placeholder="Value"
                          component={Input}
                        />
                      </FormItem>

                      <div className="mt-6 flex flex-row justify-end gap-3">
                        <Button
                          disabled={connectionString.isNew}
                          className="mr-auto"
                          type="button"
                          color="red-500"
                          variant="twoTone"
                          onClick={deleteConnectionString}
                        >
                          {translate('::Delete')}
                        </Button>
                        <Button variant="solid" loading={isSubmitting} type="submit">
                          {isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
                        </Button>
                        <Button type="button" variant="plain" onClick={onDialogClose}>
                          {translate('::Cancel')}
                        </Button>
                      </div>
                    </FormContainer>
                  </Form>
                )
              }}
            </Formik>
          )}
          {currentTab === 'seed' && (
            <Formik
              initialValues={{ id, adminEmail: '', adminPassword: '' } as SeedTenantDataInput}
              validationSchema={schemaSeed}
              onSubmit={handleSubmitSeed}
            >
              {({ touched, errors, values, isSubmitting }) => {
                return (
                  <Form>
                    <FormContainer size="sm">
                      <FormItem
                        label={translate('::Abp.Account.EmailAddress')}
                        invalid={errors.adminEmail && touched.adminEmail}
                        errorMessage={errors.adminEmail}
                      >
                        <Field
                          type="text"
                          autoFocus
                          autoComplete="off"
                          name="adminEmail"
                          component={Input}
                        />
                      </FormItem>

                      <FormItem
                        label={translate('::Abp.Identity.Password')}
                        invalid={errors.adminPassword && touched.adminPassword}
                        errorMessage={errors.adminPassword}
                      >
                        <Field
                          type={pwInputType}
                          suffix={passwordVisible}
                          autoComplete="off"
                          name="adminPassword"
                          component={Input}
                        />
                      </FormItem>

                      <div className="mt-6 flex flex-row justify-end gap-3">
                        <Button variant="solid" loading={isSubmitting} type="submit">
                          {isSubmitting
                            ? connectionString.isNew
                              ? translate('::Abp.Identity.UserCreating')
                              : translate('::AbpTenantManagement.Tenants.DatabaseSeeding')
                            : connectionString.isNew
                              ? translate('::Abp.Identity.CreateUser')
                              : translate('::AbpTenantManagement.Tenants.DatabaseSeed')}
                        </Button>
                        <Button type="button" variant="plain" onClick={onDialogClose}>
                          {translate('::Cancel')}
                        </Button>
                      </div>
                    </FormContainer>
                  </Form>
                )
              }}
            </Formik>
          )}
        </Suspense>
      </div>
    </Dialog>
  )
}

export default TenantConnectionString
