import { useCallback, useEffect, useMemo, useState } from 'react'
import { BookMarked, Download, Eye, GitFork, Pencil, Plus, Store, Trash2, Upload } 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 { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@/components/ui/sheet'
import { Textarea } from '@/components/ui/textarea'
import { MarkdownEditor } from '@/components/MarkdownEditor'
import { api } from '@/lib/api'
import { bumpPatch } from '@/lib/semver'
import { groupVersions } from '@/lib/versionedLibrary'
import { useAuth } from '@/store/auth'

interface ActionDto {
  name: string
  risk: string
  description?: string | null
}

interface GoldenTest {
  input: string
  expected: string
}

interface SkillSummary {
  id: string
  skillKey: string
  name: string
  version: string
  summary: string | null
  roles: string[]
  visibility: string
  minTier: string
  status: string
  origin: string
  organizationId: string | null
  goldenTestCount: number
  actions: ActionDto[]
}

interface SkillDetail {
  skill: SkillSummary
  inputs: string | null
  outputs: string | null
  tools: string[]
  context: string[]
  goldenTests: GoldenTest[]
  body: string
}

interface MarketplaceEntry {
  skill: SkillSummary
  alreadyInLibrary: boolean
}

type Mode = 'new' | 'version' | 'edit'

interface FormState {
  mode: Mode
  skillKey: string
  name: string
  version: string
  summary: string
  roles: string
  inputs: string
  outputs: string
  tools: string
  context: string
  visibility: string
  minTier: string
  body: string
  actions: ActionDto[]
  goldenTests: GoldenTest[]
}

const COMMON_ROLES = 'product-owner, engineer, qa, designer, analyst'
const RISKS = ['read', 'draft', 'publish', 'destructive']
const VISIBILITIES = ['public', 'private']
const TIERS = ['free', 'team', 'scale', 'enterprise']

const emptyForm = (): FormState => ({
  mode: 'new',
  skillKey: '',
  name: '',
  version: '1.0.0',
  summary: '',
  roles: '',
  inputs: '',
  outputs: '',
  tools: '',
  context: '',
  visibility: 'private',
  minTier: 'free',
  body: '',
  actions: [],
  goldenTests: [],
})

const csv = (s: string): string[] =>
  s.split(',').map((x) => x.trim()).filter(Boolean)

/** Reconstruct a readable SKILL.md (frontmatter + prompt body + actions/golden tests) for the viewer. */
function skillToMarkdown(d: SkillDetail): string {
  const s = d.skill
  const fm = [
    `id: ${s.skillKey}`,
    `name: ${s.name}`,
    `version: ${s.version}`,
    s.summary ? `summary: ${s.summary}` : null,
    s.roles.length ? `roles: [${s.roles.join(', ')}]` : null,
    d.inputs ? `inputs: ${d.inputs}` : null,
    d.outputs ? `outputs: ${d.outputs}` : null,
    d.tools.length ? `tools: [${d.tools.join(', ')}]` : null,
    d.context.length ? `context: [${d.context.join(', ')}]` : null,
    `visibility: ${s.visibility === 'PrivateToOrg' ? 'private' : 'public'}`,
    `min_tier: ${s.minTier.toLowerCase()}`,
  ].filter(Boolean)
  const actions = s.actions.length
    ? `\n\n## Actions\n${s.actions.map((a) => `- **${a.name}** (${a.risk.toLowerCase()})${a.description ? ` — ${a.description}` : ''}`).join('\n')}`
    : ''
  const golden = d.goldenTests.length
    ? `\n\n## Golden tests\n${d.goldenTests.map((g, i) => `${i + 1}. input: \`${g.input}\` → expected: ${g.expected}`).join('\n')}`
    : ''
  return `---\n${fm.join('\n')}\n---\n\n${d.body}${actions}${golden}`
}

/** The org's skill library: builtin starter skills + skills the company authors and versions itself. */
export function SkillsPage() {
  const organizationId = useAuth((s) => s.organizationId)
  const [tab, setTab] = useState<'library' | 'marketplace'>('library')
  const [skills, setSkills] = useState<SkillSummary[]>([])
  const [marketplace, setMarketplace] = useState<MarketplaceEntry[]>([])
  const [form, setForm] = useState<FormState | null>(null)
  const [preview, setPreview] = useState<{ title: string; content: string } | null>(null)
  const [busy, setBusy] = useState(false)

  const load = useCallback(async () => {
    if (!organizationId) return
    try {
      const [lib, market] = await Promise.all([
        api.get<SkillSummary[]>(`/api/skills?organizationId=${organizationId}`),
        api.get<MarketplaceEntry[]>(`/api/skills/marketplace?organizationId=${organizationId}`),
      ])
      setSkills(lib)
      setMarketplace(market)
    } catch (err) {
      toast.error((err as Error).message)
    }
  }, [organizationId])

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

  // Group every version under its key (org-owned shadows a same-version builtin). See groupVersions.
  const groups = useMemo(() => groupVersions(skills, (s) => s.skillKey), [skills])

  // Read-only details: reconstruct the SKILL.md and render it. Works for builtins too — inspect a
  // skill (frontmatter, prompt body, actions, golden tests) without forking or versioning it.
  const openView = async (key: string, version: string) => {
    try {
      const details = await api.get<SkillDetail[]>(`/api/skills/${key}?organizationId=${organizationId}`)
      const d = details.find((x) => x.skill.version === version) ?? details[0]
      if (!d) return
      setPreview({ title: `${d.skill.name} · ${d.skill.version}`, content: skillToMarkdown(d) })
    } catch (err) {
      toast.error((err as Error).message)
    }
  }

  const openForm = async (key: string, version: string, mode: Mode) => {
    try {
      const details = await api.get<SkillDetail[]>(`/api/skills/${key}?organizationId=${organizationId}`)
      const d = details.find((x) => x.skill.version === version) ?? details[0]
      if (!d) return
      setForm({
        mode,
        skillKey: d.skill.skillKey,
        name: d.skill.name,
        version: mode === 'version' ? bumpPatch(d.skill.version) : d.skill.version,
        summary: d.skill.summary ?? '',
        roles: d.skill.roles.join(', '),
        inputs: d.inputs ?? '',
        outputs: d.outputs ?? '',
        tools: d.tools.join(', '),
        context: d.context.join(', '),
        visibility: d.skill.visibility === 'PrivateToOrg' ? 'private' : 'public',
        minTier: d.skill.minTier.toLowerCase(),
        body: d.body,
        actions: d.skill.actions.map((a) => ({ name: a.name, risk: a.risk.toLowerCase(), description: a.description ?? '' })),
        goldenTests: d.goldenTests.map((g) => ({ ...g })),
      })
    } catch (err) {
      toast.error((err as Error).message)
    }
  }

  const fork = async (key: string, version: string) => {
    setBusy(true)
    try {
      await api.post(`/api/skills/${key}/fork`, { organizationId, version })
      toast.success(`Forked ${key} into your org — edit it to customize.`)
      await load()
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setBusy(false)
    }
  }

  const setListed = async (key: string, version: string, listed: boolean) => {
    setBusy(true)
    try {
      await api.post(`/api/skills/${key}/${listed ? 'publish' : 'unpublish'}`, { organizationId, version })
      toast.success(listed ? `Published ${key}@${version} to the marketplace.` : `Unlisted ${key}@${version}.`)
      await load()
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setBusy(false)
    }
  }

  const install = async (sourceSkillId: string, name: string) => {
    setBusy(true)
    try {
      await api.post('/api/skills/install', { organizationId, sourceSkillId })
      toast.success(`Installed ${name} into your library.`)
      await load()
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setBusy(false)
    }
  }

  const save = async () => {
    if (!form) return
    setBusy(true)
    try {
      await api.post('/api/skills/authored', {
        organizationId,
        skillKey: form.skillKey.trim(),
        name: form.name.trim(),
        version: form.version.trim(),
        summary: form.summary.trim() || null,
        roles: csv(form.roles),
        inputs: form.inputs.trim() || null,
        outputs: form.outputs.trim() || null,
        tools: csv(form.tools),
        context: csv(form.context),
        visibility: form.visibility,
        minTier: form.minTier,
        body: form.body,
        actions: form.actions
          .filter((a) => a.name.trim())
          .map((a) => ({ name: a.name.trim(), risk: a.risk, description: a.description?.trim() || null })),
        goldenTests: form.goldenTests.filter((g) => g.input.trim() && g.expected.trim()),
      })
      toast.success(`Saved ${form.skillKey}@${form.version}.`)
      setForm(null)
      await load()
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setBusy(false)
    }
  }

  const willPublish = !!form && csv(form.roles).length > 0 && form.goldenTests.some((g) => g.input.trim() && g.expected.trim())

  return (
    <AppShell>
      <div className="mx-auto max-w-5xl p-6">
        <header className="mb-6 flex items-start justify-between gap-4">
          <div>
            <h1 className="flex items-center gap-2 text-2xl font-semibold tracking-tight">
              <BookMarked className="size-6" /> Skills
            </h1>
            <p className="text-sm text-muted-foreground">
              Your company's skill library. Builtin starter skills are shared; author and version your own.
            </p>
          </div>
          <Button onClick={() => setForm(emptyForm())}>
            <Plus data-icon="inline-start" /> New skill
          </Button>
        </header>

        <div className="mb-4 inline-flex rounded-lg border p-1">
          <SegBtn active={tab === 'library'} onClick={() => setTab('library')} icon={BookMarked}>Library</SegBtn>
          <SegBtn active={tab === 'marketplace'} onClick={() => setTab('marketplace')} icon={Store}>Marketplace</SegBtn>
        </div>

        {tab === 'library' ? (
          <div className="flex flex-col gap-4">
            {groups.map(([key, versions]) => (
              <SkillGroupCard
                key={key}
                versions={versions}
                busy={busy}
                onView={(v) => openView(key, v)}
                onNewVersion={(v) => openForm(key, v, 'version')}
                onEdit={(v) => openForm(key, v, 'edit')}
                onFork={(v) => fork(key, v)}
                onPublish={(v) => setListed(key, v, true)}
                onUnpublish={(v) => setListed(key, v, false)}
              />
            ))}
            {groups.length === 0 && (
              <p className="text-sm text-muted-foreground">No skills yet. Run a Git sync for builtins, or author one.</p>
            )}
          </div>
        ) : (
          <div className="flex flex-col gap-4">
            <p className="text-sm text-muted-foreground">
              Published skills shared by other organizations. Install a copy into your library — it lands private,
              so you can edit or version it freely.
            </p>
            {marketplace.map(({ skill: s, alreadyInLibrary }) => (
              <Card key={s.id}>
                <CardHeader className="pb-3">
                  <CardTitle className="flex items-center gap-2 text-base">
                    {s.name} <Badge variant="outline">{s.version}</Badge>
                    <span className="font-mono text-xs text-muted-foreground">{s.skillKey}</span>
                  </CardTitle>
                  <CardDescription>{s.summary}</CardDescription>
                </CardHeader>
                <CardContent className="flex flex-wrap items-center gap-2">
                  {s.roles.map((r) => <Badge key={r} variant="secondary">{r}</Badge>)}
                  <span className="text-xs text-muted-foreground">
                    {s.goldenTestCount} golden test{s.goldenTestCount === 1 ? '' : 's'}
                  </span>
                  {alreadyInLibrary ? (
                    <Badge variant="secondary" className="ml-auto">In your library</Badge>
                  ) : (
                    <Button size="sm" disabled={busy} className="ml-auto" onClick={() => install(s.id, s.name)}>
                      <Download data-icon="inline-start" /> Install
                    </Button>
                  )}
                </CardContent>
              </Card>
            ))}
            {marketplace.length === 0 && (
              <p className="text-sm text-muted-foreground">
                Nothing published yet. Publish one of your own skills to share it here.
              </p>
            )}
          </div>
        )}
      </div>

      {form && (
        <Sheet open onOpenChange={(o) => !o && setForm(null)}>
          <SheetContent className="flex w-full flex-col gap-0 overflow-y-auto sm:max-w-xl">
            <SheetHeader>
              <SheetTitle>
                {form.mode === 'new' ? 'New skill' : form.mode === 'version' ? `New version of ${form.skillKey}` : `Edit ${form.skillKey}`}
              </SheetTitle>
              <SheetDescription>
                {willPublish
                  ? 'Has roles + a golden test — saves as Published.'
                  : 'Add ≥1 role and ≥1 golden test to publish; otherwise saved as Draft.'}
              </SheetDescription>
            </SheetHeader>

            <div className="flex flex-col gap-4 px-4 pb-6">
              <div className="grid grid-cols-2 gap-3">
                <Field label="Skill key (id)">
                  <Input
                    value={form.skillKey}
                    disabled={form.mode !== 'new'}
                    onChange={(e) => setForm({ ...form, skillKey: e.target.value })}
                    placeholder="api-endpoint-design"
                  />
                </Field>
                <Field label="Version">
                  <Input value={form.version} disabled={form.mode === 'edit'} onChange={(e) => setForm({ ...form, version: e.target.value })} />
                </Field>
              </div>
              <Field label="Name">
                <Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="API Endpoint Design" />
              </Field>
              <Field label="Summary">
                <Input value={form.summary} onChange={(e) => setForm({ ...form, summary: e.target.value })} />
              </Field>
              <Field label={`Roles (comma-separated — e.g. ${COMMON_ROLES})`}>
                <Input value={form.roles} onChange={(e) => setForm({ ...form, roles: e.target.value })} placeholder="engineer" />
              </Field>
              <div className="grid grid-cols-2 gap-3">
                <Field label="Inputs">
                  <Input value={form.inputs} onChange={(e) => setForm({ ...form, inputs: e.target.value })} />
                </Field>
                <Field label="Outputs">
                  <Input value={form.outputs} onChange={(e) => setForm({ ...form, outputs: e.target.value })} />
                </Field>
              </div>
              <div className="grid grid-cols-2 gap-3">
                <Field label="Visibility">
                  <Pick value={form.visibility} options={VISIBILITIES} onChange={(v) => setForm({ ...form, visibility: v })} />
                </Field>
                <Field label="Min tier">
                  <Pick value={form.minTier} options={TIERS} onChange={(v) => setForm({ ...form, minTier: v })} />
                </Field>
              </div>
              <div className="grid grid-cols-2 gap-3">
                <Field label="Tools (comma-separated)">
                  <Input value={form.tools} onChange={(e) => setForm({ ...form, tools: e.target.value })} />
                </Field>
                <Field label="Context docs (comma-separated)">
                  <Input value={form.context} onChange={(e) => setForm({ ...form, context: e.target.value })} />
                </Field>
              </div>

              <Repeater
                label="Actions (risk-tagged)"
                onAdd={() => setForm({ ...form, actions: [...form.actions, { name: '', risk: 'draft', description: '' }] })}
              >
                {form.actions.map((a, i) => (
                  <div key={i} className="flex items-center gap-2">
                    <Input
                      className="flex-1" placeholder="action name" value={a.name}
                      onChange={(e) => setForm({ ...form, actions: form.actions.map((x, j) => (j === i ? { ...x, name: e.target.value } : x)) })}
                    />
                    <Pick
                      value={a.risk} options={RISKS} className="w-32"
                      onChange={(v) => setForm({ ...form, actions: form.actions.map((x, j) => (j === i ? { ...x, risk: v } : x)) })}
                    />
                    <Button size="icon" variant="ghost" onClick={() => setForm({ ...form, actions: form.actions.filter((_, j) => j !== i) })}>
                      <Trash2 className="size-4" />
                    </Button>
                  </div>
                ))}
              </Repeater>

              <Repeater
                label="Golden tests (gate publishing)"
                onAdd={() => setForm({ ...form, goldenTests: [...form.goldenTests, { input: '', expected: '' }] })}
              >
                {form.goldenTests.map((g, i) => (
                  <div key={i} className="flex flex-col gap-2 rounded-md border p-2">
                    <div className="flex items-center gap-2">
                      <Input
                        className="flex-1" placeholder="input" value={g.input}
                        onChange={(e) => setForm({ ...form, goldenTests: form.goldenTests.map((x, j) => (j === i ? { ...x, input: e.target.value } : x)) })}
                      />
                      <Button size="icon" variant="ghost" onClick={() => setForm({ ...form, goldenTests: form.goldenTests.filter((_, j) => j !== i) })}>
                        <Trash2 className="size-4" />
                      </Button>
                    </div>
                    <Textarea
                      rows={2} placeholder="expected output" value={g.expected}
                      onChange={(e) => setForm({ ...form, goldenTests: form.goldenTests.map((x, j) => (j === i ? { ...x, expected: e.target.value } : x)) })}
                    />
                  </div>
                ))}
              </Repeater>

              <Field label="Body (the prompt the agent runs)">
                <MarkdownEditor
                  rows={8}
                  value={form.body}
                  onChange={(body) => setForm({ ...form, body })}
                  placeholder="You are the engineer. Turn the input into…"
                />
              </Field>

              <div className="flex items-center justify-end gap-2">
                <Button variant="ghost" onClick={() => setForm(null)}>Cancel</Button>
                <Button disabled={busy || !form.skillKey.trim() || !form.name.trim() || !form.body.trim()} onClick={save}>
                  Save {willPublish ? '& publish' : 'draft'}
                </Button>
              </div>
            </div>
          </SheetContent>
        </Sheet>
      )}

      {preview && (
        <Sheet open onOpenChange={(o) => !o && setPreview(null)}>
          <SheetContent className="flex w-full flex-col gap-0 overflow-y-auto sm:max-w-xl">
            <SheetHeader>
              <SheetTitle>{preview.title}</SheetTitle>
              <SheetDescription>The full SKILL.md — read-only. Fork or make a new version to edit.</SheetDescription>
            </SheetHeader>
            <div className="flex flex-col gap-4 px-4 pb-6">
              <MarkdownEditor rows={20} mono frontmatter value={preview.content} />
            </div>
          </SheetContent>
        </Sheet>
      )}
    </AppShell>
  )
}

function SkillGroupCard({
  versions,
  busy,
  onView,
  onNewVersion,
  onEdit,
  onFork,
  onPublish,
  onUnpublish,
}: {
  versions: SkillSummary[]
  busy: boolean
  onView: (version: string) => void
  onNewVersion: (version: string) => void
  onEdit: (version: string) => void
  onFork: (version: string) => void
  onPublish: (version: string) => void
  onUnpublish: (version: string) => void
}) {
  const [selected, setSelected] = useState(versions[0].version)
  const current = versions.find((v) => v.version === selected) ?? versions[0]
  const isBuiltin = current.origin === 'Builtin'
  const isListed = current.visibility === 'Public'
  const canPublish = !isBuiltin && current.status === 'Published'

  return (
    <Card>
      <CardHeader className="pb-3">
        <div className="flex items-start justify-between gap-3">
          <div>
            <CardTitle className="flex items-center gap-2 text-base">
              {current.name}
              <span className="font-mono text-xs text-muted-foreground">{current.skillKey}</span>
            </CardTitle>
            <CardDescription className="mt-1">{current.summary}</CardDescription>
          </div>
          <div className="flex items-center gap-2">
            <Badge variant={current.status === 'Published' ? 'default' : 'secondary'}>{current.status}</Badge>
            <Badge variant="outline">{current.origin}</Badge>
          </div>
        </div>
      </CardHeader>
      <CardContent className="flex flex-wrap items-center gap-2">
        {versions.length > 1 ? (
          <Pick value={selected} options={versions.map((v) => v.version)} className="w-28" onChange={setSelected} />
        ) : (
          <Badge variant="outline">{current.version}</Badge>
        )}
        {current.roles.map((r) => <Badge key={r} variant="secondary">{r}</Badge>)}
        <span className="text-xs text-muted-foreground">{current.goldenTestCount} golden test{current.goldenTestCount === 1 ? '' : 's'}</span>
        {isListed && <Badge variant="default" className="gap-1"><Store className="size-3" /> Listed</Badge>}

        <div className="ml-auto flex items-center gap-2">
          <Button size="sm" variant="ghost" onClick={() => onView(current.version)}>
            <Eye data-icon="inline-start" /> View
          </Button>
          {isBuiltin ? (
            <Button size="sm" variant="outline" disabled={busy} onClick={() => onFork(current.version)}>
              <GitFork data-icon="inline-start" /> Fork to my org
            </Button>
          ) : (
            <>
              <Button size="sm" variant="outline" disabled={busy} onClick={() => onEdit(current.version)}>
                <Pencil data-icon="inline-start" /> Edit
              </Button>
              {isListed ? (
                <Button size="sm" variant="outline" disabled={busy} onClick={() => onUnpublish(current.version)}>
                  Unlist
                </Button>
              ) : canPublish ? (
                <Button size="sm" variant="outline" disabled={busy} onClick={() => onPublish(current.version)}>
                  <Upload data-icon="inline-start" /> Publish
                </Button>
              ) : null}
            </>
          )}
          <Button size="sm" disabled={busy} onClick={() => onNewVersion(current.version)}>
            <Plus data-icon="inline-start" /> New version
          </Button>
        </div>
      </CardContent>
    </Card>
  )
}

function SegBtn({ active, onClick, icon: Icon, children }: { active: boolean; onClick: () => void; icon: typeof BookMarked; children: React.ReactNode }) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition ${active ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:text-foreground'}`}
    >
      <Icon className="size-4" /> {children}
    </button>
  )
}

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>
  )
}

function Pick({ value, options, onChange, className }: { value: string; options: string[]; onChange: (v: string) => void; className?: string }) {
  return (
    <Select value={value} onValueChange={onChange}>
      <SelectTrigger className={className ?? 'w-full'}><SelectValue /></SelectTrigger>
      <SelectContent>
        <SelectGroup>
          {options.map((o) => <SelectItem key={o} value={o}>{o}</SelectItem>)}
        </SelectGroup>
      </SelectContent>
    </Select>
  )
}

function Repeater({ label, onAdd, children }: { label: string; onAdd: () => void; children: React.ReactNode }) {
  return (
    <div className="flex flex-col gap-2">
      <div className="flex items-center justify-between">
        <Label className="text-xs">{label}</Label>
        <Button size="sm" variant="ghost" onClick={onAdd}><Plus data-icon="inline-start" /> Add</Button>
      </div>
      {children}
    </div>
  )
}
