import { FormEvent, MouseEvent, useEffect, useRef, useState } from 'react'

type TaskStatus = 'WAITING' | 'IN_PROGRESS' | 'COMPLETED'

type Task = {
  id: string
  title: string
  description: string | null
  status: TaskStatus
  createdAt: string
}

type ApiError = {
  message?: string
}

type TaskBoardProps = {
  activeUserName: string
  onLogOut: () => void
}

const columns: { status: TaskStatus; title: string }[] = [
  { status: 'WAITING', title: 'Väntande' },
  { status: 'IN_PROGRESS', title: 'Pågående' },
  { status: 'COMPLETED', title: 'Klart' },
]

function TaskBoard({ activeUserName, onLogOut }: TaskBoardProps) {
  const [tasks, setTasks] = useState<Task[]>([])
  const [loadState, setLoadState] = useState<'loading' | 'ready' | 'error'>('loading')
  const [showCreateTask, setShowCreateTask] = useState(false)

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

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

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

      setTasks((await response.json()) as Task[])
      setLoadState('ready')
    } catch {
      setLoadState('error')
    }
  }

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

  return (
    <main className="task-app">
      <header className="app-header">
        <div>
          <p className="eyebrow">HemHub</p>
          <h1>Uppgifter</h1>
        </div>
        <div className="user-controls">
          <span>{activeUserName}</span>
          <button type="button" className="secondary compact" onClick={onLogOut}>
            Logga ut
          </button>
        </div>
      </header>

      <div className="board-toolbar">
        <div aria-live="polite">
          {loadState === 'loading' && 'Laddar uppgifter…'}
          {loadState === 'error' && (
            <>
              Kunde inte hämta uppgifter.
              <button type="button" className="link-button" onClick={() => void loadTasks()}>
                Försök igen
              </button>
            </>
          )}
        </div>
        <button type="button" onClick={() => setShowCreateTask(true)}>
          Ny uppgift
        </button>
      </div>

      <section className="board" aria-label="Uppgiftsbräda">
        {columns.map((column) => (
          <section className="board-column" key={column.status} aria-labelledby={column.status}>
            <h2 id={column.status}>{column.title}</h2>
            <div className="task-list">
              {tasks
                .filter((task) => task.status === column.status)
                .map((task) => (
                  <article className="task-card" key={task.id}>
                    <h3>{task.title}</h3>
                    {task.description && <p>{task.description}</p>}
                  </article>
                ))}
            </div>
          </section>
        ))}
      </section>

      {showCreateTask && (
        <CreateTaskModal
          onClose={() => setShowCreateTask(false)}
          onCreated={(task) => {
            setTasks((currentTasks) => [...currentTasks, task])
            setShowCreateTask(false)
          }}
        />
      )}
    </main>
  )
}

type CreateTaskModalProps = {
  onClose: () => void
  onCreated: (task: Task) => void
}

function CreateTaskModal({ onClose, onCreated }: CreateTaskModalProps) {
  const [title, setTitle] = useState('')
  const [description, setDescription] = useState('')
  const [error, setError] = useState('')
  const [isSubmitting, setIsSubmitting] = useState(false)
  const isSubmittingRef = useRef(false)

  useEffect(() => {
    const closeOnEscape = (event: KeyboardEvent) => {
      if (event.key === 'Escape' && !isSubmittingRef.current) {
        onClose()
      }
    }

    window.addEventListener('keydown', closeOnEscape)
    return () => window.removeEventListener('keydown', closeOnEscape)
  }, [onClose])

  const closeFromBackdrop = (event: MouseEvent<HTMLDivElement>) => {
    if (event.target === event.currentTarget && !isSubmittingRef.current) {
      onClose()
    }
  }

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

    if (isSubmittingRef.current) {
      return
    }

    const trimmedTitle = title.trim()
    const trimmedDescription = description.trim()

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

    if ([...trimmedDescription].length > 500) {
      setError('Beskrivningen får innehålla högst 500 tecken.')
      return
    }

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

    try {
      const response = await fetch('/api/tasks', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          title: trimmedTitle,
          description: trimmedDescription || null,
        }),
      })

      if (!response.ok) {
        const apiError = (await response.json().catch(() => ({}))) as ApiError
        setError(apiError.message ?? 'Det gick inte att skapa uppgiften. Försök igen.')
        return
      }

      onCreated((await response.json()) as Task)
    } catch {
      setError('Det gick inte att skapa uppgiften. Försök igen.')
    } finally {
      isSubmittingRef.current = false
      setIsSubmitting(false)
    }
  }

  return (
    <div className="modal-backdrop" onMouseDown={closeFromBackdrop}>
      <section
        className="modal"
        role="dialog"
        aria-modal="true"
        aria-labelledby="create-task-title"
      >
        <div className="modal-header">
          <h2 id="create-task-title">Skapa ny uppgift</h2>
          <button
            type="button"
            className="close-button"
            aria-label="Stäng"
            disabled={isSubmitting}
            onClick={onClose}
          >
            ×
          </button>
        </div>
        <form onSubmit={(event) => void submit(event)}>
          <label htmlFor="task-title">Titel</label>
          <input
            id="task-title"
            autoFocus
            value={title}
            disabled={isSubmitting}
            onChange={(event) => setTitle(event.target.value)}
          />

          <label htmlFor="task-description">Beskrivning (valfri)</label>
          <textarea
            id="task-description"
            rows={5}
            value={description}
            disabled={isSubmitting}
            onChange={(event) => setDescription(event.target.value)}
          />

          {error && (
            <p className="error" role="alert">
              {error}
            </p>
          )}

          <button type="submit" disabled={isSubmitting}>
            {isSubmitting ? 'Skapar…' : 'Skapa uppgift'}
          </button>
        </form>
      </section>
    </div>
  )
}

export default TaskBoard
