'use client'

import { useEffect, useMemo, useState } from 'react'
import { useRouter } from 'next/navigation'
import { authFetch, clearToken, getApiBase, getToken } from '../../lib/auth'

type ProfileInfo = {
  username: string
  role: string
  auth_provider: string
  invite_management_enabled?: boolean
}

type ProfileResponse = {
  user: ProfileInfo
}

type OwnedInvite = {
  id: number
  code: string
  label?: string | null
  description?: string | null
  recipient_email?: string | null
  max_uses?: number | null
  use_count: number
  remaining_uses?: number | null
  enabled: boolean
  expires_at?: string | null
  is_expired?: boolean
  is_usable?: boolean
  created_at?: string | null
  updated_at?: string | null
}

type OwnedInvitesResponse = {
  invites?: OwnedInvite[]
  count?: number
  invite_access?: {
    enabled?: boolean
    managed_by_master?: boolean
  }
  master_invite?: {
    id: number
    code: string
    label?: string | null
    description?: string | null
    max_uses?: number | null
    enabled?: boolean
    expires_at?: string | null
    is_usable?: boolean
  } | null
}

type OwnedInviteForm = {
  code: string
  label: string
  description: string
  recipient_email: string
  max_uses: string
  expires_at: string
  enabled: boolean
  send_email: boolean
  message: string
}

const defaultOwnedInviteForm = (): OwnedInviteForm => ({
  code: '',
  label: '',
  description: '',
  recipient_email: '',
  max_uses: '',
  expires_at: '',
  enabled: true,
  send_email: false,
  message: '',
})

const formatDate = (value?: string | null) => {
  if (!value) return 'Never'
  const date = new Date(value)
  if (Number.isNaN(date.valueOf())) return value
  return date.toLocaleString()
}

const isValidEmail = (value: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim())

export default function ProfileInvitesPage() {
  const router = useRouter()
  const [profile, setProfile] = useState<ProfileInfo | null>(null)
  const [inviteStatus, setInviteStatus] = useState<string | null>(null)
  const [inviteError, setInviteError] = useState<string | null>(null)
  const [invites, setInvites] = useState<OwnedInvite[]>([])
  const [inviteSaving, setInviteSaving] = useState(false)
  const [inviteEditingId, setInviteEditingId] = useState<number | null>(null)
  const [inviteForm, setInviteForm] = useState<OwnedInviteForm>(defaultOwnedInviteForm())
  const [inviteAccessEnabled, setInviteAccessEnabled] = useState(false)
  const [inviteManagedByMaster, setInviteManagedByMaster] = useState(false)
  const [masterInviteTemplate, setMasterInviteTemplate] = useState<OwnedInvitesResponse['master_invite']>(null)
  const [loading, setLoading] = useState(true)

  const signupBaseUrl = useMemo(() => {
    if (typeof window === 'undefined') return '/signup'
    return `${window.location.origin}/signup`
  }, [])

  const loadPage = async () => {
    const baseUrl = getApiBase()
    const [profileResponse, invitesResponse] = await Promise.all([
      authFetch(`${baseUrl}/auth/profile`),
      authFetch(`${baseUrl}/auth/profile/invites`),
    ])
    if (!profileResponse.ok || !invitesResponse.ok) {
      if (profileResponse.status === 401 || invitesResponse.status === 401) {
        clearToken()
        router.push('/login')
        return
      }
      throw new Error('Could not load invite tools.')
    }
    const [profileData, inviteData] = (await Promise.all([
      profileResponse.json(),
      invitesResponse.json(),
    ])) as [ProfileResponse, OwnedInvitesResponse]
    const user = profileData?.user ?? {}
    setProfile({
      username: user?.username ?? 'Unknown',
      role: user?.role ?? 'user',
      auth_provider: user?.auth_provider ?? 'local',
      invite_management_enabled: Boolean(user?.invite_management_enabled ?? false),
    })
    setInvites(Array.isArray(inviteData?.invites) ? inviteData.invites : [])
    setInviteAccessEnabled(Boolean(inviteData?.invite_access?.enabled ?? false))
    setInviteManagedByMaster(Boolean(inviteData?.invite_access?.managed_by_master ?? false))
    setMasterInviteTemplate(inviteData?.master_invite ?? null)
  }

  useEffect(() => {
    if (!getToken()) {
      router.push('/login')
      return
    }
    const load = async () => {
      try {
        await loadPage()
      } catch (err) {
        console.error(err)
        setInviteError(err instanceof Error ? err.message : 'Could not load invite tools.')
      } finally {
        setLoading(false)
      }
    }
    void load()
  }, [router])

  const resetInviteEditor = () => {
    setInviteEditingId(null)
    setInviteForm(defaultOwnedInviteForm())
  }

  const editInvite = (invite: OwnedInvite) => {
    setInviteEditingId(invite.id)
    setInviteError(null)
    setInviteStatus(null)
    setInviteForm({
      code: invite.code ?? '',
      label: invite.label ?? '',
      description: invite.description ?? '',
      recipient_email: invite.recipient_email ?? '',
      max_uses: typeof invite.max_uses === 'number' ? String(invite.max_uses) : '',
      expires_at: invite.expires_at ?? '',
      enabled: invite.enabled !== false,
      send_email: false,
      message: '',
    })
  }

  const reloadInvites = async () => {
    const baseUrl = getApiBase()
    const response = await authFetch(`${baseUrl}/auth/profile/invites`)
    if (!response.ok) {
      if (response.status === 401) {
        clearToken()
        router.push('/login')
        return
      }
      throw new Error(`Invite refresh failed: ${response.status}`)
    }
    const data = (await response.json()) as OwnedInvitesResponse
    setInvites(Array.isArray(data?.invites) ? data.invites : [])
    setInviteAccessEnabled(Boolean(data?.invite_access?.enabled ?? false))
    setInviteManagedByMaster(Boolean(data?.invite_access?.managed_by_master ?? false))
    setMasterInviteTemplate(data?.master_invite ?? null)
  }

  const saveInvite = async (event: React.FormEvent) => {
    event.preventDefault()
    const recipientEmail = inviteForm.recipient_email.trim()
    if (!recipientEmail) {
      setInviteError('Recipient email is required.')
      setInviteStatus(null)
      return
    }
    if (!isValidEmail(recipientEmail)) {
      setInviteError('Recipient email must be valid.')
      setInviteStatus(null)
      return
    }
    setInviteSaving(true)
    setInviteError(null)
    setInviteStatus(null)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(
        inviteEditingId == null
          ? `${baseUrl}/auth/profile/invites`
          : `${baseUrl}/auth/profile/invites/${inviteEditingId}`,
        {
          method: inviteEditingId == null ? 'POST' : 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            code: inviteForm.code || null,
            label: inviteForm.label || null,
            description: inviteForm.description || null,
            recipient_email: recipientEmail,
            max_uses: inviteForm.max_uses || null,
            expires_at: inviteForm.expires_at || null,
            enabled: inviteForm.enabled,
            send_email: inviteForm.send_email,
            message: inviteForm.message || null,
          }),
        }
      )
      if (!response.ok) {
        if (response.status === 401) {
          clearToken()
          router.push('/login')
          return
        }
        const text = await response.text()
        throw new Error(text || 'Invite save failed')
      }
      const data = await response.json().catch(() => ({}))
      if (data?.email?.status === 'ok') {
        setInviteStatus(
          `${inviteEditingId == null ? 'Invite created' : 'Invite updated'} and email sent to ${data.email.recipient_email}.`
        )
      } else if (data?.email?.status === 'error') {
        setInviteStatus(
          `${inviteEditingId == null ? 'Invite created' : 'Invite updated'}, but email failed: ${data.email.detail}`
        )
      } else {
        setInviteStatus(inviteEditingId == null ? 'Invite created.' : 'Invite updated.')
      }
      resetInviteEditor()
      await reloadInvites()
    } catch (err) {
      console.error(err)
      setInviteError(err instanceof Error ? err.message : 'Could not save invite.')
    } finally {
      setInviteSaving(false)
    }
  }

  const deleteInvite = async (invite: OwnedInvite) => {
    if (!window.confirm(`Delete invite "${invite.code}"?`)) return
    setInviteError(null)
    setInviteStatus(null)
    try {
      const baseUrl = getApiBase()
      const response = await authFetch(`${baseUrl}/auth/profile/invites/${invite.id}`, {
        method: 'DELETE',
      })
      if (!response.ok) {
        if (response.status === 401) {
          clearToken()
          router.push('/login')
          return
        }
        const text = await response.text()
        throw new Error(text || 'Invite delete failed')
      }
      if (inviteEditingId === invite.id) {
        resetInviteEditor()
      }
      setInviteStatus(`Deleted invite ${invite.code}.`)
      await reloadInvites()
    } catch (err) {
      console.error(err)
      setInviteError(err instanceof Error ? err.message : 'Could not delete invite.')
    }
  }

  const copyInviteLink = async (invite: OwnedInvite) => {
    const url = `${signupBaseUrl}?code=${encodeURIComponent(invite.code)}`
    try {
      if (navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(url)
        setInviteStatus(`Copied invite link for ${invite.code}.`)
      } else {
        window.prompt('Copy invite link', url)
      }
    } catch (err) {
      console.error(err)
      window.prompt('Copy invite link', url)
    }
  }

  const canManageInvites = profile?.role === 'admin' || inviteAccessEnabled

  if (loading) {
    return <main className="card">Loading invite tools...</main>
  }

  return (
    <main className="card">
      <div className="user-directory-panel-header profile-page-header">
        <div>
          <h1>My invites</h1>
          <p className="lede">Create invite links, email them directly, and track who you have invited.</p>
        </div>
        <div className="admin-inline-actions">
          <button type="button" className="ghost-button" onClick={() => router.push('/profile')}>
            Back to profile
          </button>
        </div>
      </div>

      {profile ? (
        <div className="status-banner">
          Signed in as <strong>{profile.username}</strong> ({profile.role}).
        </div>
      ) : null}

      <div className="profile-tabbar">
        <div className="admin-segmented" role="tablist" aria-label="Profile sections">
          <button type="button" role="tab" aria-selected={false} onClick={() => router.push('/profile')}>
            Overview
          </button>
          <button
            type="button"
            role="tab"
            aria-selected={false}
            onClick={() => router.push('/profile?tab=activity')}
          >
            Activity
          </button>
          <button type="button" role="tab" aria-selected className="is-active">
            My invites
          </button>
          <button
            type="button"
            role="tab"
            aria-selected={false}
            onClick={() => router.push('/profile?tab=security')}
          >
            Security
          </button>
        </div>
      </div>

      {inviteError && <div className="error-banner">{inviteError}</div>}
      {inviteStatus && <div className="status-banner">{inviteStatus}</div>}

      {!canManageInvites ? (
        <section className="profile-section profile-tab-panel">
          <h2>Invite access is disabled</h2>
          <p className="lede">
            Your account is not currently allowed to create self-service invites. Ask an administrator to enable invite access for your profile.
          </p>
          <div className="admin-inline-actions">
            <button type="button" onClick={() => router.push('/profile')}>
              Return to profile
            </button>
          </div>
        </section>
      ) : (
        <section className="profile-section profile-invites-section profile-tab-panel">
          <div className="user-directory-panel-header">
            <div>
              <h2>Invite workspace</h2>
              <p className="lede">
                {inviteManagedByMaster
                  ? 'Create and manage invite links you have issued. New invites use the admin master invite rule.'
                  : 'Create and manage invite links you have issued. New invites use your account defaults.'}
              </p>
            </div>
          </div>

          <div className="profile-invites-layout">
            <div className="profile-invite-form-card">
              <h3>{inviteEditingId == null ? 'Create invite' : 'Edit invite'}</h3>
              <p className="meta profile-invite-form-lede">
                Save a recipient email, send the invite immediately, and keep the generated link ready to copy.
              </p>
              {inviteManagedByMaster && masterInviteTemplate ? (
                <div className="status-banner profile-invite-master-banner">
                  Using master invite rule <code>{masterInviteTemplate.code}</code>
                  {masterInviteTemplate.label ? ` (${masterInviteTemplate.label})` : ''}. Limits and status are managed by admin.
                </div>
              ) : null}
              <form onSubmit={saveInvite} className="admin-form compact-form invite-form-layout profile-form-layout">
                <div className="invite-form-row">
                  <div className="invite-form-row-label">
                    <span>Identity</span>
                    <small>Optional code and label for easier tracking.</small>
                  </div>
                  <div className="invite-form-row-control invite-form-row-grid">
                    <label>
                      <span>Code (optional)</span>
                      <input
                        value={inviteForm.code}
                        onChange={(event) =>
                          setInviteForm((current) => ({ ...current, code: event.target.value }))
                        }
                        placeholder="Leave blank to auto-generate"
                      />
                    </label>
                    <label>
                      <span>Label</span>
                      <input
                        value={inviteForm.label}
                        onChange={(event) =>
                          setInviteForm((current) => ({ ...current, label: event.target.value }))
                        }
                        placeholder="Family invite"
                      />
                    </label>
                  </div>
                </div>

                <div className="invite-form-row">
                  <div className="invite-form-row-label">
                    <span>Description</span>
                    <small>Optional note shown on the signup page.</small>
                  </div>
                  <div className="invite-form-row-control">
                    <textarea
                      rows={3}
                      value={inviteForm.description}
                      onChange={(event) =>
                        setInviteForm((current) => ({
                          ...current,
                          description: event.target.value,
                        }))
                      }
                      placeholder="Optional note shown on the signup page"
                    />
                  </div>
                </div>

                <div className="invite-form-row">
                  <div className="invite-form-row-label">
                    <span>Delivery</span>
                    <small>Recipient email is required. You can also send the invite immediately after saving.</small>
                  </div>
                  <div className="invite-form-row-control invite-form-row-control--stacked">
                    <label>
                      <span>Recipient email (required)</span>
                      <input
                        type="email"
                        required
                        value={inviteForm.recipient_email}
                        onChange={(event) =>
                          setInviteForm((current) => ({
                            ...current,
                            recipient_email: event.target.value,
                          }))
                        }
                        placeholder="Required recipient email"
                      />
                    </label>
                    <label>
                      <span>Delivery note</span>
                      <textarea
                        rows={3}
                        value={inviteForm.message}
                        onChange={(event) =>
                          setInviteForm((current) => ({
                            ...current,
                            message: event.target.value,
                          }))
                        }
                        placeholder="Optional note to include in the email"
                      />
                    </label>
                    <label className="inline-checkbox">
                      <input
                        type="checkbox"
                        checked={inviteForm.send_email}
                        onChange={(event) =>
                          setInviteForm((current) => ({
                            ...current,
                            send_email: event.target.checked,
                          }))
                        }
                      />
                      Send "You have been invited" email after saving
                    </label>
                  </div>
                </div>

                <div className="invite-form-row">
                  <div className="invite-form-row-label">
                    <span>Limits</span>
                    <small>Usage cap and optional expiry date/time.</small>
                  </div>
                  <div className="invite-form-row-control invite-form-row-grid">
                    <label>
                      <span>Max uses</span>
                      <input
                        value={inviteForm.max_uses}
                        onChange={(event) =>
                          setInviteForm((current) => ({ ...current, max_uses: event.target.value }))
                        }
                        inputMode="numeric"
                        placeholder="Blank = unlimited"
                        disabled={inviteManagedByMaster}
                      />
                    </label>
                    <label>
                      <span>Invite expiry (ISO datetime)</span>
                      <input
                        value={inviteForm.expires_at}
                        onChange={(event) =>
                          setInviteForm((current) => ({ ...current, expires_at: event.target.value }))
                        }
                        placeholder="2026-03-01T12:00:00+00:00"
                        disabled={inviteManagedByMaster}
                      />
                    </label>
                  </div>
                </div>

                <div className="invite-form-row">
                  <div className="invite-form-row-label">
                    <span>Status</span>
                    <small>Enable or disable this invite before sharing.</small>
                  </div>
                  <div className="invite-form-row-control invite-form-row-control--stacked">
                    <label className="inline-checkbox">
                      <input
                        type="checkbox"
                        checked={inviteForm.enabled}
                        onChange={(event) =>
                          setInviteForm((current) => ({
                            ...current,
                            enabled: event.target.checked,
                          }))
                        }
                        disabled={inviteManagedByMaster}
                      />
                      Invite is enabled
                    </label>
                    <div className="admin-inline-actions">
                      <button type="submit" disabled={inviteSaving}>
                        {inviteSaving
                          ? 'Saving…'
                          : inviteEditingId == null
                            ? 'Create invite'
                            : 'Save invite'}
                      </button>
                      {inviteEditingId != null && (
                        <button type="button" className="ghost-button" onClick={resetInviteEditor}>
                          Cancel edit
                        </button>
                      )}
                    </div>
                  </div>
                </div>
              </form>
              <div className="meta profile-invite-hint">
                Invite URL format: <code>{signupBaseUrl}?code=INVITECODE</code>
              </div>
            </div>

            <div className="profile-invites-list">
              {invites.length === 0 ? (
                <div className="status-banner">You have not created any invites yet.</div>
              ) : (
                <div className="admin-list">
                  {invites.map((invite) => (
                    <div key={invite.id} className="admin-list-item">
                      <div className="admin-list-item-main">
                        <div className="admin-list-item-title-row">
                          <code className="invite-code">{invite.code}</code>
                          <span className={`small-pill ${invite.is_usable ? '' : 'is-muted'}`}>
                            {invite.is_usable ? 'Usable' : 'Unavailable'}
                          </span>
                          <span className="small-pill is-muted">
                            {invite.remaining_uses == null ? 'Unlimited' : `${invite.remaining_uses} left`}
                          </span>
                        </div>
                        {invite.label && <p className="admin-list-item-text">{invite.label}</p>}
                        {invite.description && (
                          <p className="admin-list-item-text admin-list-item-text--muted">
                            {invite.description}
                          </p>
                        )}
                        <div className="admin-meta-row">
                          <span>Recipient: {invite.recipient_email || 'Not set'}</span>
                          <span>
                            Uses: {invite.use_count}
                            {typeof invite.max_uses === 'number' ? ` / ${invite.max_uses}` : ''}
                          </span>
                          <span>Expires: {formatDate(invite.expires_at)}</span>
                          <span>Created: {formatDate(invite.created_at)}</span>
                        </div>
                      </div>
                      <div className="admin-inline-actions">
                        <button
                          type="button"
                          className="ghost-button"
                          onClick={() => copyInviteLink(invite)}
                        >
                          Copy link
                        </button>
                        <button
                          type="button"
                          className="ghost-button"
                          onClick={() => editInvite(invite)}
                        >
                          Edit
                        </button>
                        <button type="button" onClick={() => deleteInvite(invite)}>
                          Delete
                        </button>
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          </div>
        </section>
      )}
    </main>
  )
}
