import { useCallback, useEffect, useState } from 'react'
import { Boxes, FileText, Plus } from 'lucide-react'
import { toast } from 'sonner'
import { AppShell } from '@/components/AppShell'
import { MarkdownEditor } from '@/components/MarkdownEditor'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@/components/ui/sheet'
import { api } from '@/lib/api'
import { useAuth } from '@/store/auth'

// A starter PRODUCT.md so an empty product gets useful structure to fill in.
const IDENTITY_TEMPLATE = (name: string) =>
  `---
product: ${name}
goals:
domain:
conventions:
glossary:
---

# About ${name}

Describe what this product is, who it serves, and the conventions every agent on it should follow.
This identity is shared by every agent across the product's teams.
`

interface Division {
  id: string
  organizationId: string
  name: string
}

interface Product {
  id: string
  organizationId: string
  divisionId: string | null
  name: string
  kind: string
}

interface Team {
  id: string
  organizationId: string
  name: string
  productId: string | null
}

const NONE = 'none'

/** Define the org structure: divisions → products/services → teams. */
export function StructurePage() {
  const organizationId = useAuth((s) => s.organizationId)
  const [divisions, setDivisions] = useState<Division[]>([])
  const [products, setProducts] = useState<Product[]>([])
  const [teams, setTeams] = useState<Team[]>([])
  const [busy, setBusy] = useState(false)

  const [divisionName, setDivisionName] = useState('')
  const [product, setProduct] = useState({ name: '', kind: 'Product', divisionId: NONE })
  const [team, setTeam] = useState({ name: '', productId: NONE })
  const [identity, setIdentity] = useState<{ productId: string; name: string; content: string } | null>(null)
  const [savingIdentity, setSavingIdentity] = useState(false)

  const load = useCallback(async () => {
    if (!organizationId) return
    try {
      const [d, p, t] = await Promise.all([
        api.get<Division[]>(`/api/orgboard/divisions?organizationId=${organizationId}`),
        api.get<Product[]>(`/api/orgboard/products?organizationId=${organizationId}`),
        api.get<Team[]>(`/api/orgboard/teams?organizationId=${organizationId}`),
      ])
      setDivisions(d)
      setProducts(p)
      setTeams(t)
    } catch (err) {
      toast.error((err as Error).message)
    }
  }, [organizationId])

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

  const run = async (action: () => Promise<void>) => {
    setBusy(true)
    try {
      await action()
      await load()
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setBusy(false)
    }
  }

  const addDivision = () =>
    run(async () => {
      await api.post('/api/orgboard/divisions', { organizationId, name: divisionName })
      setDivisionName('')
      toast.success('Division created.')
    })

  const addProduct = () =>
    run(async () => {
      await api.post('/api/orgboard/products', {
        organizationId,
        name: product.name,
        kind: product.kind,
        divisionId: product.divisionId === NONE ? null : product.divisionId,
      })
      setProduct({ name: '', kind: 'Product', divisionId: NONE })
      toast.success('Product created.')
    })

  const addTeam = () =>
    run(async () => {
      await api.post('/api/orgboard/teams', {
        organizationId,
        name: team.name,
        productId: team.productId === NONE ? null : team.productId,
      })
      setTeam({ name: '', productId: NONE })
      toast.success('Team created.')
    })

  // Open the product's shared identity (PRODUCT.md) — load current text, or start from the template.
  const openIdentity = async (p: Product) => {
    try {
      const current = await api.get<{ identity: string | null }>(`/api/orgboard/products/${p.id}/identity`)
      setIdentity({ productId: p.id, name: p.name, content: current.identity ?? IDENTITY_TEMPLATE(p.name) })
    } catch (err) {
      toast.error((err as Error).message)
    }
  }

  const saveIdentity = async () => {
    if (!identity) return
    setSavingIdentity(true)
    try {
      await api.put(`/api/orgboard/products/${identity.productId}/identity`, { identity: identity.content })
      toast.success(`Identity saved for ${identity.name} — every agent on it now shares it.`)
      setIdentity(null)
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setSavingIdentity(false)
    }
  }

  return (
    <AppShell>
      <div className="mx-auto max-w-4xl p-6">
        <header className="mb-6">
          <h1 className="flex items-center gap-2 text-2xl font-semibold tracking-tight">
            <Boxes className="size-6" /> Structure
          </h1>
          <p className="text-sm text-muted-foreground">
            The object spine: organization → divisions → products/services → teams.
          </p>
        </header>

        <div className="flex flex-col gap-6">
          <Card>
            <CardHeader>
              <CardTitle className="text-base">Divisions</CardTitle>
              <CardDescription>Technical, Finance, HR, Sales — the top-level slices.</CardDescription>
            </CardHeader>
            <CardContent className="flex flex-col gap-3">
              <div className="flex items-end gap-3">
                <Field label="Name">
                  <Input value={divisionName} onChange={(e) => setDivisionName(e.target.value)} className="w-56" placeholder="Technical" />
                </Field>
                <Button disabled={busy || !divisionName.trim()} onClick={addDivision}>
                  <Plus data-icon="inline-start" />Add division
                </Button>
              </div>
              <div className="flex flex-wrap gap-2">
                {divisions.map((d) => (
                  <Badge key={d.id} variant="secondary">{d.name}</Badge>
                ))}
                {divisions.length === 0 && <p className="text-sm text-muted-foreground">No divisions yet — optional, but they unlock the full org chart.</p>}
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle className="text-base">Products & services</CardTitle>
              <CardDescription>Engineering divisions ship products; other divisions run services.</CardDescription>
            </CardHeader>
            <CardContent className="flex flex-col gap-3">
              <div className="flex flex-wrap items-end gap-3">
                <Field label="Name">
                  <Input value={product.name} onChange={(e) => setProduct({ ...product, name: e.target.value })} className="w-48" placeholder="IPNOPS" />
                </Field>
                <Field label="Kind">
                  <Select value={product.kind} onValueChange={(v) => setProduct({ ...product, kind: v })}>
                    <SelectTrigger className="w-32"><SelectValue /></SelectTrigger>
                    <SelectContent>
                      <SelectGroup>
                        <SelectItem value="Product">Product</SelectItem>
                        <SelectItem value="Service">Service</SelectItem>
                      </SelectGroup>
                    </SelectContent>
                  </Select>
                </Field>
                <Field label="Division">
                  <Select value={product.divisionId} onValueChange={(v) => setProduct({ ...product, divisionId: v })}>
                    <SelectTrigger className="w-44"><SelectValue /></SelectTrigger>
                    <SelectContent>
                      <SelectGroup>
                        <SelectItem value={NONE}>— none —</SelectItem>
                        {divisions.map((d) => (
                          <SelectItem key={d.id} value={d.id}>{d.name}</SelectItem>
                        ))}
                      </SelectGroup>
                    </SelectContent>
                  </Select>
                </Field>
                <Button disabled={busy || !product.name.trim()} onClick={addProduct}>
                  <Plus data-icon="inline-start" />Add product
                </Button>
              </div>
              <div className="flex flex-col gap-2">
                {products.map((p) => (
                  <div key={p.id} className="flex items-center gap-2 rounded-md border px-3 py-2 text-sm">
                    <span className="font-medium">{p.name}</span>
                    <Badge variant="outline">{p.kind}</Badge>
                    <span className="text-muted-foreground">
                      {p.divisionId ? divisions.find((d) => d.id === p.divisionId)?.name ?? '' : 'no division'}
                    </span>
                    <Button variant="ghost" size="sm" className="ml-auto" onClick={() => openIdentity(p)}>
                      <FileText data-icon="inline-start" /> Identity
                    </Button>
                  </div>
                ))}
                {products.length === 0 && <p className="text-sm text-muted-foreground">No products yet.</p>}
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle className="text-base">Teams</CardTitle>
              <CardDescription>Teams run delivery. Attach them to a product to complete the spine.</CardDescription>
            </CardHeader>
            <CardContent className="flex flex-col gap-3">
              <div className="flex flex-wrap items-end gap-3">
                <Field label="Name">
                  <Input value={team.name} onChange={(e) => setTeam({ ...team, name: e.target.value })} className="w-48" placeholder="Core team" />
                </Field>
                <Field label="Product / service">
                  <Select value={team.productId} onValueChange={(v) => setTeam({ ...team, productId: v })}>
                    <SelectTrigger className="w-44"><SelectValue /></SelectTrigger>
                    <SelectContent>
                      <SelectGroup>
                        <SelectItem value={NONE}>— none —</SelectItem>
                        {products.map((p) => (
                          <SelectItem key={p.id} value={p.id}>{p.name}</SelectItem>
                        ))}
                      </SelectGroup>
                    </SelectContent>
                  </Select>
                </Field>
                <Button disabled={busy || !team.name.trim()} onClick={addTeam}>
                  <Plus data-icon="inline-start" />Add team
                </Button>
              </div>
              <div className="flex flex-col gap-2">
                {teams.map((t) => (
                  <div key={t.id} className="flex items-center gap-2 rounded-md border px-3 py-2 text-sm">
                    <span className="font-medium">{t.name}</span>
                    <span className="text-muted-foreground">
                      {t.productId ? products.find((p) => p.id === t.productId)?.name ?? '' : 'directly under the org'}
                    </span>
                  </div>
                ))}
                {teams.length === 0 && <p className="text-sm text-muted-foreground">No teams yet.</p>}
              </div>
            </CardContent>
          </Card>
        </div>
      </div>

      {identity && (
        <Sheet open onOpenChange={(o) => !o && setIdentity(null)}>
          <SheetContent className="flex w-full flex-col gap-0 overflow-y-auto sm:max-w-2xl">
            <SheetHeader>
              <SheetTitle>Product identity — {identity.name}</SheetTitle>
              <SheetDescription>
                A shared PRODUCT.md (goals, domain, conventions) injected into every agent run on this
                product, across all its teams. Treated as data, never as instructions.
              </SheetDescription>
            </SheetHeader>
            <div className="flex flex-col gap-4 px-4 pb-6">
              <MarkdownEditor
                rows={22}
                mono
                frontmatter
                value={identity.content}
                onChange={(content) => setIdentity({ ...identity, content })}
              />
              <div className="flex items-center justify-end gap-2">
                <Button variant="ghost" onClick={() => setIdentity(null)}>Cancel</Button>
                <Button disabled={savingIdentity} onClick={saveIdentity}>Save identity</Button>
              </div>
            </div>
          </SheetContent>
        </Sheet>
      )}
    </AppShell>
  )
}

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="flex flex-col gap-1.5">
      <Label className="text-xs">{label}</Label>
      {children}
    </div>
  )
}
