import { mdiChartTimelineVariant, mdiOfficeBuildingCogOutline } from '@mdi/js'
import axios from 'axios'
import Head from 'next/head'
import React, { ReactElement, useEffect, useMemo, useState } from 'react'
import { Field, Form, Formik } from 'formik'
import { useRouter } from 'next/router'

import BaseButton from '../../components/BaseButton'
import BaseButtons from '../../components/BaseButtons'
import BaseDivider from '../../components/BaseDivider'
import CardBox from '../../components/CardBox'
import ConnectedEntityCard from '../../components/ConnectedEntityCard'
import ConnectedEntityNotice from '../../components/ConnectedEntityNotice'
import FormField from '../../components/FormField'
import NotificationBar from '../../components/NotificationBar'
import SectionMain from '../../components/SectionMain'
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
import { SelectFieldMany } from '../../components/SelectFieldMany'
import { SwitchField } from '../../components/SwitchField'
import { getPageTitle } from '../../config'
import {
  getOrganizationManageHref,
  getOrganizationViewHref,
  getTenantSetupHref,
  mergeEntityOptions,
} from '../../helpers/organizationTenants'
import { hasPermission } from '../../helpers/userPermissions'
import LayoutAuthenticated from '../../layouts/Authenticated'
import { useAppDispatch, useAppSelector } from '../../stores/hooks'
import { fetch, update } from '../../stores/tenants/tenantsSlice'

const defaultInitialValues = {
  name: '',
  slug: '',
  legal_name: '',
  primary_domain: '',
  timezone: '',
  default_currency: '',
  is_active: false,
  organizations: [],
  properties: [],
  audit_logs: [],
}

const EditTenantsPage = () => {
  const router = useRouter()
  const dispatch = useAppDispatch()
  const { tenants } = useAppSelector((state) => state.tenants)
  const { currentUser } = useAppSelector((state) => state.auth)

  const [baseInitialValues, setBaseInitialValues] = useState(defaultInitialValues)
  const [organizationPrefillOptions, setOrganizationPrefillOptions] = useState<any[]>([])
  const [linkedOrganization, setLinkedOrganization] = useState<{ id: string; name: string } | null>(null)
  const [prefillError, setPrefillError] = useState('')

  const { id } = router.query
  const tenantId = useMemo(() => (typeof id === 'string' ? id : ''), [id])
  const organizationId = useMemo(
    () => (typeof router.query.organizationId === 'string' ? router.query.organizationId : ''),
    [router.query.organizationId],
  )
  const organizationNameFromQuery = useMemo(
    () => (typeof router.query.organizationName === 'string' ? router.query.organizationName : ''),
    [router.query.organizationName],
  )

  const canReadOrganizations = hasPermission(currentUser, 'READ_ORGANIZATIONS')
  const canUpdateOrganizations = hasPermission(currentUser, 'UPDATE_ORGANIZATIONS')

  const initialValues = useMemo(
    () => ({
      ...baseInitialValues,
      organizations: mergeEntityOptions(baseInitialValues.organizations, organizationPrefillOptions),
    }),
    [baseInitialValues, organizationPrefillOptions],
  )

  useEffect(() => {
    if (!id) {
      return
    }

    dispatch(fetch({ id }))
  }, [dispatch, id])

  useEffect(() => {
    if (!tenants || typeof tenants !== 'object' || Array.isArray(tenants)) {
      return
    }

    setBaseInitialValues({
      ...defaultInitialValues,
      name: tenants.name || '',
      slug: tenants.slug || '',
      legal_name: tenants.legal_name || '',
      primary_domain: tenants.primary_domain || '',
      timezone: tenants.timezone || '',
      default_currency: tenants.default_currency || '',
      is_active: Boolean(tenants.is_active),
      organizations: Array.isArray(tenants.organizations) ? tenants.organizations : [],
      properties: Array.isArray(tenants.properties) ? tenants.properties : [],
      audit_logs: Array.isArray(tenants.audit_logs) ? tenants.audit_logs : [],
    })
  }, [tenants])

  useEffect(() => {
    if (!router.isReady) {
      return
    }

    if (!organizationId) {
      setLinkedOrganization(null)
      setOrganizationPrefillOptions([])
      setPrefillError('')
      return
    }

    let isActive = true

    const loadOrganization = async () => {
      try {
        setPrefillError('')

        const { data } = await axios.get(`/organizations/${organizationId}`)

        if (!isActive) {
          return
        }

        const organizationOption = data?.id ? [{ id: data.id, name: data.name }] : []

        setLinkedOrganization(data?.id ? { id: data.id, name: data.name } : null)
        setOrganizationPrefillOptions(organizationOption)
      } catch (error) {
        console.error('Failed to prefill tenant edit from organization:', error)

        if (!isActive) {
          return
        }

        setLinkedOrganization(
          organizationId
            ? {
                id: organizationId,
                name: organizationNameFromQuery || 'Selected organization',
              }
            : null,
        )
        setOrganizationPrefillOptions(
          organizationId
            ? [
                {
                  id: organizationId,
                  name: organizationNameFromQuery || 'Selected organization',
                },
              ]
            : [],
        )
        setPrefillError('We could not load the full organization record, but you can still keep or remove the preselected organization below.')
      }
    }

    loadOrganization()

    return () => {
      isActive = false
    }
  }, [organizationId, organizationNameFromQuery, router.isReady])

  const handleSubmit = async (data) => {
    const resultAction = await dispatch(update({ id, data }))

    if (!update.fulfilled.match(resultAction)) {
      return
    }

    await router.push('/tenants/tenants-list')
  }

  const linkedOrganizations = Array.isArray(initialValues.organizations) ? initialValues.organizations : []

  return (
    <>
      <Head>
        <title>{getPageTitle('Edit tenant')}</title>
      </Head>
      <SectionMain>
        <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Edit tenant" main>
          {''}
        </SectionTitleLineWithButton>

        <NotificationBar
          color="info"
          icon={mdiOfficeBuildingCogOutline}
          button={<BaseButton href="/organizations/organizations-list" color="info" label="Browse organizations" small />}
        >
          Keep tenant-wide settings here, and use the organizations field below to control which workspaces belong to
          this tenant.
        </NotificationBar>

        <CardBox>
          {linkedOrganization ? (
            <div className="mb-6 rounded-xl border border-blue-200 bg-blue-50 px-4 py-3 text-sm text-blue-900 dark:border-blue-900 dark:bg-blue-950/40 dark:text-blue-100">
              <p className="font-semibold">Organization ready to link: {linkedOrganization.name}</p>
              <p className="mt-1 leading-6">
                This organization is preselected below so you can attach it to this tenant in the same save.
              </p>
              <div className="mt-3 flex flex-col gap-2 sm:flex-row">
                <BaseButton
                  href={getOrganizationViewHref(linkedOrganization.id, tenantId, tenantNameForLinks)}
                  color="info"
                  outline
                  small
                  label="View organization"
                />
                <BaseButton
                  href={getTenantSetupHref(linkedOrganization.id, linkedOrganization.name)}
                  color="white"
                  outline
                  small
                  label="Create separate tenant instead"
                />
              </div>
            </div>
          ) : null}

          {prefillError ? (
            <div className="mb-6 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900 dark:border-amber-900 dark:bg-amber-950/40 dark:text-amber-100">
              {prefillError}
            </div>
          ) : null}

          <Formik enableReinitialize initialValues={initialValues} onSubmit={(values) => handleSubmit(values)}>
            {({ values }) => {
              const tenantNameForLinks = values.name || initialValues.name || tenants?.name || ''

              return (
                <Form>
                  <ConnectedEntityNotice
                    contextLabel={linkedOrganization ? linkedOrganization.name : undefined}
                    contextHref={linkedOrganization ? getOrganizationViewHref(linkedOrganization.id, tenantId, tenantNameForLinks) : undefined}
                    contextActionLabel="View organization"
                    description={
                      <>
                        Tenants hold shared settings, while organizations are the workspaces connected to them.
                        {linkedOrganizations.length
                          ? ` ${linkedOrganizations.length} organization${linkedOrganizations.length === 1 ? '' : 's'} currently linked.`
                          : ' No organizations are linked yet.'}
                        {linkedOrganization ? ` ${linkedOrganization.name} is already preselected from the organization flow.` : ''}
                      </>
                    }
                    actions={[
                      {
                        href: '/organizations/organizations-list',
                        label: 'Browse organizations',
                        color: 'info',
                        outline: true,
                      },
                      ...(linkedOrganization
                        ? canUpdateOrganizations
                          ? [
                              {
                                href: getOrganizationManageHref(linkedOrganization.id, tenantId, tenantNameForLinks),
                                label: 'Back to organization',
                                color: 'white',
                                outline: true,
                              },
                            ]
                          : canReadOrganizations
                            ? [
                                {
                                  href: getOrganizationViewHref(linkedOrganization.id, tenantId, tenantNameForLinks),
                                  label: 'View organization',
                                  color: 'white',
                                  outline: true,
                                },
                              ]
                            : []
                        : []),
                    ]}
                  />

                  <FormField
                label="Tenant name"
                labelFor="name"
                help="Use the customer-facing or workspace name for this tenant."
              >
                <Field name="name" id="name" placeholder="Acme Hospitality" />
              </FormField>

              <FormField
                label="Tenant slug"
                labelFor="slug"
                help="Short internal identifier, often URL-friendly. Example: acme-hospitality"
              >
                <Field name="slug" id="slug" placeholder="acme-hospitality" />
              </FormField>

              <FormField label="Legal name" labelFor="legal_name" help="Optional registered business name.">
                <Field name="legal_name" id="legal_name" placeholder="Acme Hospitality LLC" />
              </FormField>

              <FormField
                label="Primary domain"
                labelFor="primary_domain"
                help="Optional domain used by this tenant, such as app.acme.com"
              >
                <Field name="primary_domain" id="primary_domain" placeholder="app.acme.com" />
              </FormField>

              <FormField label="Timezone" labelFor="timezone" help="Example: America/New_York">
                <Field name="timezone" id="timezone" placeholder="America/New_York" />
              </FormField>

              <FormField label="Default currency" labelFor="default_currency" help="Example: USD">
                <Field name="default_currency" id="default_currency" placeholder="USD" />
              </FormField>

              <FormField label="Active tenant" labelFor="is_active" help="Turn this on when the tenant is ready to use.">
                <Field name="is_active" id="is_active" component={SwitchField}></Field>
              </FormField>

              <div className="mb-6 rounded-xl border border-dashed border-gray-300 bg-gray-50 p-4 dark:border-dark-700 dark:bg-dark-800">
                <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                  <div>
                    <p className="font-semibold text-gray-700 dark:text-gray-100">Linked organizations</p>
                    <p className="mt-1 text-sm leading-6 text-gray-600 dark:text-gray-300">
                      {linkedOrganizations.length
                        ? `${linkedOrganizations.length} organization${linkedOrganizations.length === 1 ? '' : 's'} will stay attached to this tenant after you save.`
                        : 'No organizations are currently linked. Add one below when this tenant should own a workspace.'}
                    </p>
                  </div>
                  <BaseButton
                    href="/organizations/organizations-new"
                    color="white"
                    outline
                    small
                    label="Create organization"
                    className="w-full sm:w-auto"
                  />
                </div>

                {linkedOrganizations.length ? (
                  <div className="mt-4 grid gap-3 sm:grid-cols-2">
                    {linkedOrganizations.map((organization: any) => (
                      <ConnectedEntityCard
                        key={organization.id}
                        entityLabel="Organization"
                        title={organization.name || 'Unnamed organization'}
                        actions={[
                          ...(canReadOrganizations
                            ? [
                                {
                                  href: getOrganizationViewHref(organization.id, tenantId, tenantNameForLinks),
                                  label: 'View organization',
                                  color: 'info',
                                  outline: true,
                                },
                              ]
                            : []),
                          ...(canUpdateOrganizations
                            ? [
                                {
                                  href: getOrganizationManageHref(organization.id, tenantId, tenantNameForLinks),
                                  label: 'Edit organization',
                                  color: 'info',
                                },
                              ]
                            : []),
                        ]}
                        helperText={canUpdateOrganizations ? 'Context preserved when editing this organization.' : undefined}
                      />
                    ))}
                  </div>
                ) : null}
              </div>

              <FormField
                label="Organizations"
                labelFor="organizations"
                help={
                  linkedOrganization
                    ? `${linkedOrganization.name} has been preselected. Keep it here to link that organization to this tenant.`
                    : 'Link the organizations that belong to this tenant.'
                }
              >
                <Field
                  name="organizations"
                  id="organizations"
                  itemRef={'organizations'}
                  options={initialValues.organizations}
                  component={SelectFieldMany}
                  showField={'name'}
                ></Field>
              </FormField>

              <FormField label="Properties" labelFor="properties" help="Optional: attach properties managed by this tenant.">
                <Field
                  name="properties"
                  id="properties"
                  itemRef={'properties'}
                  options={initialValues.properties}
                  component={SelectFieldMany}
                  showField={'name'}
                ></Field>
              </FormField>

              <FormField
                label="Audit logs"
                labelFor="audit_logs"
                help="Optional: keep existing audit log links if you use them for tenant-level reporting."
              >
                <Field
                  name="audit_logs"
                  id="audit_logs"
                  itemRef={'audit_logs'}
                  options={initialValues.audit_logs}
                  component={SelectFieldMany}
                  showField={'action'}
                ></Field>
              </FormField>

              <BaseDivider />

                  <BaseButtons
                    type="justify-start sm:justify-end"
                    className="items-stretch sm:items-center"
                    classAddon="w-full sm:w-auto mr-0 sm:mr-3 mb-3"
                  >
                    <BaseButton type="submit" color="info" label="Save changes" />
                    <BaseButton type="reset" color="info" outline label="Reset" />
                    <BaseButton
                      type="reset"
                      color="danger"
                      outline
                      label="Cancel"
                      onClick={() => router.push('/tenants/tenants-list')}
                    />
                  </BaseButtons>
                </Form>
              )
            }}
          </Formik>
        </CardBox>
      </SectionMain>
    </>
  )
}

EditTenantsPage.getLayout = function getLayout(page: ReactElement) {
  return <LayoutAuthenticated permission={'UPDATE_TENANTS'}>{page}</LayoutAuthenticated>
}

export default EditTenantsPage
