import { useEffect, useState } from 'react'
import { api } from '../api'
import type { CospendProject, Group, Item, Member } from '../types'

interface Props {
  receiptId: string
  items: Item[]
  onAllDone: (groups: Group[]) => void
}

export function GroupStep({ receiptId, items, onAllDone }: Props) {
  const [projects, setProjects] = useState<CospendProject[]>([])
  const [projectId, setProjectId] = useState<string | null>(null)
  const [members, setMembers] = useState<Member[]>([])
  const [loadError, setLoadError] = useState<string | null>(null)

  const [remainingIds, setRemainingIds] = useState<Set<string>>(new Set(items.map((i) => i.id)))
  const [groups, setGroups] = useState<Group[]>([])

  // current draft
  const [name, setName] = useState('WG')
  const [payerId, setPayerId] = useState<string | null>(null)
  const [selectedMemberIds, setSelectedMemberIds] = useState<Set<string>>(new Set())
  const [selectedItemIds, setSelectedItemIds] = useState<Set<string>>(new Set())
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState<string | null>(null)

  // load Cospend projects once, pick the configured default (or the only one)
  useEffect(() => {
    api
      .getProjects()
      .then(({ projects: p, default_project_id }) => {
        setProjects(p)
        const initial = default_project_id ?? (p.length === 1 ? p[0].id : null)
        if (initial) setProjectId(initial)
      })
      .catch((e) => setLoadError(e instanceof Error ? e.message : String(e)))
  }, [])

  // load members whenever the selected project changes
  useEffect(() => {
    if (!projectId) return
    api
      .getMembers(projectId)
      .then((m) => {
        setMembers(m)
        if (m.length > 0) {
          setPayerId(m[0].id)
          setSelectedMemberIds(new Set(m.map((mm) => mm.id)))
        }
      })
      .catch((e) => setLoadError(e instanceof Error ? e.message : String(e)))
  }, [projectId])

  function toggleItem(id: string) {
    setSelectedItemIds((prev) => {
      const next = new Set(prev)
      next.has(id) ? next.delete(id) : next.add(id)
      return next
    })
  }

  function toggleMember(id: string) {
    setSelectedMemberIds((prev) => {
      const next = new Set(prev)
      next.has(id) ? next.delete(id) : next.add(id)
      return next
    })
  }

  const remainingItems = items.filter((i) => remainingIds.has(i.id))
  const groupTotal = items
    .filter((i) => selectedItemIds.has(i.id))
    .reduce((sum, i) => sum + i.price, 0)

  async function submitCurrentGroup() {
    if (!projectId) {
      setError('pick a Cospend project')
      return
    }
    if (!payerId || selectedMemberIds.size === 0 || selectedItemIds.size === 0) {
      setError('pick a payer, at least one member, and at least one item')
      return
    }
    setSubmitting(true)
    setError(null)
    try {
      const { id: groupId } = await api.createGroup(receiptId, {
        name,
        cospend_project_id: projectId,
        payer_member_id: payerId,
        member_ids: [...selectedMemberIds],
        item_ids: [...selectedItemIds],
      })
      const result = await api.submitGroup(receiptId, groupId)
      const allGroups = await api.listGroups(receiptId)
      setGroups(allGroups)

      setRemainingIds((prev) => {
        const next = new Set(prev)
        selectedItemIds.forEach((id) => next.delete(id))
        return next
      })
      const wasLastGroup = remainingItems.length === selectedItemIds.size
      setSelectedItemIds(new Set())
      setName('WG')

      if (wasLastGroup) {
        onAllDone(allGroups)
      }
      void result
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e))
    } finally {
      setSubmitting(false)
    }
  }

  if (loadError) {
    return (
      <div className="step">
        <p className="error">Couldn't load Cospend data: {loadError}</p>
      </div>
    )
  }

  return (
    <div className="step group-step">
      <h2>Who's splitting this?</h2>
      <p className="hint">
        Select the items for one splitting arrangement, pick who's in on it, submit. Repeat for
        any items that need a different group (e.g. only your snack).
      </p>

      <label className="payer-select">
        Cospend project
        <select value={projectId ?? ''} onChange={(e) => setProjectId(e.target.value)}>
          <option value="" disabled>
            select a project…
          </option>
          {projects.map((p) => (
            <option key={p.id} value={p.id}>
              {p.name}
            </option>
          ))}
        </select>
      </label>

      {groups.length > 0 && (
        <div className="submitted-groups">
          {groups.map((g) => (
            <p key={g.id}>
              ✓ {g.name} bill created —{' '}
              <a href={g.share_url ?? '#'} target="_blank" rel="noreferrer">
                receipt
              </a>
            </p>
          ))}
        </div>
      )}

      <input
        className="group-name"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="group name (e.g. WG, just me + Alex)"
      />

      <h3>Items ({remainingItems.length} left)</h3>
      <ul className="item-list selectable">
        {remainingItems.map((item) => (
          <li
            key={item.id}
            className={selectedItemIds.has(item.id) ? 'selected' : ''}
            onClick={() => toggleItem(item.id)}
          >
            <span>{item.label || '(unnamed)'}</span>
            <span>{item.price.toFixed(2)}</span>
          </li>
        ))}
      </ul>

      <h3>Split with</h3>
      <ul className="member-list">
        {members.map((m) => (
          <li key={m.id}>
            <label>
              <input
                type="checkbox"
                checked={selectedMemberIds.has(m.id)}
                onChange={() => toggleMember(m.id)}
              />
              {m.name}
            </label>
          </li>
        ))}
      </ul>

      <label className="payer-select">
        Paid by
        <select value={payerId ?? ''} onChange={(e) => setPayerId(e.target.value)}>
          {members.map((m) => (
            <option key={m.id} value={m.id}>
              {m.name}
            </option>
          ))}
        </select>
      </label>

      <p className="total">Group total: {groupTotal.toFixed(2)}</p>
      {error && <p className="error">{error}</p>}

      <button disabled={submitting || selectedItemIds.size === 0} onClick={submitCurrentGroup}>
        {submitting ? 'Creating bill…' : 'Create bill for this group'}
      </button>

      {remainingItems.length === 0 && groups.length > 0 && (
        <button className="secondary" onClick={() => onAllDone(groups)}>
          All items assigned — finish
        </button>
      )}
    </div>
  )
}
