import { useEffect, useMemo, useState } from 'react'
import api from '@/services/api'
import { useAuth } from '@/hooks/useAuth'
import { useAuthConfig } from '@/hooks/useAuthConfig'
import type { User } from '@/types'

interface RoleOption {
  id: number
  name: string
  description?: string | null
}

interface ApiKeyPerms {
  can_reset_self: boolean
  can_reset_any: boolean
}

export default function UsersPage() {
  const { user } = useAuth()
  const { config: authCfg } = useAuthConfig()
  const oidcOnly = authCfg.oidcOnly
  const oidcEnabled = authCfg.oidcEnabled
  const isAdmin = user?.is_admin === true

  const [bindForm, setBindForm] = useState({ issuer: '', subject: '' })

  const [users, setUsers] = useState<User[]>([])
  const [roles, setRoles] = useState<RoleOption[]>([])
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)
  const [message, setMessage] = useState('')
  const [selectedId, setSelectedId] = useState<number | null>(null)
  const [apikeyPerms, setApikeyPerms] = useState<ApiKeyPerms>({ can_reset_self: false, can_reset_any: false })
  const [generatedApiKey, setGeneratedApiKey] = useState<string | null>(null)

  const [createForm, setCreateForm] = useState({
    username: '',
    email: '',
    full_name: '',
    password: '',
    role_id: '',
  })

  const [editForm, setEditForm] = useState({
    email: '',
    full_name: '',
    password: '',
    role_id: '',
    is_active: true,
  })

  const selectedUser = useMemo(
    () => users.find((u) => u.id === selectedId) ?? null,
    [users, selectedId],
  )

  useEffect(() => {
    if (!isAdmin) {
      setLoading(false)
      return
    }
    fetchData()
  }, [isAdmin])

  useEffect(() => {
    if (!selectedUser) return
    setGeneratedApiKey(null)
    setEditForm({
      email: selectedUser.email,
      full_name: selectedUser.full_name || '',
      password: '',
      role_id: selectedUser.role_id ? String(selectedUser.role_id) : '',
      is_active: selectedUser.is_active,
    })
  }, [selectedUser])

  useEffect(() => {
    if (!createForm.role_id && roles.length > 0) {
      const guestRole = roles.find((r) => r.name === 'guest') ?? roles[0]
      if (guestRole) {
        setCreateForm((prev) => ({ ...prev, role_id: String(guestRole.id) }))
      }
    }
  }, [roles, createForm.role_id])

  const fetchData = async () => {
    try {
      const [usersRes, rolesRes, apikeyRes] = await Promise.all([
        api.get<User[]>('/users'),
        api.get<RoleOption[]>('/roles'),
        api.get<ApiKeyPerms>('/auth/me/apikey-permissions').catch(() => ({ data: { can_reset_self: false, can_reset_any: false } })),
      ])
      setApikeyPerms(apikeyRes.data)
      const assignableRoles = rolesRes.data
        .filter((role) => role.name !== 'admin')
        .sort((a, b) => a.name.localeCompare(b.name))

      setUsers(usersRes.data)
      setRoles(assignableRoles)

      if (!selectedId && usersRes.data.length > 0) {
        setSelectedId(usersRes.data[0].id)
      } else if (selectedId && !usersRes.data.some((u) => u.id === selectedId)) {
        setSelectedId(usersRes.data[0]?.id ?? null)
      }
    } catch (err: any) {
      setMessage(err.response?.data?.detail || 'Failed to load user management data')
    } finally {
      setLoading(false)
    }
  }

  const handleCreateUser = async () => {
    if (!createForm.username.trim() || !createForm.email.trim()) return
    if (!oidcOnly && !createForm.password.trim()) return
    setSaving(true)
    setMessage('')
    try {
      const payload: Record<string, any> = {
        username: createForm.username.trim(),
        email: createForm.email.trim(),
        full_name: createForm.full_name.trim() || null,
        role_id: createForm.role_id ? Number(createForm.role_id) : undefined,
      }
      if (!oidcOnly) {
        payload.password = createForm.password
      }
      const { data } = await api.post<User>('/users', payload)
      const guestRole = roles.find((r) => r.name === 'guest') ?? roles[0]
      setCreateForm({
        username: '',
        email: '',
        full_name: '',
        password: '',
        role_id: guestRole ? String(guestRole.id) : '',
      })
      setMessage('User created successfully')
      await fetchData()
      setSelectedId(data.id)
    } catch (err: any) {
      setMessage(err.response?.data?.detail || 'Failed to create user')
    } finally {
      setSaving(false)
    }
  }

  const handleSaveUser = async () => {
    if (!selectedUser) return
    setSaving(true)
    setMessage('')
    try {
      const payload: Record<string, any> = {
        email: editForm.email.trim(),
        full_name: editForm.full_name.trim() || null,
        is_active: editForm.is_active,
      }
      if (!selectedUser.is_admin) {
        payload.role_id = editForm.role_id ? Number(editForm.role_id) : undefined
      }
      if (editForm.password.trim()) {
        payload.password = editForm.password
      }
      await api.patch<User>(`/users/${selectedUser.id}`, payload)
      setMessage('User updated successfully')
      await fetchData()
      setEditForm((prev) => ({ ...prev, password: '' }))
    } catch (err: any) {
      setMessage(err.response?.data?.detail || 'Failed to update user')
    } finally {
      setSaving(false)
    }
  }

  const canResetApiKey = (targetUser: User) => {
    if (apikeyPerms.can_reset_any) return true
    if (apikeyPerms.can_reset_self && targetUser.id === user?.id) return true
    return false
  }

  const handleResetApiKey = async () => {
    if (!selectedUser) return
    if (!confirm(`Reset API key for ${selectedUser.username}? The old key will be deactivated.`)) return
    setSaving(true)
    setMessage('')
    setGeneratedApiKey(null)
    try {
      const { data } = await api.post(`/users/${selectedUser.id}/reset-apikey`)
      setGeneratedApiKey(data.api_key)
      setMessage('API key reset successfully. Copy it now — it will not be shown again.')
    } catch (err: any) {
      setMessage(err.response?.data?.detail || 'Failed to reset API key')
    } finally {
      setSaving(false)
    }
  }

  const handleDeleteUser = async () => {
    if (!selectedUser) return
    if (!confirm(`Delete user ${selectedUser.username}? This cannot be undone.`)) return
    setSaving(true)
    setMessage('')
    try {
      await api.delete(`/users/${selectedUser.id}`)
      setMessage('User deleted successfully')
      await fetchData()
    } catch (err: any) {
      setMessage(err.response?.data?.detail || 'Failed to delete user')
    } finally {
      setSaving(false)
    }
  }

  const handleBindOidc = async () => {
    if (!selectedUser) return
    if (!bindForm.issuer.trim() || !bindForm.subject.trim()) return
    setSaving(true)
    setMessage('')
    try {
      await api.put(`/users/${selectedUser.id}/oidc-binding`, {
        issuer: bindForm.issuer.trim(),
        subject: bindForm.subject.trim(),
      })
      setBindForm({ issuer: '', subject: '' })
      setMessage('OIDC identity bound successfully')
      await fetchData()
    } catch (err: any) {
      setMessage(err.response?.data?.detail || 'Failed to bind OIDC identity')
    } finally {
      setSaving(false)
    }
  }

  const handleUnbindOidc = async () => {
    if (!selectedUser) return
    if (!confirm(`Remove the OIDC binding for ${selectedUser.username}?`)) return
    setSaving(true)
    setMessage('')
    try {
      await api.delete(`/users/${selectedUser.id}/oidc-binding`)
      setMessage('OIDC binding removed')
      await fetchData()
    } catch (err: any) {
      setMessage(err.response?.data?.detail || 'Failed to remove OIDC binding')
    } finally {
      setSaving(false)
    }
  }

  if (loading) return <div className="loading">Loading users...</div>

  if (!isAdmin) {
    return (
      <div className="section">
        <h2>👥 User Management</h2>
        <p className="empty">Admin access required.</p>
      </div>
    )
  }

  return (
    <div className="section">
      <div className="page-header">
        <div>
          <h2>👥 User Management</h2>
          <div className="text-dim">Create accounts, assign one non-admin role, and manage activation state.</div>
        </div>
      </div>

      {message && (
        <div
          style={{
            padding: '10px 12px',
            marginBottom: '16px',
            borderRadius: '8px',
            background: message.toLowerCase().includes('successfully') ? 'rgba(16,185,129,.12)' : 'rgba(239,68,68,.12)',
            border: `1px solid ${message.toLowerCase().includes('successfully') ? 'rgba(16,185,129,.35)' : 'rgba(239,68,68,.35)'}`,
          }}
        >
          {message}
        </div>
      )}

      <div style={{ display: 'grid', gridTemplateColumns: '320px 1fr', gap: '20px', alignItems: 'start' }}>
        <div className="monitor-card">
          <h3 style={{ marginBottom: 12 }}>Create User</h3>
          <div className="task-create-form">
            <label>
              Username
              <input value={createForm.username} onChange={(e) => setCreateForm({ ...createForm, username: e.target.value })} />
            </label>
            <label>
              Email
              <input value={createForm.email} onChange={(e) => setCreateForm({ ...createForm, email: e.target.value })} />
            </label>
            <label>
              Full Name
              <input value={createForm.full_name} onChange={(e) => setCreateForm({ ...createForm, full_name: e.target.value })} />
            </label>
            {!oidcOnly && (
              <label>
                Password
                <input type="password" value={createForm.password} onChange={(e) => setCreateForm({ ...createForm, password: e.target.value })} />
              </label>
            )}
            {oidcOnly && (
              <p className="text-dim">OIDC-only mode: users are created without a password and sign in via a bound OIDC identity.</p>
            )}
            <label>
              Role
              <select value={createForm.role_id} onChange={(e) => setCreateForm({ ...createForm, role_id: e.target.value })}>
                <option value="" disabled>Select role</option>
                {roles.map((role) => (
                  <option key={role.id} value={String(role.id)}>{role.name}</option>
                ))}
              </select>
            </label>
            <button className="btn-primary" disabled={saving || !createForm.username.trim() || !createForm.email.trim() || (!oidcOnly && !createForm.password.trim()) || !createForm.role_id} onClick={handleCreateUser}>
              {saving ? 'Saving...' : 'Create User'}
            </button>
          </div>

          <h3 style={{ marginTop: 24, marginBottom: 12 }}>Users</h3>
          <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
            {users.map((u) => (
              <button
                key={u.id}
                onClick={() => setSelectedId(u.id)}
                className="btn-secondary"
                style={{
                  textAlign: 'left',
                  padding: '12px',
                  background: selectedId === u.id ? 'var(--bg-hover)' : 'transparent',
                  borderColor: selectedId === u.id ? 'var(--accent)' : 'var(--border)',
                }}
              >
                <div style={{ fontWeight: 600 }}>{u.username}</div>
                <div className="text-dim">{u.email}</div>
                <div style={{ display: 'flex', gap: '6px', marginTop: '6px', flexWrap: 'wrap' }}>
                  <span className="badge">{u.role_name || 'unassigned'}</span>
                  {u.is_admin && <span className="badge">admin</span>}
                  <span className={'badge ' + (u.is_active ? 'status-online' : 'status-offline')}>{u.is_active ? 'active' : 'inactive'}</span>
                </div>
              </button>
            ))}
          </div>
        </div>

        <div className="monitor-card">
          {selectedUser ? (
            <>
              <div className="page-header" style={{ marginBottom: 12 }}>
                <div>
                  <h3 style={{ marginBottom: 6 }}>{selectedUser.username}</h3>
                  <div className="text-dim">Created at {new Date(selectedUser.created_at).toLocaleString()}</div>
                </div>
                <div style={{ display: 'flex', gap: '8px' }}>
                  <button className="btn-primary" disabled={saving} onClick={handleSaveUser}>
                    {saving ? 'Saving...' : 'Save Changes'}
                  </button>
                  <button className="btn-danger" disabled={saving || user?.id === selectedUser.id || selectedUser.is_admin || selectedUser.username === 'acc-mgr'} onClick={handleDeleteUser}>
                    Delete
                  </button>
                </div>
              </div>

              <div className="task-create-form">
                <label>
                  Username
                  <input value={selectedUser.username} disabled />
                </label>
                <label>
                  Email
                  <input value={editForm.email} onChange={(e) => setEditForm({ ...editForm, email: e.target.value })} />
                </label>
                <label>
                  Full Name
                  <input value={editForm.full_name} onChange={(e) => setEditForm({ ...editForm, full_name: e.target.value })} />
                </label>
                {!oidcOnly && (
                  <label>
                    Reset Password
                    <input type="password" placeholder="Leave blank to keep current password" value={editForm.password} onChange={(e) => setEditForm({ ...editForm, password: e.target.value })} />
                  </label>
                )}

                <div style={{ marginTop: '8px', padding: '12px', border: '1px solid var(--border)', borderRadius: '8px' }}>
                  <div style={{ fontWeight: 600, marginBottom: '10px' }}>Role</div>
                  {selectedUser.is_admin ? (
                    <div className="text-dim">{selectedUser.role_name || 'admin'} (admin accounts are managed outside this screen)</div>
                  ) : (
                    <label>
                      Account Role
                      <select value={editForm.role_id} onChange={(e) => setEditForm({ ...editForm, role_id: e.target.value })}>
                        <option value="" disabled>Select role</option>
                        {roles.map((role) => (
                          <option key={role.id} value={String(role.id)}>{role.name}</option>
                        ))}
                      </select>
                    </label>
                  )}
                </div>

                <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>
                  <label className="filter-check">
                    <input
                      type="checkbox"
                      checked={editForm.is_active}
                      disabled={user?.id === selectedUser.id}
                      onChange={(e) => setEditForm({ ...editForm, is_active: e.target.checked })}
                    />
                    Active
                  </label>
                </div>

                {canResetApiKey(selectedUser) && (
                  <div style={{ marginTop: '8px', padding: '12px', border: '1px solid var(--border)', borderRadius: '8px' }}>
                    <div style={{ fontWeight: 600, marginBottom: '10px' }}>API Key</div>
                    <button className="btn-secondary" disabled={saving} onClick={handleResetApiKey}>
                      🔑 Reset API Key
                    </button>
                    {generatedApiKey && (
                      <div style={{ marginTop: 10, padding: '10px', background: 'rgba(16,185,129,.08)', border: '1px solid rgba(16,185,129,.35)', borderRadius: '6px', wordBreak: 'break-all', fontFamily: 'monospace', fontSize: '13px' }}>
                        <div style={{ marginBottom: 6, fontWeight: 600, fontFamily: 'inherit' }}>New API Key (copy now!):</div>
                        <code>{generatedApiKey}</code>
                        <button
                          className="btn-sm"
                          style={{ marginLeft: 8 }}
                          onClick={() => { navigator.clipboard.writeText(generatedApiKey); setMessage('API key copied to clipboard') }}
                        >
                          📋 Copy
                        </button>
                      </div>
                    )}
                  </div>
                )}

                {oidcEnabled && (
                  <div style={{ marginTop: '8px', padding: '12px', border: '1px solid var(--border)', borderRadius: '8px' }}>
                    <div style={{ fontWeight: 600, marginBottom: '10px' }}>OIDC Binding</div>
                    {selectedUser.oidc_subject ? (
                      <div style={{ marginBottom: 10 }}>
                        <div className="text-dim" style={{ fontFamily: 'monospace', wordBreak: 'break-all' }}>
                          issuer: {selectedUser.oidc_issuer || '—'}<br />
                          subject: {selectedUser.oidc_subject}
                        </div>
                        <button className="btn-danger" style={{ marginTop: 10 }} disabled={saving} onClick={handleUnbindOidc}>
                          Unbind OIDC identity
                        </button>
                      </div>
                    ) : (
                      <div className="text-dim" style={{ marginBottom: 10 }}>No OIDC identity bound.</div>
                    )}
                    <label>
                      Issuer
                      <input value={bindForm.issuer} placeholder="https://idp.example.com" onChange={(e) => setBindForm({ ...bindForm, issuer: e.target.value })} />
                    </label>
                    <label>
                      Subject (sub)
                      <input value={bindForm.subject} placeholder="OIDC subject claim" onChange={(e) => setBindForm({ ...bindForm, subject: e.target.value })} />
                    </label>
                    <button className="btn-secondary" style={{ marginTop: 10 }} disabled={saving || !bindForm.issuer.trim() || !bindForm.subject.trim()} onClick={handleBindOidc}>
                      {selectedUser.oidc_subject ? 'Rebind OIDC identity' : 'Bind OIDC identity'}
                    </button>
                  </div>
                )}
              </div>
            </>
          ) : (
            <div className="empty">No user selected.</div>
          )}
        </div>
      </div>
    </div>
  )
}
