import { useCallback, useEffect, useMemo, useState } from 'react'
import { KeyRound, Plug, Plus, Bot, Sparkles, Trash2, Wand2 } from 'lucide-react'
import { toast } from 'sonner'
import { AppShell } from '@/components/AppShell'
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 { cn } from '@/lib/utils'
import { api } from '@/lib/api'
import { useAuth } from '@/store/auth'

interface Team {
  id: string
  name: string
}

interface ApiConfig {
  id: string
  name: string
  provider: string
  model: string
  endpoint: string | null
}

interface McpServer {
  id: string
  name: string
  endpoint: string
  enabled: boolean
  headerNames: string[]
}

interface Seat {
  id: string
  teamId: string
  roleName: string
  state: string
  agentId?: string | null
}

interface Skill {
  skillKey: string
  name: string
  roles: string[]
  status: string
}

interface Agent {
  id: string
  name: string
  monogram?: string | null
  autonomy: string
  apiConfigId: string
  skillKeys: string[]
  mcpServerIds: string[]
  docs: string[]
  persona?: string | null
}

interface AgentProfileLite {
  id: string
  profileKey: string
  name: string
  monogram?: string | null
  recommendedAutonomy: string
  skillKeys: string[]
}

interface AgentProfileDetail {
  profile: AgentProfileLite
  body: string
}

const AUTONOMY = [
  { value: 'DraftOnly', label: 'Draft', on: 'bg-slate-600 text-white' },
  { value: 'Gated', label: 'Gated', on: 'bg-indigo-600 text-white' },
  { value: 'Autonomous', label: 'Auto', on: 'bg-teal-600 text-white' },
] as const

export function SeatsPage() {
  const organizationId = useAuth((s) => s.organizationId)

  const [teams, setTeams] = useState<Team[]>([])
  const [teamId, setTeamId] = useState<string | null>(null)
  const [configs, setConfigs] = useState<ApiConfig[]>([])
  const [mcpServers, setMcpServers] = useState<McpServer[]>([])
  const [seats, setSeats] = useState<Seat[]>([])
  const [skills, setSkills] = useState<Skill[]>([])

  const [cfg, setCfg] = useState({ name: '', provider: 'stub', model: 'gpt-4o-mini', apiKey: '', endpoint: '' })
  const [mcp, setMcp] = useState({ name: '', endpoint: '', headerName: 'Authorization', headerValue: '' })
  const [newSeat, setNewSeat] = useState('')
  const [selectedSeat, setSelectedSeat] = useState<string | null>(null)
  const [profiles, setProfiles] = useState<AgentProfileLite[]>([])
  const [agent, setAgent] = useState({
    name: '',
    monogram: '',
    autonomy: 'Gated',
    apiConfigId: '',
    skillKeys: [] as string[],
    mcpServerIds: [] as string[],
    docs: '',
    persona: '',
  })

  const run = useCallback(async (action: () => Promise<unknown>) => {
    try {
      await action()
    } catch (err) {
      toast.error((err as Error).message)
    }
  }, [])

  const loadConfigs = useCallback(async () => {
    if (!organizationId) return
    setConfigs(await api.get<ApiConfig[]>(`/api/integrations/api-configs?organizationId=${organizationId}`))
  }, [organizationId])

  const loadMcpServers = useCallback(async () => {
    if (!organizationId) return
    setMcpServers(await api.get<McpServer[]>(`/api/integrations/mcp-servers?organizationId=${organizationId}`))
  }, [organizationId])

  const loadSeats = useCallback(async (id: string) => {
    setSeats(await api.get<Seat[]>(`/api/orgboard/seats?teamId=${id}`))
  }, [])

  useEffect(() => {
    if (!organizationId) return
    void run(async () => {
      setTeams(await api.get<Team[]>(`/api/orgboard/teams?organizationId=${organizationId}`))
      // The org's library = shared builtins + its own authored/installed skills. The API returns
      // every version (newest first per key); collapse to one selectable entry per key.
      const lib = await api.get<Skill[]>(`/api/skills/?organizationId=${organizationId}`)
      const byKey = new Map<string, Skill>()
      for (const s of lib) if (!byKey.has(s.skillKey)) byKey.set(s.skillKey, s)
      setSkills([...byKey.values()])
      // Agent profiles (AGENTS.md): one selectable entry per key (the resolvable winner is first).
      const profileList = await api.get<AgentProfileLite[]>(`/api/orgboard/agent-profiles?organizationId=${organizationId}`)
      const byProfileKey = new Map<string, AgentProfileLite>()
      for (const p of profileList) if (!byProfileKey.has(p.profileKey)) byProfileKey.set(p.profileKey, p)
      setProfiles([...byProfileKey.values()])
      await loadConfigs()
      await loadMcpServers()
    })
  }, [organizationId, loadConfigs, loadMcpServers, run])

  useEffect(() => {
    if (teamId) void run(() => loadSeats(teamId))
  }, [teamId, loadSeats, run])

  const createConfig = () =>
    run(async () => {
      await api.post('/api/integrations/api-configs', { organizationId, ...cfg, endpoint: cfg.endpoint.trim() || null })
      setCfg({ name: '', provider: 'stub', model: 'gpt-4o-mini', apiKey: '', endpoint: '' })
      await loadConfigs()
      toast.success('API config saved (key encrypted).')
    })

  const testConfig = (id: string) =>
    run(async () => {
      const result = await api.post<{ success: boolean; error?: string; latencyMs: number }>(
        `/api/integrations/api-configs/${id}/test`,
      )
      result.success
        ? toast.success(`Test call succeeded (${result.latencyMs} ms).`)
        : toast.error(`Test failed: ${result.error}`)
    })

  const createMcpServer = () =>
    run(async () => {
      const headers = mcp.headerValue.trim() && mcp.headerName.trim()
        ? { [mcp.headerName.trim()]: mcp.headerValue.trim() }
        : null
      await api.post('/api/integrations/mcp-servers', {
        organizationId,
        name: mcp.name.trim(),
        endpoint: mcp.endpoint.trim(),
        headers,
      })
      setMcp({ name: '', endpoint: '', headerName: 'Authorization', headerValue: '' })
      await loadMcpServers()
      toast.success('MCP server added (auth header encrypted).')
    })

  const testMcpServer = (id: string) =>
    run(async () => {
      const result = await api.post<{ success: boolean; error?: string; toolCount: number; toolNames: string[] }>(
        `/api/integrations/mcp-servers/${id}/test`,
      )
      result.success
        ? toast.success(`Connected — ${result.toolCount} tool(s): ${result.toolNames.slice(0, 6).join(', ') || 'none'}.`)
        : toast.error(`MCP test failed: ${result.error}`)
    })

  const deleteMcpServer = (id: string) =>
    run(async () => {
      await api.del(`/api/integrations/mcp-servers/${id}`)
      await loadMcpServers()
    })

  const toggleMcp = (id: string) =>
    setAgent((a) => ({
      ...a,
      mcpServerIds: a.mcpServerIds.includes(id) ? a.mcpServerIds.filter((x) => x !== id) : [...a.mcpServerIds, id],
    }))

  const createSeat = () =>
    run(async () => {
      if (!teamId) return
      await api.post('/api/orgboard/seats', { teamId, roleName: newSeat })
      setNewSeat('')
      await loadSeats(teamId)
    })

  const selectSeat = (seat: Seat) =>
    run(async () => {
      setSelectedSeat(seat.id)
      const existing = seat.agentId
        ? await api.get<Agent>(`/api/orgboard/seats/${seat.id}/agent`).catch(() => null)
        : null
      setAgent(
        existing
          ? {
              name: existing.name,
              monogram: existing.monogram ?? '',
              autonomy: existing.autonomy,
              apiConfigId: existing.apiConfigId,
              skillKeys: existing.skillKeys,
              mcpServerIds: existing.mcpServerIds ?? [],
              docs: existing.docs.join(', '),
              persona: existing.persona ?? '',
            }
          : { name: '', monogram: '', autonomy: 'Gated', apiConfigId: configs[0]?.id ?? '', skillKeys: [], mcpServerIds: [], docs: '', persona: '' },
      )
    })

  // Apply an AGENTS.md profile to the seat: prefill identity, autonomy, skills, and the persona
  // (operating guide). The user can still tweak everything before saving.
  const applyProfile = (key: string) =>
    run(async () => {
      const versions = await api.get<AgentProfileDetail[]>(`/api/orgboard/agent-profiles/${key}?organizationId=${organizationId}`)
      const chosen = versions[0]
      if (!chosen) return
      const known = new Set(skills.map((s) => s.skillKey))
      setAgent((a) => ({
        ...a,
        name: chosen.profile.name,
        monogram: chosen.profile.monogram ?? '',
        autonomy: chosen.profile.recommendedAutonomy,
        skillKeys: chosen.profile.skillKeys.filter((k) => known.has(k)),
        persona: chosen.body,
      }))
      toast.success(`Applied “${chosen.profile.name}”. Review and save.`)
    })

  const saveAgent = () =>
    run(async () => {
      if (!selectedSeat) return
      await api.post(`/api/orgboard/seats/${selectedSeat}/agent`, {
        name: agent.name,
        monogram: agent.monogram || null,
        autonomy: agent.autonomy,
        apiConfigId: agent.apiConfigId,
        skillKeys: agent.skillKeys,
        mcpServerIds: agent.mcpServerIds,
        docs: agent.docs ? agent.docs.split(',').map((d) => d.trim()).filter(Boolean) : [],
        persona: agent.persona.trim() || null,
      })
      if (teamId) await loadSeats(teamId)
      toast.success(`${agent.name || 'Agent'} configured — seat is now AI.`)
    })

  const toggleSkill = (key: string) =>
    setAgent((a) => ({
      ...a,
      skillKeys: a.skillKeys.includes(key) ? a.skillKeys.filter((k) => k !== key) : [...a.skillKeys, key],
    }))

  const selected = useMemo(() => seats.find((s) => s.id === selectedSeat) ?? null, [seats, selectedSeat])

  return (
    <AppShell>
      <div className="mx-auto flex max-w-5xl flex-col gap-6 p-6">
        <header>
          <h1 className="text-2xl font-semibold tracking-tight">AI seats</h1>
          <p className="text-sm text-muted-foreground">Connect a model (BYOK) and staff a seat with an AI agent.</p>
        </header>

        <Card>
          <CardHeader>
            <CardTitle className="flex items-center gap-2 text-base">
              <KeyRound className="size-4" /> Model connections (BYOK)
            </CardTitle>
            <CardDescription>Keys are encrypted server-side and never shown again after saving.</CardDescription>
          </CardHeader>
          <CardContent className="flex flex-col gap-4">
            <div className="flex flex-wrap items-end gap-3">
              <Field label="Name">
                <Input value={cfg.name} onChange={(e) => setCfg({ ...cfg, name: e.target.value })} className="w-40" placeholder="Vertex-Pro" />
              </Field>
              <Field label="Provider">
                <Select value={cfg.provider} onValueChange={(v) => setCfg({ ...cfg, provider: v })}>
                  <SelectTrigger className="w-36"><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectGroup>
                      {['stub', 'openai', 'ollama', 'vllm', 'custom'].map((p) => (
                        <SelectItem key={p} value={p}>{p}</SelectItem>
                      ))}
                    </SelectGroup>
                  </SelectContent>
                </Select>
              </Field>
              <Field label="Model">
                <Input value={cfg.model} onChange={(e) => setCfg({ ...cfg, model: e.target.value })} className="w-40" />
              </Field>
              <Field label="API key">
                <Input type="password" value={cfg.apiKey} onChange={(e) => setCfg({ ...cfg, apiKey: e.target.value })} className="w-44" placeholder="sk-…" />
              </Field>
              <Field label="Base URL (OpenAI-compatible; optional)">
                <Input
                  value={cfg.endpoint}
                  onChange={(e) => setCfg({ ...cfg, endpoint: e.target.value })}
                  className="w-72"
                  placeholder="https://my-gateway.example.com"
                />
              </Field>
              <Button onClick={createConfig}><Plus data-icon="inline-start" />Add</Button>
            </div>
            <div className="flex flex-col gap-2">
              {configs.map((c) => (
                <div key={c.id} className="flex items-center justify-between rounded-md border px-3 py-2 text-sm">
                  <span className="font-medium">{c.name}</span>
                  <span className="text-muted-foreground">
                    {c.provider} · {c.model}
                    {c.endpoint ? ` · ${c.endpoint}` : ''}
                  </span>
                  <Button variant="outline" size="sm" onClick={() => testConfig(c.id)}>Test</Button>
                </div>
              ))}
              {configs.length === 0 && <p className="text-sm text-muted-foreground">No model connections yet.</p>}
            </div>
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle className="flex items-center gap-2 text-base">
              <Plug className="size-4" /> MCP servers
            </CardTitle>
            <CardDescription>
              Connect Model Context Protocol servers (Streamable HTTP). Auth headers are encrypted and never
              shown again. Bind servers to an agent below — their tools are offered to the agent at run time.
            </CardDescription>
          </CardHeader>
          <CardContent className="flex flex-col gap-4">
            <div className="flex flex-wrap items-end gap-3">
              <Field label="Name">
                <Input value={mcp.name} onChange={(e) => setMcp({ ...mcp, name: e.target.value })} className="w-40" placeholder="GitHub MCP" />
              </Field>
              <Field label="Endpoint URL">
                <Input value={mcp.endpoint} onChange={(e) => setMcp({ ...mcp, endpoint: e.target.value })} className="w-72" placeholder="https://host/mcp" />
              </Field>
              <Field label="Auth header (optional)">
                <Input value={mcp.headerName} onChange={(e) => setMcp({ ...mcp, headerName: e.target.value })} className="w-36" placeholder="Authorization" />
              </Field>
              <Field label="Header value (optional)">
                <Input type="password" value={mcp.headerValue} onChange={(e) => setMcp({ ...mcp, headerValue: e.target.value })} className="w-48" placeholder="Bearer …" />
              </Field>
              <Button onClick={createMcpServer}><Plus data-icon="inline-start" />Add</Button>
            </div>
            <div className="flex flex-col gap-2">
              {mcpServers.map((s) => (
                <div key={s.id} className="flex items-center justify-between rounded-md border px-3 py-2 text-sm">
                  <span className="font-medium">{s.name}</span>
                  <span className="truncate text-muted-foreground">
                    {s.endpoint}{s.headerNames.length > 0 ? ` · auth: ${s.headerNames.join(', ')}` : ''}
                  </span>
                  <div className="flex gap-2">
                    <Button variant="outline" size="sm" onClick={() => testMcpServer(s.id)}>Test</Button>
                    <Button variant="ghost" size="sm" onClick={() => deleteMcpServer(s.id)}><Trash2 className="size-4" /></Button>
                  </div>
                </div>
              ))}
              {mcpServers.length === 0 && <p className="text-sm text-muted-foreground">No MCP servers yet.</p>}
            </div>
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle className="text-base">Team</CardTitle>
          </CardHeader>
          <CardContent className="flex flex-wrap items-end gap-3">
            <Field label="Team">
              <Select value={teamId ?? ''} onValueChange={(v) => setTeamId(v || null)}>
                <SelectTrigger className="w-56"><SelectValue placeholder="Select a team" /></SelectTrigger>
                <SelectContent>
                  <SelectGroup>
                    {teams.map((t) => <SelectItem key={t.id} value={t.id}>{t.name}</SelectItem>)}
                  </SelectGroup>
                </SelectContent>
              </Select>
            </Field>
            {teamId && (
              <Field label="New seat (role)">
                <div className="flex gap-2">
                  <Input value={newSeat} onChange={(e) => setNewSeat(e.target.value)} className="w-48" placeholder="Product Owner" />
                  <Button onClick={createSeat}><Plus data-icon="inline-start" />Create</Button>
                </div>
              </Field>
            )}
          </CardContent>
        </Card>

        {teamId && (
          <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
            <Card>
              <CardHeader>
                <CardTitle className="text-base">Seats</CardTitle>
                <CardDescription>Pick a seat to configure its agent.</CardDescription>
              </CardHeader>
              <CardContent className="flex flex-col gap-2">
                {seats.map((seat) => (
                  <button
                    key={seat.id}
                    onClick={() => selectSeat(seat)}
                    className={cn(
                      'flex items-center justify-between rounded-md border px-3 py-2 text-left text-sm',
                      selectedSeat === seat.id && 'border-indigo-500 ring-1 ring-indigo-500',
                    )}
                  >
                    <span className="font-medium">{seat.roleName}</span>
                    <Badge variant={seat.state === 'Ai' ? 'default' : 'secondary'}>{seat.state}</Badge>
                  </button>
                ))}
                {seats.length === 0 && <p className="text-sm text-muted-foreground">No seats yet.</p>}
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle className="flex items-center gap-2 text-base">
                  <Bot className="size-4" /> Agent
                </CardTitle>
                <CardDescription>
                  {selected ? `Configure “${selected.roleName}”` : 'Select a seat on the left.'}
                </CardDescription>
              </CardHeader>
              {selected && (
                <CardContent className="flex flex-col gap-4">
                  {profiles.length > 0 && (
                    <Field label="Start from a profile (AGENTS.md)">
                      <Select value="" onValueChange={applyProfile}>
                        <SelectTrigger className="w-72"><SelectValue placeholder="Apply an agent profile…" /></SelectTrigger>
                        <SelectContent>
                          <SelectGroup>
                            {profiles.map((p) => <SelectItem key={p.profileKey} value={p.profileKey}>{p.name}</SelectItem>)}
                          </SelectGroup>
                        </SelectContent>
                      </Select>
                    </Field>
                  )}

                  <div className="flex flex-wrap items-end gap-3">
                    <Field label="Name">
                      <Input value={agent.name} onChange={(e) => setAgent({ ...agent, name: e.target.value })} className="w-40" placeholder="Aria" />
                    </Field>
                    <Field label="Monogram">
                      <Input value={agent.monogram} onChange={(e) => setAgent({ ...agent, monogram: e.target.value })} className="w-20" placeholder="AR" />
                    </Field>
                  </div>

                  <div className="flex flex-col gap-2">
                    <Label>Autonomy</Label>
                    <div className="flex gap-2">
                      {AUTONOMY.map((a) => (
                        <button
                          key={a.value}
                          onClick={() => setAgent({ ...agent, autonomy: a.value })}
                          className={cn(
                            'rounded-md border px-3 py-1.5 text-sm',
                            agent.autonomy === a.value ? a.on : 'text-muted-foreground',
                          )}
                        >
                          {a.label}
                        </button>
                      ))}
                    </div>
                  </div>

                  <Field label="Model connection">
                    <Select value={agent.apiConfigId} onValueChange={(v) => setAgent({ ...agent, apiConfigId: v })}>
                      <SelectTrigger className="w-64"><SelectValue placeholder="Pick a connection" /></SelectTrigger>
                      <SelectContent>
                        <SelectGroup>
                          {configs.map((c) => <SelectItem key={c.id} value={c.id}>{c.name} · {c.model}</SelectItem>)}
                        </SelectGroup>
                      </SelectContent>
                    </Select>
                  </Field>

                  <div className="flex flex-col gap-2">
                    <Label>Skills</Label>
                    {selected && (
                      <SuggestedSkills
                        roleName={selected.roleName}
                        skills={skills}
                        current={agent.skillKeys}
                        onApply={(keys) => setAgent({ ...agent, skillKeys: keys })}
                      />
                    )}
                    <div className="flex flex-wrap gap-2">
                      {skills.map((skill) => (
                        <button key={skill.skillKey} onClick={() => toggleSkill(skill.skillKey)} title={skill.status !== 'Published' ? 'Draft — add roles + a golden test to publish before an agent can run it' : undefined}>
                          <Badge variant={agent.skillKeys.includes(skill.skillKey) ? 'default' : 'outline'}>
                            {skill.name}{skill.status !== 'Published' ? ' · draft' : ''}
                          </Badge>
                        </button>
                      ))}
                      {skills.length === 0 && <p className="text-sm text-muted-foreground">No skills indexed yet.</p>}
                    </div>
                  </div>

                  <div className="flex flex-col gap-2">
                    <Label>MCP servers</Label>
                    <div className="flex flex-wrap gap-2">
                      {mcpServers.map((s) => (
                        <button key={s.id} onClick={() => toggleMcp(s.id)} title={s.endpoint}>
                          <Badge variant={agent.mcpServerIds.includes(s.id) ? 'default' : 'outline'}>
                            <Plug className="mr-1 size-3" />{s.name}
                          </Badge>
                        </button>
                      ))}
                      {mcpServers.length === 0 && <p className="text-sm text-muted-foreground">No MCP servers connected — add one above.</p>}
                    </div>
                  </div>

                  <Field label="Docs (comma-separated)">
                    <Input value={agent.docs} onChange={(e) => setAgent({ ...agent, docs: e.target.value })} placeholder="product-docs, house-style" />
                  </Field>

                  <div className="flex flex-col gap-2">
                    <Label>Operating guide (persona)</Label>
                    <textarea
                      value={agent.persona}
                      onChange={(e) => setAgent({ ...agent, persona: e.target.value })}
                      rows={4}
                      placeholder="The agent's persona / operating guide — set by a profile, editable here. Injected into the run."
                      className="w-full resize-y rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50"
                    />
                  </div>

                  <Button onClick={saveAgent} className="self-start">
                    <Wand2 data-icon="inline-start" />
                    Save agent
                  </Button>
                </CardContent>
              )}
            </Card>
          </div>
        )}
      </div>
    </AppShell>
  )
}

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

/** Maps a free-text seat role name to skill role tags — any role can be AI-staffed. */
function roleTagsFor(roleName: string): string[] {
  const n = roleName.toLowerCase()
  const tags: string[] = []
  if (n.includes('product') || n.includes('owner') || n.includes('pm')) tags.push('product-owner')
  if (n.includes('qa') || n.includes('test') || n.includes('quality')) tags.push('qa')
  if (n.includes('engineer') || n.includes('dev') || n.includes('programmer') || n.includes('backend') || n.includes('frontend')) tags.push('engineer')
  if (n.includes('design') || n.includes('ux') || n.includes('ui')) tags.push('designer')
  if (n.includes('analyst') || n.includes('analysis') || n.includes('business')) tags.push('analyst')
  return tags
}

/** Suggests the skill set matching the seat's role — one click staffs any role with AI. */
function SuggestedSkills({
  roleName,
  skills,
  current,
  onApply,
}: {
  roleName: string
  skills: { skillKey: string; name: string; roles: string[] }[]
  current: string[]
  onApply: (keys: string[]) => void
}) {
  const tags = roleTagsFor(roleName)
  const suggested = skills.filter((s) => s.roles.some((r) => tags.includes(r)))
  if (suggested.length === 0) return null

  const keys = suggested.map((s) => s.skillKey)
  const applied = keys.every((k) => current.includes(k))

  return (
    <div className="flex items-center gap-2 rounded-md border border-dashed px-3 py-2 text-xs text-muted-foreground">
      <Sparkles className="size-3.5 shrink-0 text-primary" />
      <span className="min-w-0 truncate">
        Suggested for “{roleName}”: {suggested.map((s) => s.name).join(', ')}
      </span>
      <Button
        variant="outline"
        size="sm"
        className="ml-auto shrink-0"
        disabled={applied}
        onClick={() => onApply([...new Set([...current, ...keys])])}
      >
        {applied ? 'Applied' : 'Use set'}
      </Button>
    </div>
  )
}
