import { useEffect, useState } from 'react'
import { PageShell } from '../components/PageShell'
import type { User, Role, Capability } from '../types'

interface ManagedUser {
  id: number
  email: string
  name: string
  active: boolean
  is_admin: boolean
  offsite_allowed: boolean
  workforce_user_id: string | null
  app_slugs: string[]
  roles: { id: number; name: string; slug: string }[]
  capabilities: string[]   // direct "<app>:<cap>" grants (not role-derived)
}

export function AdminUsers({ user }: { user: User }) {
  const [users, setUsers] = useState<ManagedUser[]>([])
  const [allApps, setAllApps] = useState<{ slug: string; name: string }[]>([])
  const [allRoles, setAllRoles] = useState<Role[]>([])
  const [allCaps, setAllCaps] = useState<Capability[]>([])
  const [showCreate, setShowCreate] = useState(false)
  const [expanded, setExpanded] = useState<Set<number>>(new Set())

  async function load() {
    const [u, a, r, c] = await Promise.all([
      fetch('/api/auth/admin/users',        { credentials: 'include' }).then(r => r.json()),
      fetch('/api/auth/admin/apps',         { credentials: 'include' }).then(r => r.json()),
      fetch('/api/auth/admin/roles',        { credentials: 'include' }).then(r => r.json()),
      fetch('/api/auth/admin/capabilities', { credentials: 'include' }).then(r => r.json()),
    ])
    setUsers(u)
    setAllApps(a)
    setAllRoles(r)
    setAllCaps(c)
  }

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

  // Capabilities a user inherits from their assigned roles (shown read-only).
  function roleDerivedCaps(u: ManagedUser): Set<string> {
    const set = new Set<string>()
    for (const ur of u.roles) {
      const role = allRoles.find(r => r.id === ur.id)
      role?.capabilities?.forEach(c => set.add(c))
    }
    return set
  }

  async function toggle(userId: number, field: string, current: boolean) {
    await fetch(`/api/auth/admin/users/${userId}`, {
      method: 'PATCH', credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ [field]: !current }),
    })
    load()
  }

  async function grantRevoke(userId: number, slug: string, has: boolean) {
    await fetch(`/api/auth/admin/users/${userId}/apps/${slug}`, {
      method: has ? 'DELETE' : 'POST', credentials: 'include',
    })
    load()
  }

  async function toggleUserCap(userId: number, appSlug: string, capSlug: string, has: boolean) {
    await fetch(`/api/auth/admin/users/${userId}/capabilities/${appSlug}/${capSlug}`, {
      method: has ? 'DELETE' : 'POST', credentials: 'include',
    })
    load()
  }

  async function addRole(userId: number, roleId: number) {
    await fetch(`/api/auth/admin/users/${userId}/roles/${roleId}`, {
      method: 'POST', credentials: 'include',
    })
    load()
  }

  async function removeRole(userId: number, roleId: number) {
    await fetch(`/api/auth/admin/users/${userId}/roles/${roleId}`, {
      method: 'DELETE', credentials: 'include',
    })
    load()
  }

  async function syncWfRoles(userId: number) {
    await fetch(`/api/auth/admin/workforce/sync-user/${userId}`, {
      method: 'POST', credentials: 'include',
    })
    load()
  }

  return (
    <PageShell user={user}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '1.5rem' }}>
          <h1 style={{ fontSize: '1.2rem' }}>Users</h1>
          <button onClick={() => setShowCreate(v => !v)} style={goldBtn}>
            {showCreate ? 'Cancel' : '+ New user'}
          </button>
        </div>

        {showCreate && <CreateUserForm onCreated={() => { setShowCreate(false); load() }} />}

        <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
          {users.map(u => {
            const isExpanded = expanded.has(u.id)
            const toggleExpanded = () => setExpanded(prev => {
              const next = new Set(prev)
              next.has(u.id) ? next.delete(u.id) : next.add(u.id)
              return next
            })
            const inherited = roleDerivedCaps(u)
            return (
              <div key={u.id} style={{
                background: 'var(--card-bg)', borderRadius: '10px',
                padding: '1rem 1.25rem', border: '1px solid var(--card-border)',
                boxShadow: 'var(--shadow-sm)', opacity: u.active ? 1 : 0.5,
              }}>
                {/* Always-visible row */}
                <div style={{ display: 'flex', alignItems: 'center', gap: '1rem', flexWrap: 'wrap' }}>
                  <div style={{ flex: 1, minWidth: '140px' }}>
                    <div style={{ fontWeight: 600, fontSize: '0.9rem' }}>{u.name}</div>
                    <div style={{ fontSize: '0.78rem', color: 'var(--text-mid)' }}>{u.email}</div>
                  </div>
                  <div style={{ display: 'flex', gap: '0.4rem', flexWrap: 'wrap', alignItems: 'center' }}>
                    <Toggle label="Active"   on={u.active}          onClick={() => toggle(u.id, 'active', u.active)} />
                    <Toggle label="Admin"    on={u.is_admin}        onClick={() => toggle(u.id, 'is_admin', u.is_admin)} />
                    <Toggle label="Offsite"  on={u.offsite_allowed} onClick={() => toggle(u.id, 'offsite_allowed', u.offsite_allowed)} />
                  </div>
                </div>

                {/* Summary row: role badges + expand toggle */}
                <div style={{ marginTop: '0.6rem', display: 'flex', alignItems: 'center', gap: '0.4rem', flexWrap: 'wrap' }}>
                  {u.roles.length > 0
                    ? u.roles.map(r => (
                        <span key={r.id} style={{
                          background: 'var(--navy)', color: '#fff',
                          borderRadius: '4px', padding: '0.15rem 0.5rem', fontSize: '0.72rem',
                        }}>{r.name}</span>
                      ))
                    : <span style={{ fontSize: '0.72rem', color: 'var(--text-mid)' }}>No roles</span>
                  }
                  <button onClick={toggleExpanded} style={{
                    marginLeft: 'auto', background: 'none', border: 'none',
                    color: 'var(--text-mid)', fontSize: '0.72rem', cursor: 'pointer',
                    padding: '0.15rem 0.25rem', display: 'flex', alignItems: 'center', gap: '0.2rem',
                  }}>
                    {isExpanded ? 'Hide permissions ▲' : 'Show permissions ▼'}
                  </button>
                </div>

                {/* Expanded: app grants, capabilities, role editor */}
                {isExpanded && (
                  <>
                    <div style={{ marginTop: '0.75rem', display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
                      {allApps.map(app => {
                        const has = u.app_slugs.includes(app.slug)
                        const hasViaRole = u.roles.some(ur => allRoles.find(r => r.id === ur.id)?.app_slugs.includes(app.slug))
                        const appCaps = allCaps.filter(c => c.app_slug === app.slug)
                        return (
                          <div key={app.slug} style={{ display: 'flex', gap: '0.5rem', alignItems: 'flex-start', flexWrap: 'wrap' }}>
                            <button onClick={() => grantRevoke(u.id, app.slug, has)}
                              title={hasViaRole ? 'Also granted via a role' : ''} style={{
                                background: has ? 'var(--navy)' : 'var(--body-bg)',
                                border: `1px solid ${has ? 'var(--navy)' : hasViaRole ? 'var(--navy)' : 'var(--card-border)'}`,
                                color: has ? '#fff' : hasViaRole ? 'var(--navy)' : 'var(--text-mid)',
                                borderRadius: '4px', padding: '0.2rem 0.6rem', fontSize: '0.75rem', cursor: 'pointer',
                                minWidth: '120px', textAlign: 'left', flexShrink: 0,
                              }}>
                              {app.name}{hasViaRole && !has ? ' (role)' : ''}
                            </button>
                            {(has || hasViaRole) && appCaps.length > 0 && (
                              <div style={{ display: 'flex', gap: '0.3rem', flexWrap: 'wrap', alignItems: 'center' }}>
                                {appCaps.map(cap => {
                                  const capKey = `${cap.app_slug}:${cap.slug}`
                                  const direct = u.capabilities.includes(capKey)
                                  const viaRole = inherited.has(capKey)
                                  const on = direct || viaRole
                                  return (
                                    <button key={capKey}
                                      title={viaRole && !direct ? `Granted via role — ${cap.description ?? ''}` : (cap.description ?? '')}
                                      onClick={() => { if (!viaRole) toggleUserCap(u.id, cap.app_slug, cap.slug, direct) }}
                                      style={{
                                        background: on ? (viaRole && !direct ? '#5a7d6a' : '#2d6a4f') : 'var(--body-bg)',
                                        border: `1px solid ${on ? (viaRole && !direct ? '#5a7d6a' : '#2d6a4f') : 'var(--card-border)'}`,
                                        color: on ? '#fff' : 'var(--text-mid)',
                                        borderRadius: '4px', padding: '0.15rem 0.5rem', fontSize: '0.7rem',
                                        cursor: viaRole && !direct ? 'default' : 'pointer',
                                      }}>
                                      {on ? '✓ ' : ''}{cap.name}{viaRole && !direct ? ' (role)' : ''}
                                    </button>
                                  )
                                })}
                              </div>
                            )}
                          </div>
                        )
                      })}
                    </div>

                    {/* Role editor */}
                    <div style={{ marginTop: '0.5rem', display: 'flex', gap: '0.4rem', flexWrap: 'wrap', alignItems: 'center' }}>
                      <span style={{ fontSize: '0.72rem', color: 'var(--text-mid)', marginRight: '0.15rem' }}>Roles:</span>
                      {u.roles.map(r => (
                        <button key={r.id} onClick={() => removeRole(u.id, r.id)} title="Click to remove" style={{
                          background: 'var(--navy)', border: '1px solid var(--navy)',
                          color: '#fff', borderRadius: '4px',
                          padding: '0.15rem 0.5rem', fontSize: '0.72rem', cursor: 'pointer',
                        }}>
                          {r.name} ×
                        </button>
                      ))}
                      <select
                        value=""
                        onChange={e => { if (e.target.value) addRole(u.id, Number(e.target.value)) }}
                        style={{
                          background: 'var(--body-bg)', border: '1px solid var(--card-border)',
                          borderRadius: '4px', color: 'var(--text-mid)',
                          padding: '0.15rem 0.4rem', fontSize: '0.72rem',
                        }}
                      >
                        <option value="">+ Add role</option>
                        {allRoles.filter(r => !u.roles.find(ur => ur.id === r.id)).map(r => (
                          <option key={r.id} value={r.id}>{r.name}</option>
                        ))}
                      </select>
                      {u.workforce_user_id && (
                        <button onClick={() => syncWfRoles(u.id)} style={{
                          background: 'var(--body-bg)', border: '1px solid var(--card-border)',
                          color: 'var(--text-mid)', borderRadius: '4px',
                          padding: '0.15rem 0.5rem', fontSize: '0.72rem', cursor: 'pointer',
                        }}>
                          Sync WF roles
                        </button>
                      )}
                    </div>
                  </>
                )}
              </div>
            )
          })}
        </div>
    </PageShell>
  )
}

function Toggle({ label, on, onClick }: { label: string; on: boolean; onClick: () => void }) {
  return (
    <button onClick={onClick} style={{
      background: on ? 'var(--navy)' : 'var(--body-bg)',
      border: `1px solid ${on ? 'var(--navy)' : 'var(--card-border)'}`,
      color: on ? '#fff' : 'var(--text-mid)',
      borderRadius: '4px', padding: '0.2rem 0.6rem', fontSize: '0.75rem', cursor: 'pointer',
    }}>
      {label}
    </button>
  )
}

function CreateUserForm({ onCreated }: { onCreated: () => void }) {
  const [form, setForm] = useState({ email: '', name: '', password: '', is_admin: false, offsite_allowed: false })
  const [error, setError] = useState('')

  async function submit(e: React.FormEvent) {
    e.preventDefault()
    const res = await fetch('/api/auth/admin/users', {
      method: 'POST', credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(form),
    })
    if (res.ok) onCreated()
    else setError('Failed to create user')
  }

  const f = (k: string) => (e: React.ChangeEvent<HTMLInputElement>) =>
    setForm(v => ({ ...v, [k]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }))

  return (
    <form onSubmit={submit} style={{
      background: 'var(--card-bg)', borderRadius: '10px', padding: '1.25rem',
      border: '1px solid var(--card-border)', marginBottom: '1rem',
      display: 'flex', flexDirection: 'column', gap: '0.75rem',
      boxShadow: 'var(--shadow-sm)',
    }}>
      <h2 style={{ fontSize: '0.9rem', color: 'var(--navy)', fontWeight: 700 }}>New User</h2>
      <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
        <input placeholder="Full name" value={form.name} onChange={f('name')} required style={{ ...inp, flex: 1 }} />
        <input type="email" placeholder="Email" value={form.email} onChange={f('email')} required style={{ ...inp, flex: 1 }} />
        <input type="password" placeholder="Password" value={form.password} onChange={f('password')} required style={{ ...inp, flex: 1 }} />
      </div>
      <div style={{ display: 'flex', gap: '1rem' }}>
        <label style={chk}><input type="checkbox" checked={form.is_admin} onChange={f('is_admin')} /> Admin</label>
        <label style={chk}><input type="checkbox" checked={form.offsite_allowed} onChange={f('offsite_allowed')} /> Offsite access</label>
      </div>
      {error && <p style={{ color: 'var(--danger)', fontSize: '0.85rem' }}>{error}</p>}
      <button type="submit" style={goldBtn}>Create user</button>
    </form>
  )
}

const inp: React.CSSProperties = {
  background: 'var(--body-bg)', border: '1px solid var(--card-border)',
  borderRadius: '6px', color: 'var(--text-dark)', padding: '0.6rem 0.75rem', fontSize: '0.875rem',
}
const chk: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: '0.4rem', fontSize: '0.875rem', cursor: 'pointer' }
const goldBtn: React.CSSProperties = {
  background: 'var(--navy)', color: '#fff', border: 'none',
  borderRadius: '6px', padding: '0.5rem 1rem', fontSize: '0.875rem', fontWeight: 600, cursor: 'pointer',
}
