import { FormEvent, useEffect, useRef, useState } from 'react'
import TaskBoard from './TaskBoard'

type User = {
  id: string
  name: string
  createdAt: string
}

type ApiError = {
  code?: string
  message?: string
}

const ACTIVE_USER_KEY = 'hemhub.activeUserId'

function App() {
  const [users, setUsers] = useState<User[]>([])
  const [activeUser, setActiveUser] = useState<User | null>(null)
  const [loadState, setLoadState] = useState<'loading' | 'ready' | 'error'>('loading')
  const [showCreateUser, setShowCreateUser] = useState(false)

  const loadUsers = async () => {
    setLoadState('loading')

    try {
      const response = await fetch('/api/users')

      if (!response.ok) {
        throw new Error('Kunde inte hämta användare')
      }

      const loadedUsers = (await response.json()) as User[]
      const storedUserId = window.localStorage.getItem(ACTIVE_USER_KEY)
      const storedUser = loadedUsers.find((user) => user.id === storedUserId) ?? null

      if (storedUserId && !storedUser) {
        window.localStorage.removeItem(ACTIVE_USER_KEY)
      }

      setUsers(loadedUsers)
      setActiveUser(storedUser)
      setShowCreateUser(loadedUsers.length === 0)
      setLoadState('ready')
    } catch {
      setLoadState('error')
    }
  }

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

  const selectUser = (user: User) => {
    window.localStorage.setItem(ACTIVE_USER_KEY, user.id)
    setActiveUser(user)
  }

  const logOut = () => {
    window.localStorage.removeItem(ACTIVE_USER_KEY)
    setActiveUser(null)
    setShowCreateUser(false)
  }

  if (loadState === 'loading') {
    return <main className="panel">Laddar HemHub…</main>
  }

  if (loadState === 'error') {
    return (
      <main className="panel">
        <h1>HemHub</h1>
        <p>Kunde inte ansluta till HemHub.</p>
        <button type="button" onClick={() => void loadUsers()}>
          Försök igen
        </button>
      </main>
    )
  }

  if (activeUser) {
    return <TaskBoard activeUserName={activeUser.name} users={users} onLogOut={logOut} />
  }

  if (showCreateUser) {
    return (
      <CreateUserForm
        hasExistingUsers={users.length > 0}
        onCancel={() => setShowCreateUser(false)}
        onCreated={(user) => {
          setUsers((currentUsers) => [...currentUsers, user])
          selectUser(user)
        }}
      />
    )
  }

  return (
    <main className="panel">
      <h1>HemHub</h1>
      <h2>Vem är du?</h2>
      <div className="user-list">
        {users.map((user) => (
          <button type="button" key={user.id} onClick={() => selectUser(user)}>
            {user.name}
          </button>
        ))}
      </div>
      <button type="button" className="secondary" onClick={() => setShowCreateUser(true)}>
        Skapa användare
      </button>
    </main>
  )
}

type CreateUserFormProps = {
  hasExistingUsers: boolean
  onCancel: () => void
  onCreated: (user: User) => void
}

function CreateUserForm({ hasExistingUsers, onCancel, onCreated }: CreateUserFormProps) {
  const [name, setName] = useState('')
  const [error, setError] = useState('')
  const [isSubmitting, setIsSubmitting] = useState(false)
  const isSubmittingRef = useRef(false)

  const submit = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault()

    if (isSubmittingRef.current) {
      return
    }

    const trimmedName = name.trim()

    if (!trimmedName || [...trimmedName].length > 50) {
      setError('Namnet måste innehålla mellan 1 och 50 tecken.')
      return
    }

    setError('')
    isSubmittingRef.current = true
    setIsSubmitting(true)

    try {
      const response = await fetch('/api/users', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: trimmedName }),
      })

      if (!response.ok) {
        const apiError = (await response.json().catch(() => ({}))) as ApiError

        if (
          apiError.code === 'INVALID_USER_NAME' ||
          apiError.code === 'USER_NAME_ALREADY_EXISTS'
        ) {
          setError(apiError.message ?? 'Det gick inte att skapa användaren.')
        } else {
          setError('Det gick inte att skapa användaren. Försök igen.')
        }
        return
      }

      const createdUser = (await response.json()) as User
      onCreated(createdUser)
    } catch {
      setError('Det gick inte att skapa användaren. Försök igen.')
    } finally {
      isSubmittingRef.current = false
      setIsSubmitting(false)
    }
  }

  return (
    <main className="panel">
      <h1>HemHub</h1>
      <h2>Skapa användare</h2>
      <form onSubmit={(event) => void submit(event)}>
        <label htmlFor="user-name">Namn</label>
        <input
          id="user-name"
          value={name}
          disabled={isSubmitting}
          onChange={(event) => setName(event.target.value)}
        />
        {error && (
          <p className="error" role="alert">
            {error}
          </p>
        )}
        <button type="submit" disabled={isSubmitting}>
          {isSubmitting ? 'Skapar…' : 'Skapa användare'}
        </button>
        {hasExistingUsers && (
          <button type="button" className="secondary" disabled={isSubmitting} onClick={onCancel}>
            Tillbaka
          </button>
        )}
      </form>
    </main>
  )
}

export default App
