import {
  Button,
  Checkbox,
  DatePicker,
  FormContainer,
  FormItem,
  Input,
  Notification,
  Select,
  Tabs,
  toast,
} from '@/components/ui'
import Dialog from '@/components/ui/Dialog'
import DateTimepicker from '@/components/ui/DatePicker/DateTimepicker'
import Table from '@/components/ui/Table'
import TBody from '@/components/ui/Table/TBody'
import Td from '@/components/ui/Table/Td'
import Th from '@/components/ui/Table/Th'
import THead from '@/components/ui/Table/THead'
import Tr from '@/components/ui/Table/Tr'
import TabContent from '@/components/ui/Tabs/TabContent'
import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav'
import {
  deleteClaimUser,
  getUserDetail,
  postClaimUser,
  putUserDetail,
  putUserLookout,
} from '@/services/identity.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import dayjs from 'dayjs'
import { Field, FieldArray, FieldProps, Form, Formik, FormikHelpers } from 'formik'
import { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { FaLockOpen, FaUser, FaFileAlt, FaTrashAlt } from 'react-icons/fa'
import { useParams } from 'react-router-dom'
import * as Yup from 'yup'
import { SelectBoxOption } from '@/types/shared'
import { ConfirmDialog, Container } from '@/components/shared'
import { AssignedClaimViewModel, UserInfoViewModel } from '@/proxy/admin/models'
import { APP_NAME } from '@/constants/app.constant'

export interface ClaimTypeDto {
  claimType: string
  claimValue: string
}

function UserDetails() {
  const { userId } = useParams()
  const { translate } = useLocalization()
  const [userDetails, setUserDetails] = useState<UserInfoViewModel>()
  const [loading, setLoading] = useState(true)
  const [open, setOpen] = useState(false)
  const [confirmDeleteClaim, setConfirmDeleteClaim] = useState<AssignedClaimViewModel | null>(null)

  const getUser = async () => {
    const { data } = await getUserDetail(userId || '')
    setUserDetails(data)
  }

  useEffect(() => {
    getUser()
  }, [])

  const scheme = Yup.object().shape({
    claimType: Yup.string().required(),
    claimValue: Yup.string().required(),
  })

  const handleSubmit = async (
    values: ClaimTypeDto,
    { setSubmitting }: FormikHelpers<ClaimTypeDto>,
  ) => {
    setLoading(true)
    setSubmitting(true)

    try {
      await postClaimUser({ userId, claimType: values.claimType, claimValue: values.claimValue })
      toast.push(
        <Notification type="success" duration={2000}>
          {translate('::Kaydet')}
        </Notification>,
        {
          placement: 'top-end',
        },
      )
      setOpen(false)
      getUser()
    } catch (error) {
      toast.push(
        <Notification type="danger" duration={2000}>
          {'Hata'}
        </Notification>,
        {
          placement: 'top-end',
        },
      )
    } finally {
      setLoading(false)
      setSubmitting(false)
    }
  }

  return userDetails ? (
    <>
      <Helmet
        titleTemplate={`%s | ${APP_NAME}`}
        title={userDetails.email}
        defaultTitle={APP_NAME}
      ></Helmet>
      <Container>
        <Tabs defaultValue="user">
          <TabList>
            <TabNav value="user" icon={<FaUser />}>
              {translate('::Abp.Identity.User.UserInformation')}
            </TabNav>
            <TabNav value="lockout" icon={<FaLockOpen />}>
              {translate('::Abp.Identity.User.LockoutManagement')}
            </TabNav>
            <TabNav value="claimTypes" icon={<FaFileAlt />}>
              {translate('::Abp.Identity.User.ClaimTypes')}
            </TabNav>
          </TabList>
          <TabContent value="user">
            <div className="mt-5">
              <Formik
                initialValues={userDetails}
                onSubmit={async (values, { resetForm, setSubmitting }) => {
                  setSubmitting(true)
                  await putUserDetail({ ...values })

                  toast.push(
                    <Notification type="success" duration={2000}>
                      {translate('Kaydet')}
                    </Notification>,
                    {
                      placement: 'top-end',
                    },
                  )

                  getUser()
                  setSubmitting(false)
                }}
              >
                {({ touched, errors, resetForm, isSubmitting, values }) => {
                  const userRoleNames = values.userRoleNames
                  const roles = values.roles
                  const branches = values.branches

                  return (
                    <Form>
                      <div className="w-1/2">
                        <FormContainer size="md">
                          <div className="grid grid-cols-1 lg:grid-cols-2 gap-4 w-full">
                            {/* Personal Information */}
                            <div>
                              <FormItem
                                label={translate('::Abp.Identity.User.UserInformation.Name')}
                              >
                                <Field
                                  type="text"
                                  name="name"
                                  placeholder="Name"
                                  component={Input}
                                />
                              </FormItem>
                            </div>

                            {/* Personal Information */}
                            <div>
                              <FormItem
                                label={translate('::Abp.Identity.User.UserInformation.Surname')}
                              >
                                <Field
                                  type="text"
                                  name="surname"
                                  placeholder="Surname"
                                  component={Input}
                                />
                              </FormItem>
                            </div>

                            {/* Şube Management */}
                            <div>
                              <h6 className="mb-4">
                                {translate('::Abp.Identity.User.UserInformation.BranchManagement')}
                              </h6>
                              <div className="border-2 rounded-lg p-4">
                                <FieldArray name="branches">
                                  {({ form, remove, push }) => (
                                    <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 text-center">
                                      {branches && branches.length > 0
                                        ? branches.map((_, index: number) => (
                                            <div key={index} className="p-2">
                                              <FormItem
                                                labelClass="block text-center"
                                                className="mb-0 justify-center"
                                                label={branches[index].name}
                                              >
                                                <Field
                                                  className="mr-0"
                                                  name={`branches[${index}].isAssigned`}
                                                  component={Checkbox}
                                                />
                                              </FormItem>
                                            </div>
                                          ))
                                        : null}
                                    </div>
                                  )}
                                </FieldArray>
                              </div>
                            </div>

                            {/* Role Management */}
                            <div>
                              <h6 className="mb-4">
                                {translate('::Abp.Identity.User.UserInformation.RoleManagement')}
                              </h6>
                              <div className="border-2 rounded-lg p-4">
                                <FieldArray name="roles">
                                  {({ form, remove, push }) => (
                                    <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 text-center">
                                      {roles && roles.length > 0
                                        ? roles.map((_, index: number) => (
                                            <div key={index} className="p-2">
                                              <FormItem
                                                labelClass="block text-center"
                                                className="mb-0 justify-center"
                                                label={roles[index].name}
                                              >
                                                <Field
                                                  className="mr-0"
                                                  name={`roles[${index}].isAssigned`}
                                                  component={Checkbox}
                                                />
                                              </FormItem>
                                            </div>
                                          ))
                                        : null}
                                    </div>
                                  )}
                                </FieldArray>
                              </div>
                            </div>

                            {/* Contact Information */}
                            <div>
                              <h6 className="mb-4">
                                {translate(
                                  '::Abp.Identity.User.UserInformation.ContactInformation',
                                )}
                              </h6>
                              <FormItem
                                label={translate(
                                  '::Abp.Account.EmailAddress',
                                )}
                              >
                                <Field
                                  type="text"
                                  disabled
                                  name="email"
                                  placeholder="Email Address"
                                  component={Input}
                                />
                              </FormItem>
                              <FormItem
                                label={translate('::Abp.Identity.User.UserInformation.PhoneNumber')}
                              >
                                <Field
                                  type="text"
                                  name="phoneNumber"
                                  placeholder="Phone Number"
                                  component={Input}
                                />
                              </FormItem>
                              <FormItem label={translate('::RocketUsername')}>
                                <Field
                                  type="text"
                                  name="rocketUsername"
                                  placeholder={translate('::RocketUsername')}
                                  component={Input}
                                />
                              </FormItem>
                            </div>

                            {/* Account Timestamps */}
                            <div>
                              <h6 className="mb-4">
                                {translate('::Abp.Identity.User.UserInformation.AccountTimestamps')}
                              </h6>
                              <FormItem
                                label={translate(
                                  '::Abp.Identity.User.UserInformation.PasswordChangeTime',
                                )}
                              >
                                <Field name="lastPasswordChangeTime">
                                  {({ field, form }: FieldProps) => (
                                    <DateTimepicker
                                      field={field}
                                      form={form}
                                      value={field.value ? dayjs(field.value).toDate() : null}
                                      placeholder="Select Date"
                                      onChange={(date: any) => {
                                        form.setFieldValue(
                                          field.name,
                                          date
                                            ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss')
                                            : null,
                                        )
                                      }}
                                    />
                                  )}
                                </Field>
                              </FormItem>
                              <FormItem
                                label={translate('::Abp.Identity.User.UserInformation.CreateTime')}
                              >
                                <Field name="creationTime">
                                  {({ field, form }: FieldProps) => (
                                    <Input
                                      field={field}
                                      form={form}
                                      value={
                                        field.value ? dayjs(field.value).format('L LT') : undefined
                                      }
                                      disabled
                                    />
                                  )}
                                </Field>
                              </FormItem>
                              <FormItem
                                label={translate('::Abp.Identity.User.UserInformation.UpdateTime')}
                              >
                                <Field name="lastModificationTime">
                                  {({ field, form }: FieldProps) => (
                                    <Input
                                      field={field}
                                      form={form}
                                      value={
                                        field.value ? dayjs(field.value).format('L LT') : undefined
                                      }
                                      disabled
                                    />
                                  )}
                                </Field>
                              </FormItem>
                            </div>
                          </div>
                        </FormContainer>
                      </div>

                      <div>
                        <Button variant="solid" loading={isSubmitting} type="submit">
                          {isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
                        </Button>
                      </div>
                    </Form>
                  )
                }}
              </Formik>
            </div>
          </TabContent>
          <TabContent value="lockout">
            <div className="mt-5">
              <Formik
                initialValues={userDetails}
                onSubmit={async (values, { setSubmitting }) => {
                  setSubmitting(true)

                  await putUserLookout({ ...values })

                  toast.push(
                    <Notification type="success" duration={2000}>
                      {'Lockout bilgileri kaydedildi.'}
                    </Notification>,
                    {
                      placement: 'top-end',
                    },
                  )

                  getUser()

                  setSubmitting(false)
                }}
              >
                {({ touched, errors, resetForm, isSubmitting, values }) => {
                  const userRoleNames = values.userRoleNames
                  return (
                    <Form>
                      <div className="w-1/2">
                        <FormContainer size="md">
                          <div className="grid grid-cols-1 lg:grid-cols-2 gap-4 w-full">
                            {/* Account Status */}
                            <div>
                              <h6 className="mb-4">
                                {translate('::Abp.Identity.User.LockoutManagement.AccountStatus')}
                              </h6>
                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate('::Abp.Identity.User.LockoutManagement.Status')}
                              >
                                <Field
                                  name="isActive"
                                  placeholder={translate(
                                    '::Abp.Identity.User.LockoutManagement.Status',
                                  )}
                                  component={Checkbox}
                                />
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.AdminVerification',
                                )}
                              >
                                <Field
                                  name="isVerified"
                                  placeholder={translate(
                                    '::Abp.Identity.User.LockoutManagement.AdminVerification',
                                  )}
                                  component={Checkbox}
                                />
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.EmailConfirmed',
                                )}
                              >
                                <Field
                                  name="emailConfirmed"
                                  placeholder={translate(
                                    '::Abp.Identity.User.LockoutManagement.EmailConfirmed',
                                  )}
                                  component={Checkbox}
                                />
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.PhoneNumberConfirmed',
                                )}
                              >
                                <Field
                                  name="phoneNumberConfirmed"
                                  placeholder={translate(
                                    '::Abp.Identity.User.LockoutManagement.PhoneNumberConfirmed',
                                  )}
                                  component={Checkbox}
                                />
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.TwoFactorEnabled',
                                )}
                              >
                                <Field
                                  name="twoFactorEnabled"
                                  placeholder={translate(
                                    '::Abp.Identity.User.LockoutManagement.TwoFactorEnabled',
                                  )}
                                  component={Checkbox}
                                />
                              </FormItem>
                            </div>

                            {/* Login & Lockout Settings */}
                            <div>
                              <h6 className="mb-4">
                                {translate(
                                  '::Abp.Identity.User.LockoutManagement.LoginAndLockoutSettings',
                                )}
                              </h6>
                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.LoginEndDate',
                                )}
                              >
                                <Field name="loginEndDate">
                                  {({ field, form }: FieldProps) => (
                                    <DatePicker
                                      field={field}
                                      form={form}
                                      value={field.value ? dayjs(field.value).toDate() : null}
                                      placeholder={translate(
                                        '::Abp.Identity.User.LockoutManagement.LoginEndDate',
                                      )}
                                      onChange={(date) => {
                                        form.setFieldValue(
                                          field.name,
                                          date
                                            ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss')
                                            : null,
                                        )
                                      }}
                                    />
                                  )}
                                </Field>
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.AccountLockoutEnabled',
                                )}
                              >
                                <Field
                                  name="lockoutEnabled"
                                  placeholder={translate(
                                    '::Abp.Identity.User.LockoutManagement.AccountLockoutEnabled',
                                  )}
                                  component={Checkbox}
                                />
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.AccountLocked',
                                )}
                              >
                                <Field
                                  name="lockUser"
                                  placeholder={translate(
                                    '::Abp.Identity.User.LockoutManagement.AccountLocked',
                                  )}
                                  component={Checkbox}
                                />
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.AccountEndDate',
                                )}
                              >
                                <Field name="lockoutEnd">
                                  {({ field, form }: FieldProps) => (
                                    <DatePicker
                                      field={field}
                                      form={form}
                                      value={field.value ? dayjs(field.value).toDate() : null}
                                      placeholder={translate(
                                        '::Abp.Identity.User.LockoutManagement.AccountEndDate',
                                      )}
                                      onChange={(date) => {
                                        form.setFieldValue(
                                          field.name,
                                          date
                                            ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss')
                                            : null,
                                        )
                                      }}
                                    />
                                  )}
                                </Field>
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.ShouldChangePwOnNextLogin',
                                )}
                              >
                                <Field
                                  name="shouldChangePasswordOnNextLogin"
                                  placeholder={translate(
                                    '::Abp.Identity.User.LockoutManagement.ShouldChangePwOnNextLogin',
                                  )}
                                  component={Checkbox}
                                />
                              </FormItem>

                              <FormItem
                                layout="horizontal"
                                labelClass="!justify-start"
                                labelWidth="50%"
                                label={translate(
                                  '::Abp.Identity.User.LockoutManagement.AccessFailedCount',
                                )}
                              >
                                <Field type="number" name="accessFailedCount" component={Input} />
                              </FormItem>
                            </div>
                          </div>
                        </FormContainer>
                      </div>

                      <div>
                        <Button variant="solid" loading={isSubmitting} type="submit">
                          {isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
                        </Button>
                      </div>
                    </Form>
                  )
                }}
              </Formik>
            </div>
          </TabContent>
          <TabContent value="claimTypes">
            <div className="mt-5 w-1/2">
              <Table compact>
                <THead>
                  <Tr>
                    <Th className="text-center">
                      <Button
                        shape="circle"
                        variant="plain"
                        type="button"
                        size="xs"
                        title="Add"
                        icon={<FaFileAlt />}
                        onClick={async (e) => {
                          setOpen(true)
                        }}
                      />
                    </Th>
                    <Th>{translate('::Abp.Identity.User.ClaimType')}</Th>
                    <Th>{translate('::Abp.Identity.User.ClaimValue')}</Th>
                  </Tr>
                </THead>
                <TBody>
                  {userDetails.claims.filter((a) => a.isAssigned === true) &&
                  userDetails.claims.filter((a) => a.isAssigned === true).length > 0 ? (
                    userDetails.claims.map((claim) => (
                      <Tr key={claim.id}>
                        <Td>
                          <Button
                            shape="circle"
                            variant="plain"
                            type="button"
                            size="xs"
                            title="Delete"
                            icon={<FaTrashAlt />}
                            onClick={() => setConfirmDeleteClaim(claim)}
                          />
                        </Td>
                        <Td>{claim.claimType}</Td>
                        <Td>{claim.claimValue}</Td>
                      </Tr>
                    ))
                  ) : (
                    <Tr>
                      <Td colSpan={3} className="text-center">
                        {translate('::Abp.Identity.User.NoClaimsFound')}
                      </Td>
                    </Tr>
                  )}
                </TBody>
              </Table>
            </div>
          </TabContent>
        </Tabs>
      </Container>

      <Dialog isOpen={open} onClose={() => setOpen(false)} onRequestClose={() => setOpen(false)}>
        <Formik
          initialValues={{ claimType: '', claimValue: '' }}
          validationSchema={scheme}
          onSubmit={handleSubmit}
        >
          {({ touched, errors, values, isSubmitting }) => {
            const claimOptions: SelectBoxOption[] = userDetails?.claims.map((claim) => ({
              value: claim.claimType,
              label: claim.claimType,
            }))

            return (
              <Form>
                <FormContainer size="sm">
                  <FormItem
                    label={translate('::Abp.Identity.User.ClaimType')}
                    invalid={errors.claimType && touched.claimType}
                    errorMessage={errors.claimType}
                  >
                    <Field type="text" name="claimType">
                      {({ field, form }: FieldProps<SelectBoxOption>) => (
                        <Select
                          field={field}
                          form={form}
                          options={claimOptions}
                          isClearable={true}
                          value={claimOptions.filter((option) => option.value === values.claimType)}
                          onChange={(option) => form.setFieldValue(field.name, option?.value)}
                        />
                      )}
                    </Field>
                  </FormItem>

                  <FormItem
                    label={translate('::Abp.Identity.User.ClaimValue')}
                    invalid={errors.claimValue && touched.claimValue}
                    errorMessage={errors.claimValue}
                  >
                    <Field type="text" autoComplete="off" name="claimValue" component={Input} />
                  </FormItem>

                  <div className="mt-6 flex flex-row justify-end gap-3">
                    <Button variant="solid" loading={isSubmitting} type="submit">
                      {isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
                    </Button>
                    <Button type="button" variant="plain" onClick={() => setOpen(false)}>
                      {translate('::Cancel')}
                    </Button>
                  </div>
                </FormContainer>
              </Form>
            )
          }}
        </Formik>
      </Dialog>

      <ConfirmDialog
        isOpen={!!confirmDeleteClaim}
        type="danger"
        title={translate('::DeleteConfirmation')}
        confirmText={translate('::Delete')}
        cancelText={translate('::Cancel')}
        confirmButtonColor="red-600"
        onCancel={() => setConfirmDeleteClaim(null)}
        onConfirm={async () => {
          if (confirmDeleteClaim) {
            await deleteClaimUser(confirmDeleteClaim.id, userId)
            toast.push(
              <Notification type="success" duration={2000}>
                {translate('::Abp.Identity.User.ClaimDeleted')}
              </Notification>,
              { placement: 'top-end' },
            )
            setConfirmDeleteClaim(null)
            getUser()
          }
        }}
      >
        <p>
          <span className="font-semibold">{confirmDeleteClaim?.claimType}</span> claim silmek
          istediğinize emin misiniz?
        </p>
      </ConfirmDialog>
    </>
  ) : (
    <></>
  )
}

export default UserDetails
