import { type FormEvent, useCallback, useEffect, useMemo, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import {
  fetchAllUsersForAssign,
  fetchRolesList,
  saveUserRoles,
  type AssignUserRow,
  type RoleRow,
} from '../../api/rolePermission'
import { AcademicFilterBar } from '../discounts/AcademicFilterBar'

export function AssignRolePage() {
  const [searchParams] = useSearchParams()
  const schoolYear = searchParams.get('school_year') ?? undefined
  const semester = searchParams.get('semester') ?? undefined

  const [users, setUsers] = useState<AssignUserRow[]>([])
  const [roles, setRoles] = useState<RoleRow[]>([])
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [modalOpen, setModalOpen] = useState(false)
  const [selUser, setSelUser] = useState<AssignUserRow | null>(null)
  const [selRoleIds, setSelRoleIds] = useState<Set<string>>(new Set())
  const [sortKey, setSortKey] = useState<'id' | 'account_id' | 'name' | 'email' | 'roles'>('name')
  const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc')
  const [page, setPage] = useState(1)
  const pageSize = 25

  const loadUsers = useCallback(() => {
    setError(null)
    setLoading(true)
    fetchAllUsersForAssign({ school_year: schoolYear, semester })
      .then((d) => setUsers(d.users ?? []))
      .catch((e: unknown) =>
        setError(e instanceof ApiHttpError ? e.message : 'Failed to load users.'),
      )
      .finally(() => setLoading(false))
  }, [schoolYear, semester])

  useEffect(() => {
    fetchRolesList()
      .then((d) => setRoles(d.roles ?? []))
      .catch((e: unknown) =>
        setError(e instanceof ApiHttpError ? e.message : 'Failed to load roles.'),
      )
  }, [])

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

  useEffect(() => {
    setPage(1)
  }, [schoolYear, semester])

  const sortedUsers = useMemo(() => {
    const rows = [...users]
    const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' })

    const valueFor = (u: AssignUserRow): string => {
      switch (sortKey) {
        case 'id':
          return String(u.id ?? '')
        case 'account_id':
          return String(u.account_id ?? '')
        case 'email':
          return String(u.email ?? '')
        case 'roles':
          return Array.isArray(u.roles) ? u.roles.join(', ') : ''
        case 'name':
        default:
          return `${u.firstname ?? ''} ${u.lastname ?? ''}`.trim()
      }
    }

    rows.sort((a, b) => {
      const left = valueFor(a)
      const right = valueFor(b)
      const result = collator.compare(left, right)
      return sortDir === 'asc' ? result : -result
    })

    return rows
  }, [sortDir, sortKey, users])

  const totalPages = Math.max(1, Math.ceil(sortedUsers.length / pageSize))
  const currentPage = Math.min(page, totalPages)
  const pagedUsers = useMemo(() => {
    const start = (currentPage - 1) * pageSize
    return sortedUsers.slice(start, start + pageSize)
  }, [currentPage, sortedUsers])

  function toggleSort(nextKey: 'id' | 'account_id' | 'name' | 'email' | 'roles') {
    if (sortKey === nextKey) {
      setSortDir((current) => (current === 'asc' ? 'desc' : 'asc'))
      setPage(1)
      return
    }
    setSortKey(nextKey)
    setSortDir('asc')
    setPage(1)
  }

  function sortIndicator(key: 'id' | 'account_id' | 'name' | 'email' | 'roles') {
    if (sortKey !== key) return ''
    return sortDir === 'asc' ? ' ▲' : ' ▼'
  }

  function renderSortableHeader(
    key: 'id' | 'account_id' | 'name' | 'email' | 'roles',
    label: string,
  ) {
    return (
      <button
        type="button"
        onClick={() => toggleSort(key)}
        style={{
          background: 'transparent',
          border: 0,
          color: 'inherit',
          font: 'inherit',
          fontWeight: 600,
          padding: 0,
          textAlign: 'left',
        }}
      >
        {label}
        {sortIndicator(key)}
      </button>
    )
  }

  function openModal(u: AssignUserRow) {
    setSelUser(u)
    const current = Array.isArray(u.roles) ? u.roles.map((s) => String(s).trim()).filter(Boolean) : []
    const ids = new Set<string>()
    for (const r of roles) {
      if (current.some((c) => c.toLowerCase() === String(r.name ?? '').toLowerCase())) {
        if (r.id != null) ids.add(String(r.id))
      }
    }
    setSelRoleIds(ids)
    setModalOpen(true)
  }

  function toggleRole(id: string) {
    setSelRoleIds((prev) => {
      const n = new Set(prev)
      if (n.has(id)) n.delete(id)
      else n.add(id)
      return n
    })
  }

  async function saveModal(e: FormEvent) {
    e.preventDefault()
    if (!selUser?.id) return
    try {
      await saveUserRoles({
        user_id: selUser.id,
        role_ids: [...selRoleIds],
      })
      setModalOpen(false)
      loadUsers()
    } catch (err: unknown) {
      alert(err instanceof ApiHttpError ? err.message : 'Save failed.')
    }
  }

  return (
    <div className="container-fluid py-3">
      <h2 className="text-center mt-4 mb-3">Assign Role to Users</h2>

      <AcademicFilterBar />

      {error ? <div className="alert alert-danger">{error}</div> : null}

      <div className="table-responsive">
        <table className="table table-bordered table-striped align-middle">
          <thead className="table-dark">
            <tr>
              <th>{renderSortableHeader('id', 'User ID')}</th>
              <th>{renderSortableHeader('account_id', 'Account Number')}</th>
              <th>{renderSortableHeader('name', 'Name')}</th>
              <th>{renderSortableHeader('email', 'Email')}</th>
              <th>{renderSortableHeader('roles', 'Current Roles')}</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            {loading ? (
              <tr>
                <td colSpan={6} className="text-center text-muted py-4">
                  Loading users…
                </td>
              </tr>
            ) : users.length === 0 ? (
              <tr>
                <td colSpan={6} className="text-center text-muted py-4">
                  No users loaded.
                </td>
              </tr>
            ) : (
              pagedUsers.map((u) => (
                <tr key={String(u.id)}>
                  <td>{String(u.id ?? '')}</td>
                  <td>{String(u.account_id ?? '')}</td>
                  <td>{`${u.firstname ?? ''} ${u.lastname ?? ''}`.trim()}</td>
                  <td>{String(u.email ?? '')}</td>
                  <td>{Array.isArray(u.roles) ? u.roles.join(', ') : ''}</td>
                  <td>
                    <button type="button" className="btn btn-sm btn-primary" onClick={() => openModal(u)}>
                      Assign
                    </button>
                  </td>
                </tr>
              ))
            )}
          </tbody>
        </table>
      </div>

      {!loading && users.length > 0 ? (
        <div className="d-flex flex-wrap justify-content-between align-items-center gap-2 mt-3">
          <div className="text-muted small">
            Showing {(currentPage - 1) * pageSize + 1}-{Math.min(currentPage * pageSize, sortedUsers.length)} of{' '}
            {sortedUsers.length} users
          </div>
          <div className="btn-group" role="group" aria-label="Pagination">
            <button
              type="button"
              className="btn btn-outline-secondary btn-sm"
              disabled={currentPage <= 1}
              onClick={() => setPage(1)}
            >
              First
            </button>
            <button
              type="button"
              className="btn btn-outline-secondary btn-sm"
              disabled={currentPage <= 1}
              onClick={() => setPage((p) => Math.max(1, p - 1))}
            >
              Previous
            </button>
            <button type="button" className="btn btn-outline-secondary btn-sm" disabled>
              Page {currentPage} of {totalPages}
            </button>
            <button
              type="button"
              className="btn btn-outline-secondary btn-sm"
              disabled={currentPage >= totalPages}
              onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
            >
              Next
            </button>
            <button
              type="button"
              className="btn btn-outline-secondary btn-sm"
              disabled={currentPage >= totalPages}
              onClick={() => setPage(totalPages)}
            >
              Last
            </button>
          </div>
        </div>
      ) : null}

      {modalOpen && selUser ? (
        <div className="modal show d-block" tabIndex={-1} style={{ background: 'rgba(0,0,0,.35)' }}>
          <div className="modal-dialog">
            <div className="modal-content">
              <form onSubmit={saveModal}>
                <div className="modal-header">
                  <h5 className="modal-title">Assign Roles</h5>
                  <button type="button" className="btn-close" onClick={() => setModalOpen(false)} />
                </div>
                <div className="modal-body">
                  <div className="mb-3">
                    <span className="form-label d-block">User</span>
                    <div className="fw-semibold">
                      {`${selUser.firstname ?? ''} ${selUser.lastname ?? ''}`.trim()} ({String(selUser.email ?? '')})
                    </div>
                  </div>
                  <div className="d-flex flex-column gap-2">
                    <span className="form-label">Select Roles</span>
                    {roles.length === 0 ? (
                      <div className="text-muted small">No roles loaded.</div>
                    ) : null}
                    {roles.map((r) => {
                      const id = String(r.id ?? '')
                      return (
                        <label key={id} className="form-check">
                          <input
                            type="checkbox"
                            className="form-check-input"
                            checked={selRoleIds.has(id)}
                            onChange={() => toggleRole(id)}
                          />
                          <span className="form-check-label">{String(r.name ?? id)}</span>
                        </label>
                      )
                    })}
                  </div>
                </div>
                <div className="modal-footer">
                  <button type="button" className="btn btn-secondary" onClick={() => setModalOpen(false)}>
                    Cancel
                  </button>
                  <button type="submit" className="btn btn-primary">
                    Save Roles
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  )
}
