import { useEffect, useMemo, useState } from 'react'
import { createPortal } from 'react-dom'
import { X } from 'lucide-react'
import { useT } from '../i18n/useT'
import type { BusinessMessageKey } from '../i18n/messages'
import { ApiError } from '../lib/api'
import {
  assignBusinessAccess,
  type BusinessAccess,
} from '../services/teamService'
import type { BusinessCustomerListItem } from '../services/customerService'
import modalStyles from './VariationsModal.module.css'
import styles from './ChangeUserAccessModal.module.css'

const ANIMATION_MS = 220

const ALL_TEAM_ROLES = ['admin', 'editor', 'viewer'] as const
const BUSINESS_TEAM_ROLES = ['editor', 'viewer'] as const

const TEAM_ROLE_LABEL_KEYS: Record<(typeof ALL_TEAM_ROLES)[number], BusinessMessageKey> = {
  admin: 'customers.access.role.admin',
  editor: 'customers.access.role.editor',
  viewer: 'customers.access.role.viewer',
}

const TEAM_ROLE_DESC_KEYS: Record<(typeof ALL_TEAM_ROLES)[number], BusinessMessageKey> = {
  admin: 'customers.access.role.admin.desc',
  editor: 'customers.access.role.editor.desc',
  viewer: 'customers.access.role.viewer.desc',
}

export interface ChangeUserAccessModalProps {
  open: boolean
  user: BusinessCustomerListItem | null
  /** When true, Admin team role is offered (super-admin only). */
  canAssignAdmin: boolean
  onClose: () => void
  onSaved: (user: BusinessCustomerListItem) => void
}

function displayName(user: BusinessCustomerListItem) {
  const name = [user.firstName, user.lastName].filter(Boolean).join(' ').trim()
  return name || '—'
}

export function ChangeUserAccessModal({
  open,
  user,
  canAssignAdmin,
  onClose,
  onSaved,
}: ChangeUserAccessModalProps) {
  const t = useT()
  const [mounted, setMounted] = useState(open)
  const [closing, setClosing] = useState(false)
  const [access, setAccess] = useState<BusinessAccess>('customer')
  const [teamRole, setTeamRole] = useState('editor')
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState('')

  const teamRoles = useMemo(
    () => (canAssignAdmin ? [...ALL_TEAM_ROLES] : [...BUSINESS_TEAM_ROLES]),
    [canAssignAdmin],
  )

  useEffect(() => {
    if (open && user) {
      setMounted(true)
      setClosing(false)
      const isStaff = Boolean(user.businessMemberId) && !user.isBusinessOwner
      setAccess(isStaff ? 'staff' : 'customer')
      const current = user.teamRole
      if (isStaff && current && teamRoles.includes(current as (typeof ALL_TEAM_ROLES)[number])) {
        setTeamRole(current)
      } else {
        setTeamRole(teamRoles[0] ?? 'editor')
      }
      setError('')
    } else if (mounted) {
      setClosing(true)
      const timer = setTimeout(() => {
        setMounted(false)
        setClosing(false)
      }, ANIMATION_MS)
      return () => clearTimeout(timer)
    }
  }, [open, user, mounted, teamRoles])

  useEffect(() => {
    if (!mounted || closing) return
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose()
    }
    document.addEventListener('keydown', onKey)
    return () => document.removeEventListener('keydown', onKey)
  }, [mounted, closing, onClose])

  if (!mounted || !user) return null

  const canSave =
    !user.isBusinessOwner && (access === 'customer' || Boolean(teamRole))

  async function handleSubmit() {
    if (!user || !canSave) return
    setSubmitting(true)
    setError('')
    try {
      const result = await assignBusinessAccess({
        userId: user.id,
        access,
        roleSlug: access === 'staff' ? teamRole : undefined,
      })

      onSaved({
        ...user,
        businessMemberId:
          access === 'staff'
            ? result.member?.id != null
              ? String(result.member.id)
              : user.businessMemberId
            : null,
        isBusinessOwner: false,
        teamRole: access === 'staff' ? teamRole : null,
      })
      onClose()
    } catch (err) {
      setError(err instanceof ApiError ? err.message : t('customers.access.error'))
    } finally {
      setSubmitting(false)
    }
  }

  return createPortal(
    <div
      className={`${modalStyles.overlay} ${closing ? modalStyles.overlayOut : modalStyles.overlayIn}`}
      onClick={onClose}
    >
      <div
        className={`${modalStyles.modal} ${closing ? modalStyles.modalOut : modalStyles.modalIn}`}
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
        aria-labelledby="change-access-title"
      >
        <div className={modalStyles.header}>
          <div>
            <h3 id="change-access-title" className={modalStyles.title}>
              {t('customers.access.title')}
            </h3>
            <p className={modalStyles.subtitle}>
              {t('customers.access.subtitle', { name: displayName(user) })}
            </p>
          </div>
          <button type="button" className={modalStyles.closeBtn} onClick={onClose} aria-label="Close">
            <X size={18} />
          </button>
        </div>

        <div className={modalStyles.body}>
          {error ? <p className={modalStyles.errorText}>{error}</p> : null}

          <div className={styles.roleList}>
            <label className={styles.roleOption}>
              <input
                type="radio"
                name="business-access"
                value="customer"
                checked={access === 'customer'}
                onChange={() => setAccess('customer')}
                disabled={submitting}
              />
              <span className={styles.roleOptionLabel}>{t('customers.access.customer')}</span>
            </label>
            <label className={styles.roleOption}>
              <input
                type="radio"
                name="business-access"
                value="staff"
                checked={access === 'staff'}
                onChange={() => {
                  setAccess('staff')
                  if (!teamRoles.includes(teamRole as (typeof ALL_TEAM_ROLES)[number])) {
                    setTeamRole(teamRoles[0] ?? 'editor')
                  }
                }}
                disabled={submitting}
              />
              <span className={styles.roleOptionLabel}>{t('customers.access.manager')}</span>
            </label>
          </div>

          {access === 'staff' ? (
            <>
              {!canAssignAdmin ? (
                <p className={styles.roleHint}>{t('customers.access.hintBusiness')}</p>
              ) : null}
              <div className={`${styles.roleList} ${styles.roleListNested}`}>
                {teamRoles.map((slug) => {
                  const role = slug as (typeof ALL_TEAM_ROLES)[number]
                  return (
                    <label key={slug} className={styles.roleOption}>
                      <input
                        type="radio"
                        name="team-role"
                        value={slug}
                        checked={teamRole === slug}
                        onChange={() => setTeamRole(slug)}
                        disabled={submitting}
                      />
                      <span className={styles.roleOptionText}>
                        <span className={styles.roleOptionLabel}>
                          {t(TEAM_ROLE_LABEL_KEYS[role])}
                        </span>
                        <span className={styles.roleOptionDesc}>
                          {t(TEAM_ROLE_DESC_KEYS[role])}
                        </span>
                      </span>
                    </label>
                  )
                })}
              </div>
            </>
          ) : null}

          <div className={modalStyles.actions}>
            <button
              type="button"
              className={modalStyles.cancelBtn}
              onClick={onClose}
              disabled={submitting}
            >
              {t('customers.access.cancel')}
            </button>
            <button
              type="button"
              className={modalStyles.submitBtn}
              onClick={() => void handleSubmit()}
              disabled={submitting || !canSave}
            >
              {t('customers.access.save')}
            </button>
          </div>
        </div>
      </div>
    </div>,
    document.body,
  )
}
